main_server.cpp 3.16 KB
/** @file 
* \brief Implementación del servidor
* \author Imanol Barba Sabariego
* \date 13/06/2013
*
* En este fichero se implementa un servidor TCP/IP usando las clases Socket y Server.
*/
#include "server.h"
#include <sys/types.h> 
#include <unistd.h>
#include <sstream>

//!Instancia de la clase Server
/*! Esta variable contiene la instancia de la clase Server que aquí se usa e 
inicializa.

_Se trata de una variable global para poder así usarla en las funciones que reciban signals del SO._ */
Server *serv;

void killThread(thread_args *t_arg)
{
	(t_arg->s)->Close();
	pthread_mutex_lock(t_arg->mutex);
	t_arg->serv->setNWorkers(t_arg->serv->getNWorkers()-1);
	cout << "TCP: Worker " << t_arg->id << ": connection terminated" << endl;
	pthread_mutex_unlock(t_arg->mutex);
	pthread_cond_signal(t_arg->condition);
	t_arg->serv->getStartedThreads()->remove(t_arg->thread);
	t_arg->serv->getStoppedThreads()->push_back(t_arg->thread);
	if(t_arg->s != 0)
	{
		delete t_arg->s;
		t_arg->s = 0;
	}
	if(t_arg != 0)
	{
		delete t_arg;
		t_arg = 0;
	}
	pthread_exit(NULL);
}

void *WorkerThread(void* args)
{
	struct thread_args *t_arg = (struct thread_args*)args;
	try
	{
		while(true)
		{
			string message;
			*(t_arg->s) >> message;
			if(message == "exit")
			{
				*(t_arg->s) << "OK";
				break;
			}
			else if(message == "test")
			{
				string data;
				*(t_arg->s) >> data;
				cout << "TCP: Received " << data.length() << " bytes" << endl;
				*(t_arg->s) << "ACK";
			}
			else
			{
				cout << "TCP: Worker " << t_arg->id << " received: " << message << endl;
				string send = "You said: ";
				send += message;
				*(t_arg->s) << send;
			}
		}
	}
	catch(SocketException& e)
	{
		cout << e.description() << endl;
		cout << "TCP: Client closed the connection unexpectedly" << endl;
	}
	killThread(t_arg);
}

//! Método de detención del servidor
/*! Este método detiene el servidor al recibir el signal SIGINT del SO. */
void stopServer(int signal/*!<Parámetro que captura el signal recibido*/)
{
	serv->requestExit();
}

void processText(string *str)
{
	for(int i = 0; i < str->length(); i++)
	{
		if((*str)[i] == 32 || (*str)[i] == 10 || (*str)[i] == 11)
		{
			str->erase(i--,1);
		}
	}
}

bool readConf(string *ip, int *port)
{
	*ip = "";
	*port = 0;
	ifstream confFile;
	confFile.open(CONFFILE);
	if(!confFile.is_open())
	{
		cout << "TCP: Error opening configuration file" << endl;
		return false;
	}
	string parameter;
	while(true)
	{
		getline(confFile, parameter, '=');
		processText(&parameter);
		if(confFile.eof())
		{
			break;
		}
		if(parameter == "bind-ip")
		{
			confFile >> *ip;
		}
		else if(parameter == "port")
		{
			confFile >> *port;
		}
	}
	confFile.close();
	if(*ip == "" || *port == 0)
	{
		return false;
	}
	return true;
}

//! Método principal del servidor
/*! Lee la configuración usando readConf() y incializa el servidor. */
int main()
{
	stringstream sstream;
	string ip;
	int port;
	serv = new Server();
	signal(SIGINT, stopServer);
	if(!readConf(&ip,&port))
	{
		cout << "TCP: Configuration couldn't be loaded" << endl;
		return -1;
	}
	serv->startServer(ip,port);
	delete serv;
	return 0;
}

/* TO-DO
 *
 * Request nick
 * map with sockets/nicks
 * spawn a messagesend thread
 */