/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/helpers/serversocket.h>
#include "apr_network_io.h"
#include "apr_pools.h"
#include "apr_poll.h"

using namespace log4cxx::helpers;

/**  Creates a server socket on a specified port.
*/
ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
{
	apr_status_t status =
		apr_socket_create(&socket, APR_INET, SOCK_STREAM,
			APR_PROTO_TCP, pool.getAPRPool());

	if (status != APR_SUCCESS)
	{
		throw SocketException(status);
	}

	status = apr_socket_opt_set(socket, APR_SO_NONBLOCK, 1);

	if (status != APR_SUCCESS)
	{
		throw SocketException(status);
	}

	// Create server socket address (including port number)
	apr_sockaddr_t* server_addr;
	status =
		apr_sockaddr_info_get(&server_addr, NULL, APR_INET,
			port, 0, pool.getAPRPool());

	if (status != APR_SUCCESS)
	{
		throw ConnectException(status);
	}

	// bind the socket to the address
	status = apr_socket_bind(socket, server_addr);

	if (status != APR_SUCCESS)
	{
		throw BindException(status);
	}


	status = apr_socket_listen(socket, 50);

	if (status != APR_SUCCESS)
	{
		throw SocketException(status);
	}
}


ServerSocket::~ServerSocket()
{
}

void ServerSocket::close()
{
	log4cxx::unique_lock<log4cxx::mutex> lock(mutex);

	if (socket != 0)
	{
		apr_status_t status = apr_socket_close(socket);

		if (status != APR_SUCCESS)
		{
			throw SocketException(status);
		}

		socket = 0;
	}
}

/** Listens for a connection to be made to this socket and
accepts it
*/
SocketPtr ServerSocket::accept()
{
	log4cxx::unique_lock<log4cxx::mutex> lock(mutex);

	if (socket == 0)
	{
		throw IOException();
	}

	apr_pollfd_t poll;
	poll.p = pool.getAPRPool();
	poll.desc_type = APR_POLL_SOCKET;
	poll.reqevents = APR_POLLIN;
	poll.rtnevents = 0;
	poll.desc.s = socket;
	poll.client_data = NULL;

	apr_int32_t signaled;
	apr_interval_time_t to = timeout * 1000;
	apr_status_t status = apr_poll(&poll, 1, &signaled, to);

	if (APR_STATUS_IS_TIMEUP(status))
	{
		throw SocketTimeoutException();
	}
	else if (status != APR_SUCCESS)
	{
		throw SocketException(status);
	}

	apr_pool_t* newPool;
	status = apr_pool_create(&newPool, 0);

	if (status != APR_SUCCESS)
	{
		throw PoolException(status);
	}

	apr_socket_t* newSocket;
	status = apr_socket_accept(&newSocket, socket, newPool);

	if (status != APR_SUCCESS)
	{
		apr_pool_destroy(newPool);
		throw SocketException(status);
	}

	status = apr_socket_opt_set(newSocket, APR_SO_NONBLOCK, 0);

	if (status != APR_SUCCESS)
	{
		apr_pool_destroy(newPool);
		throw SocketException(status);
	}

    return SocketPtr(new Socket(newSocket, newPool));
}

/** Retrive setting for SO_TIMEOUT.
*/
int ServerSocket::getSoTimeout() const
{
	return timeout;
}

/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
*/
void ServerSocket::setSoTimeout(int newVal)
{
	timeout = newVal;
}
