/*************************************************************************************************************
* This file contains start/stop server function
* 2012/8 by Dlxko
* Version 3.0
**************************************************************************************************************/
#include "StartStopServer.h"

// Winsock data
static WSADATA wsaData;

// Results
static int result;
static int i;

// For non-blocking
static unsigned long b = 1;

// Adress structures
static sockaddr_in	server_address;
static sockaddr  	server_socket_address;

// Just small counter
static int counter;

// Function to start server
void function_start_server()
{
	// Structures
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = INADDR_ANY;
	server_address.sin_port = htons ( PORT);

	// Just copy adress
	memcpy ( &server_socket_address, &server_address, sizeof ( SOCKADDR_IN ) );

	// Start WinSock or report error
	result = WSAStartup (MAKEWORD(1,1), &wsaData);
	if (result == WSASYSNOTREADY)
		function_showgtk_fatal("WSA Startup - he underlying network subsystem is not ready for network communication.");
	else if (result == WSAVERNOTSUPPORTED)
		function_showgtk_fatal("WSA Startup - The version of Windows Sockets support requested is not provided by this particular Windows Sockets implementation.");
	else if (result == WSAEINPROGRESS)
		function_showgtk_fatal("WSA Startup - A blocking Windows Sockets 1.1 operation is in progress.");
	else if (result == WSAEPROCLIM)
		function_showgtk_fatal("WSA Startup - A limit on the number of tasks supported by the Windows Sockets implementation has been reached.");
	else if (result == WSAEFAULT)
		function_showgtk_fatal("WSA Startup - The lpWSAData parameter is not a valid pointer.");

	// If sucess print it
	function_show_ready("WSA Startup - success!");

	// Create socket or report errors
	server_socket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if (server_socket == INVALID_SOCKET || server_socket == SOCKET_ERROR)
	{
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "WSA Socket - Failed to create socket with error %d", WSAGetLastError());
		function_showgtk_fatal(warnings_tmp);
	}
	function_show_ready("WSA Socket - success!");

	// Sets the option to re-use the address the entire run of the program
	//setsockopt (server_socket, SOL_SOCKET, SO_REUSEADDR, ( char * ) &i, sizeof ( i ) );

	// Bind the socket to the address
	result = bind ( server_socket, &server_socket_address, sizeof (server_socket_address) );
	if ( result != 0 )
	{
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "WSA Bind - Failed to bind with error %d", WSAGetLastError());
		function_showgtk_fatal(warnings_tmp);
	}
	function_show_ready("WSA Bind - success!");

	// Start listening for connection requests
	result = listen (server_socket, SOMAXCONN);
	if ( result != 0 )
	{
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "WSA Listen - Failed to listen with error %d", WSAGetLastError());
		function_showgtk_fatal(warnings_tmp);
	}
	function_show_ready("WSA Listen - success!");

	// Clean structure
	counter = RESET;
	do
	{
		client[counter].connected = false;
		client[counter].client_acess = RESET;
		client[counter].client_event_id = RESET;
		client[counter].return_value = RESET;
		client[counter].socket = RESET;
		memset(client[counter].nick_name, 0, DATA_ONE_SIZE);
		++counter;
	}
	while (counter < MAX_CLIENTS);
	function_show_ready("Client structure cleaned!");

	// This makes the server non blocking, hence it won't wait for a response
	ioctlsocket ( server_socket, FIONBIO, &b );
	function_show_ready("WSA Ioctlsocket - Set to non-blocking!");

	// Create server channel with watchdog
	if(!create_server_channel())
		function_showgtk_fatal("Channel - Can't create server channnel!");
}

// Function to exit server
void signal_end_server()
{
	//Disconect all clients
	counter = RESET;
	do
	{
		if(client[counter].connected || client[counter].socket != 0)
		{
			function_disconnect_client(&client[counter]);
			++counter;
		}
		else
			++counter;
	}
	while (counter < MAX_CLIENTS);

	// Close server listening socket
	closesocket (server_socket);

	// Clean WinSock2
	WSACleanup();

	// Write msg, sleep and exit
	exit(0);
}