Blame view

src/server.cpp 2.59 KB
Imanol-Mikel Barba Sabariego authored
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/** @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);
}