/*
 * @(#)ServerSocket.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 *
 * Jörg Haeger, 19.04.2002
 */

#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "Exception.h"
#include "Log.h"
#include "Socket.h"
#include "ServerSocket.h"

ServerSocket::ServerSocket(int port) {
	this->port = port;

	sock = socket(PF_INET, SOCK_STREAM, 0);
	if (sock < 0)
		throw new Exception("socket() failed");

	int on = 1;
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
		(void *)&on, sizeof on) == -1)
		log.put(1, S.e + "set SO_REUSEADDR: errno = " + errno
			+ " <" + strerror(errno) + ">");
	else
		log.put(1, S.e + "SO_REUSEADDR activated");

	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	addr.sin_port = htons(port);
	int i;
	for (i = 0; i < 10 * 60; i++) {
		if (bind(sock, (struct sockaddr *)&addr, sizeof addr) == 0)
			break;
		sleep(1);
	}
	if (i == 10 * 60)
		throw new Exception(S.e + "cannot bind socket to port " + port);

	if (listen(sock, 5) != 0)
		throw new Exception("listen() failed");
}

ServerSocket::~ServerSocket() {
}

Socket *ServerSocket::accept() {
	struct sockaddr_in clientAddr;
	unsigned int clientAddrLength = sizeof(clientAddr);
	int clientSocket = ::accept(sock,
		(struct sockaddr *)&clientAddr, &clientAddrLength);
	if(clientSocket < 0)
		throw new Exception(S.e + "accept() failed on port " + port);

	return new Socket(clientSocket);
}
