server.cpp 2.59 KB
/** @file 
* \brief Fichero de implementación de la clase Server
* \author Imanol Barba Sabariego
* \date 13/06/2013
*
* En este fichero se implementan los métodos de la clase Server definidos en server.h
*/
#include "server.h"

using namespace std;

int Server::getNWorkers()
{
	return nWorkers;
}

void Server::setNWorkers(int n)
{
	nWorkers = n;
}

list<pthread_t*>* Server::getStartedThreads()
{
	return &startedThreads;
}
list<pthread_t*>* Server::getStoppedThreads()
{
	return &stoppedThreads;
}

void Server::freeRAM(list<pthread_t*> *threadList)
{
	int count = 0;
	for(list<pthread_t*>::iterator it = threadList->begin(); it != threadList->end(); it++)
	{
		if(*it != 0)
		{
			delete *it;
			*it = 0;
		}
		count++;
	}
	threadList->clear();
	cout << "TCP: " << count << " Threads freed" << endl;
}

void Server::requestExit()
{
	cout << "TCP: Exiting!" << endl;
	shutdownServer = true;
	ss.Close();
}

void Server::startServer(string i, int p)
{
	Socket ss;
	ss.loadKeys(PUBLICKEY,PRIVATEKEY);
	string ip = i;
	int port = p;
	signal(SIGPIPE, SIG_IGN);
	try
	{
		int optval = 1;
		ss.Create();
		setsockopt(ss.getSock(),SOL_SOCKET,SO_REUSEADDR,&optval,sizeof optval);
		ss.Bind(ip,port);
	}
	catch(SocketException& e)
	{
		cout << e.description() << endl;
		return;
	}
	pthread_mutex_t m_mutex;
	pthread_mutex_init(&m_mutex,0);
	pthread_cond_t condition;
	pthread_cond_init(&condition,0);
	ss.Listen(N);

	while(!shutdownServer)
	{
		pthread_mutex_lock(&m_mutex);
		while(nWorkers >= N)
		{
			cout << "TCP: Server sleeping" << endl;
			pthread_cond_wait(&condition,&m_mutex);
		}
		freeRAM(&stoppedThreads);
		pthread_mutex_unlock(&m_mutex);
		Socket *cs = new Socket();
		try
		{
			ss.Accept(*cs);
		}
		catch(SocketException& e)
		{
			break;
		}
		pthread_mutex_lock(&m_mutex);
		cs->setKeys(ss.getPublicKey(), ss.getPrivateKey(), ss.getAESKey(), ss.getAESIV());
		if(!cs->sendPublicKey() || !cs->receivePublicKey())
		{
			cs->Close();
			if(cs != 0)
			{
				delete cs;
				cs = 0;
			}
			pthread_mutex_unlock(&m_mutex);
			continue;
		}
		cs->sendAES();
		cs->recvAES();
		thread_args *t_args = new thread_args;
		pthread_t *thread = new pthread_t;
		t_args->mutex = &m_mutex;
		t_args->condition = &condition;
		t_args->id = workerID++;
		t_args->s = cs;
		t_args->serv = this;
		t_args->thread = thread;
		startedThreads.push_back(thread);
		cout << "TCP: Client connected" << endl;
		nWorkers++;
		pthread_create(thread,NULL,WorkerThread,(void *)t_args);
		pthread_mutex_unlock(&m_mutex);
	}
	cout << "TCP: Running Threads:" << endl;
	freeRAM(&startedThreads);
	cout << "TCP: Stopped Threads:" << endl;
	freeRAM(&stoppedThreads);
}