]> git.llucax.com Git - z.facultad/75.42/plaqui.git/blob - Server/src/tcpserver.cpp
Se termina de poner prolijo Runnable:
[z.facultad/75.42/plaqui.git] / Server / src / tcpserver.cpp
1 // vim: set noexpandtab tabstop=4 shiftwidth=4:
2 //----------------------------------------------------------------------------
3 //                                  PlaQui
4 //----------------------------------------------------------------------------
5 // This file is part of PlaQui.
6 //
7 // PlaQui is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the Free Software
9 // Foundation; either version 2 of the License, or (at your option) any later
10 // version.
11 //
12 // PlaQui is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 // details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with PlaQui; if not, write to the Free Software Foundation, Inc., 59 Temple
19 // Place, Suite 330, Boston, MA  02111-1307  USA
20 //----------------------------------------------------------------------------
21 // Creado:  Sat Oct 18 18:18:36 2003
22 // Autores: Leandro Lucarella <llucare@fi.uba.ar>
23 //----------------------------------------------------------------------------
24 //
25 // $Id$
26 //
27
28 #include "plaqui/server/tcpserver.h"
29 #include <sigc++/class_slot.h>
30 #include <glibmm/timer.h>
31 #ifdef DEBUG
32 #       include <iostream>
33 #endif // DEBUG
34
35 using namespace std;
36
37 namespace PlaQui {
38
39 namespace Server {
40
41 TCPServer::~TCPServer(void) {
42 #ifdef DEBUG
43         cerr << __FILE__ << "(" << __LINE__ << ")"
44                 <<  ": destructor." << endl;
45 #endif // DEBUG
46         // Mando a terminar todas las conexiones.
47         connections_mutex.lock();
48         for (ConnectionList::iterator con = connections.begin();
49                         con != connections.end(); con++) {
50                 (*con)->finish();
51         }
52         ConnectionList::size_type count = connections.size();
53         connections_mutex.unlock();
54         // Espero que terminen realmente.
55         while (count) {
56                 Glib::usleep(10000); // 10 milisegundos
57                 connections_mutex.lock();
58                 count = connections.size();
59                 connections_mutex.unlock();
60         }
61 }
62
63 TCPServer::TCPServer(const Connection::Port& port) throw(sockerr):
64                 socket(sockbuf::sock_stream) {
65 #ifdef DEBUG
66         cerr << __FILE__ << "(" << __LINE__ << ")"
67                 <<  ": port = " << port << endl;
68 #endif // DEBUG
69         // FIXME
70         //cerr << "recvtimeout = " << socket.recvtimeout(1) << endl;
71         //cerr << "sendtimeout = " << socket.sendtimeout(1) << endl;
72         //cerr << "recvtimeout = " << socket.recvtimeout(1) << endl;
73         //cerr << "sendtimeout = " << socket.sendtimeout(1) << endl;
74         socket.bind(port);
75 #ifdef DEBUG
76         cerr << __FILE__ << "(" << __LINE__ << ")"
77                 <<  ": escuchando en " << socket.localhost()
78                 << ":" << socket.localport() << "." << endl;
79 #endif // DEBUG
80         socket.listen(MAX_PENDING_CONNECTIONS);
81 #ifdef DEBUG
82         cerr << __FILE__ << "(" << __LINE__ << ")"
83                 <<  ": [despues de listen()] escuchando en "
84                 << socket.localhost() << ":" << socket.localport() << "." << endl;
85 #endif // DEBUG
86 }
87
88 /*void TCPServer::finish(bool attach) {
89 #ifdef DEBUG
90         cerr << __FILE__ << "(" << __LINE__ << ")"
91                 <<  ": finish(attach = " << attach << ");" << endl;
92 #endif // DEBUG
93         //socket_mutex.lock();
94         close(socket.sd());
95         //socket.shutdown(sockbuf::shut_readwrite);
96         //socket_mutex.unlock();
97         Runnable::finish(attach);
98 }*/
99
100 void TCPServer::on_connection_finished(Connection* connection) {
101 #ifdef DEBUG
102         cerr << __FILE__ << "(" << __LINE__ << ")"
103                 <<  ": on_connection_finished(connection = "
104                 << connection << ")" << endl;
105 #endif // DEBUG
106         Glib::Mutex::Lock lock(connections_mutex);
107         connections.remove(connection);
108 #ifdef DEBUG
109         cerr << __FILE__ << "(" << __LINE__ << ")"
110                 <<  ": lista de conexiones" << endl;
111         for (ConnectionList::const_iterator i = connections.begin();
112                         i != connections.end(); i++) {
113                 cerr << "\t " << *i << endl;
114         }
115 #endif // DEBUG
116 }
117
118 void TCPServer::real_run(void) throw() {
119 #ifdef DEBUG
120         cerr << __FILE__ << "(" << __LINE__ << ")"
121                 <<  ": real_run()" << endl;
122 #endif // DEBUG
123         Connection* connection;
124         while (!stop()) {
125                 // Forma grasa de salir del accept: crear conexion que salga al toque.
126                 try {
127                         connection = new_connection(socket.accept());
128                 } catch (const sockerr& e) { // No se si el accept() puede fallar.
129                         signal_error().emit(e.serrno(), e.errstr());
130                         continue; // Supongo que puede seguir aceptando conexiones.
131                 }
132 #ifdef DEBUG
133                 cerr << __FILE__ << "(" << __LINE__ << ")"
134                         <<  ": real_run(): connection = " << connection
135                         << endl;
136 #endif // DEBUG
137                 Glib::Mutex::Lock lock(connections_mutex);
138                 // XXX connections_mutex.lock();
139                 connections.push_back(connection);
140 #ifdef DEBUG
141                 cerr << __FILE__ << "(" << __LINE__ << ")"
142                         <<  ": real_run(): lista de conexiones" << endl;
143                 for (ConnectionList::const_iterator i = connections.begin();
144                                 i != connections.end(); i++) {
145                         cerr << "\t " << *i << endl;
146                 }
147 #endif // DEBUG
148                 // XXX connections_mutex.unlock(); // Si pongo el mutex antes del run(),
149                 //                                    muere.
150                 // Conecto la señal para cuando termina una conexión, borrarla.
151                 connection->signal_finished().connect(
152                                 SigC::bind<Connection*>(
153                                         SigC::slot_class(*this,
154                                                 &TCPServer::on_connection_finished),
155                                         connection));
156                 connection->run();
157         }
158 }
159
160 bool TCPServer::disconnect(const std::string& host, const Connection::Port& port) {
161 #ifdef DEBUG
162         cerr << __FILE__ << "(" << __LINE__ << ")"
163                 <<  ": disconnect(host = " << host
164                 << ", port = " << port << ")" << endl;
165 #endif // DEBUG
166         Glib::Mutex::Lock lock(connections_mutex);
167         for (ConnectionList::iterator con = connections.begin();
168                         con != connections.end(); con++) {
169                 if (((*con)->get_host() == host) && ((*con)->get_port() == port)) {
170                         (*con)->finish();
171                         return true;
172                 }
173         }
174         return false;
175 }
176
177 /// \todo TODO Hay que reemplazarlo por una lista generica.
178 TCPServer::ConnectionInfoList TCPServer::get_connected(void) {
179 #ifdef DEBUG
180         cerr << __FILE__ << "(" << __LINE__ << ")"
181                 <<  ": get_connected()" << endl;
182 #endif // DEBUG
183         TCPServer::ConnectionInfoList cl;
184         Glib::Mutex::Lock lock(connections_mutex);
185         for (ConnectionList::const_iterator con = connections.begin();
186                         con != connections.end(); con++) {
187                 TCPServer::ConnectionInfo ci =
188                         { (*con)->get_host(), (*con)->get_port() };
189                 cl.push_back(ci);
190         }
191         return cl;
192 }
193
194 } // namespace Server
195
196 } // namespace PlaQui
197