Blame view

src/main_server.cpp 3.08 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/** @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;
}