From 212f9ae5dc8899bab8b23ed13d81c28c510db3c3 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Sun, 23 Nov 2003 05:07:37 +0000 Subject: [PATCH] Varios cambios: - Se empiezan a emprolijar las cosas, empezando por Runnable: * Se ponen atributos y signals como privados y se agrega mutex. * El thread que usa ahora no es joinable, por lo que finish() ahora no lleva argumentos. - Se arreglan todas las otras clases (y el programa principal) para que anden con el nuevo Runnable (haciendo loops de espera cuando deben 'joinear' un thread). - Se actuliza el plaqui-client y se le arreglan un par de bugs (ya anda la opcion desconectar del menu). - Se implementa el comando /server/stop por completo (usando una conexion suicida para salir del accept()). - Se agregan separadores de tipos, constantes, atributos y metodos mas llamativos :) --- Client/src/principal.cpp | 16 ++++--- Server/include/plaqui/server/command.h | 3 ++ Server/include/plaqui/server/connection.h | 8 ++-- Server/include/plaqui/server/controlclient.h | 3 ++ Server/include/plaqui/server/controlserver.h | 6 +-- Server/include/plaqui/server/httperror.h | 2 + Server/include/plaqui/server/httpheaders.h | 1 + Server/include/plaqui/server/httpmessage.h | 3 ++ Server/include/plaqui/server/httprequest.h | 4 ++ Server/include/plaqui/server/httpresponse.h | 3 ++ Server/include/plaqui/server/plant.h | 6 +-- Server/include/plaqui/server/receiver.h | 5 ++- Server/include/plaqui/server/runnable.h | 45 ++++++++++++------- Server/include/plaqui/server/server.h | 3 ++ Server/include/plaqui/server/string.h | 5 ++- Server/include/plaqui/server/tcpserver.h | 12 ++--- Server/include/plaqui/server/transmitter.h | 1 + Server/src/connection.cpp | 10 +++-- Server/src/controlclient.cpp | 14 +++--- Server/src/controlserver.cpp | 6 +-- Server/src/main.cpp | 15 ++++++- Server/src/plant.cpp | 21 ++++++--- Server/src/receiver.cpp | 4 +- Server/src/runnable.cpp | 38 +++++++++------- Server/src/server.cpp | 33 +++++++++++--- Server/src/tcpserver.cpp | 26 ++++++++--- Server/src/transmitter.cpp | 8 ++-- docs/cliente_servidor.dia | Bin 2769 -> 2770 bytes 28 files changed, 210 insertions(+), 91 deletions(-) diff --git a/Client/src/principal.cpp b/Client/src/principal.cpp index 0b59c0b..1b42b2b 100644 --- a/Client/src/principal.cpp +++ b/Client/src/principal.cpp @@ -62,8 +62,13 @@ Principal::Principal(BaseObjectType *co, const Glib::RefPtr & Principal::~Principal() { - if (conexion != NULL) - delete conexion; + if (conexion) { + conexion->finish(); + } + // Espera a que termine realmente. + while (conexion) { + Glib::usleep(10000); // 10 milisegundos + } } void Principal::on_dlg_connect_ok() @@ -75,8 +80,9 @@ void Principal::on_dlg_connect_ok() } catch (...) { txt_view->get_buffer()->insert_at_cursor("NO SE PUDO CREAR OBJETO\n"); - delete conexion; - conexion == NULL; + //delete conexion; XXX Si no me equivoco, si falla el + //constructor, no se reserva la memoria (el delete no va). + conexion = NULL; return; } @@ -122,7 +128,7 @@ void Principal::on_mnu_file_disconnect() PlaQui::Server::Command c("connection", "stop"); c.add_arg(conexion->get_host()); - c.add_arg("7522"); + c.add_arg(conexion->get_port()); conexion->send(c); } diff --git a/Server/include/plaqui/server/command.h b/Server/include/plaqui/server/command.h index 0074557..6f78b53 100644 --- a/Server/include/plaqui/server/command.h +++ b/Server/include/plaqui/server/command.h @@ -43,6 +43,7 @@ namespace Server { /// Pedido HTTP. class Command: private HTTPRequest { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -50,6 +51,7 @@ namespace Server { /// Tipo de métodos HTTP reconocidos. typedef std::vector Arguments; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -63,6 +65,7 @@ namespace Server { /// Lista de argumentos que recibe el comando. Arguments args; + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/connection.h b/Server/include/plaqui/server/connection.h index 1eab7fa..7eda172 100644 --- a/Server/include/plaqui/server/connection.h +++ b/Server/include/plaqui/server/connection.h @@ -38,6 +38,7 @@ namespace Server { /// Conexión. class Connection: public Runnable { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -45,6 +46,7 @@ namespace Server { /// Puerto. typedef unsigned Port; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: @@ -61,6 +63,7 @@ namespace Server { /// Mutex para el socket. //Glib::Mutex socket_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. public: @@ -98,13 +101,10 @@ namespace Server { /** * Finaliza la conexión. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - virtual void finish(bool attach = false); + virtual void finish(void); /** * Obtiene el nombre del host local de la conexión. diff --git a/Server/include/plaqui/server/controlclient.h b/Server/include/plaqui/server/controlclient.h index d046c8f..254f815 100644 --- a/Server/include/plaqui/server/controlclient.h +++ b/Server/include/plaqui/server/controlclient.h @@ -40,6 +40,7 @@ namespace Server { /// Conexión para enviar comandos de control a una planta. class ControlClient: public Connection { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -53,6 +54,7 @@ namespace Server { /// Tipo de señal para indicar que se recibió un error. typedef SigC::Signal1 SignalErrorReceived; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: @@ -69,6 +71,7 @@ namespace Server { /// Receptor del estado de la planta TODO Temporal. Receiver* receiver; + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/controlserver.h b/Server/include/plaqui/server/controlserver.h index 25d1224..a5cb0fe 100644 --- a/Server/include/plaqui/server/controlserver.h +++ b/Server/include/plaqui/server/controlserver.h @@ -41,7 +41,7 @@ namespace Server { /// Conexión para recibir comandos de control para una planta. class ControlServer: public Connection { - + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -49,7 +49,7 @@ namespace Server { /// Tipo de señal para indicar que se recibió un comando. typedef SigC::Signal1 SignalCommandReceived; - + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -57,7 +57,7 @@ namespace Server { /// Señal para indicar que se recibió un comando. SignalCommandReceived command_received; - + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/httperror.h b/Server/include/plaqui/server/httperror.h index 1cc4ee8..e55bf61 100644 --- a/Server/include/plaqui/server/httperror.h +++ b/Server/include/plaqui/server/httperror.h @@ -40,6 +40,7 @@ namespace Server { /// Error HTTP. class HTTPError: public std::runtime_error { + ///////////////////////////////////////////////////////////////////// // Atributos. public: @@ -47,6 +48,7 @@ namespace Server { /// Código de error. unsigned code; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpheaders.h b/Server/include/plaqui/server/httpheaders.h index 23470f3..ce703b2 100644 --- a/Server/include/plaqui/server/httpheaders.h +++ b/Server/include/plaqui/server/httpheaders.h @@ -42,6 +42,7 @@ namespace Server { /// Cabeceras HTTP. class HTTPHeaders: public std::map { + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpmessage.h b/Server/include/plaqui/server/httpmessage.h index 30bc794..37c0287 100644 --- a/Server/include/plaqui/server/httpmessage.h +++ b/Server/include/plaqui/server/httpmessage.h @@ -38,6 +38,7 @@ namespace Server { /// Pedido HTTP. class HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Constantes. public: @@ -52,6 +53,7 @@ namespace Server { static const unsigned NOT_IMPLEMENTED = 501; static const unsigned HTTP_VERSION_NOT_SUPPORTED = 505; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -67,6 +69,7 @@ namespace Server { /// Cabeceras HTTP. HTTPHeaders headers; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httprequest.h b/Server/include/plaqui/server/httprequest.h index 5f0757e..7b43f67 100644 --- a/Server/include/plaqui/server/httprequest.h +++ b/Server/include/plaqui/server/httprequest.h @@ -42,6 +42,7 @@ namespace Server { /// Pedido HTTP. class HTTPRequest: public HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Constantes. protected: @@ -73,6 +74,7 @@ namespace Server { /// Caracteres no hexa para URIs (RFC 2396). static const std::string CHARS_HEX; + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -80,6 +82,7 @@ namespace Server { /// Tipo de métodos HTTP reconocidos. typedef enum {GET, POST} HTTPMethod; + ///////////////////////////////////////////////////////////////////// // Atributos. protected: // TODO hacer privados con get() y set() ??? @@ -96,6 +99,7 @@ namespace Server { /// Query string. std::string query; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/httpresponse.h b/Server/include/plaqui/server/httpresponse.h index 5aa8f62..09ff21d 100644 --- a/Server/include/plaqui/server/httpresponse.h +++ b/Server/include/plaqui/server/httpresponse.h @@ -40,6 +40,7 @@ namespace Server { /// Respuesta HTTP. class HTTPResponse: public HTTPMessage { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -51,6 +52,7 @@ namespace Server { MISSING_HTTP_RESPONSE_CODE } Error; + ///////////////////////////////////////////////////////////////////// // Atributos. //protected: FIXME - hacer privado con get/set? @@ -62,6 +64,7 @@ namespace Server { /// Descripción del código (razón). std::string reason; + ///////////////////////////////////////////////////////////////////// // Métodos. public: diff --git a/Server/include/plaqui/server/plant.h b/Server/include/plaqui/server/plant.h index 31aea96..753899b 100644 --- a/Server/include/plaqui/server/plant.h +++ b/Server/include/plaqui/server/plant.h @@ -40,7 +40,7 @@ namespace Server { /// Planta Química. class Plant: public Runnable { - + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -48,7 +48,7 @@ namespace Server { /// Lista de conexiones de control. typedef std::list TransmitterList; - + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -68,7 +68,7 @@ namespace Server { /// Nombre del archivo donde esta el XML de la planta. std::string filename; - + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/receiver.h b/Server/include/plaqui/server/receiver.h index 462c739..c33fd28 100644 --- a/Server/include/plaqui/server/receiver.h +++ b/Server/include/plaqui/server/receiver.h @@ -40,6 +40,7 @@ namespace Server { /// Conexión para recibir el estado de una planta. class Receiver: public Connection { + ///////////////////////////////////////////////////////////////////// // Constantes. private: @@ -50,7 +51,7 @@ namespace Server { /// Marca de fin de frame. static const std::string FRAME_END; - + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -66,7 +67,7 @@ namespace Server { /// Señal que indica que se recibió un cuadro. SignalFrameReceived frame_received; - + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/include/plaqui/server/runnable.h b/Server/include/plaqui/server/runnable.h index c46cf8c..258cd2d 100644 --- a/Server/include/plaqui/server/runnable.h +++ b/Server/include/plaqui/server/runnable.h @@ -38,6 +38,7 @@ namespace Server { /// ealizauna tarea (generalmente en un thread). class Runnable { + ///////////////////////////////////////////////////////////////////// // Tipos. public: @@ -51,28 +52,27 @@ namespace Server { /// Tipo de señal para indicar que hubo un error. typedef SigC::Signal2 SignalError; + ///////////////////////////////////////////////////////////////////// // Atributos. private: /// Thread en el cual correr la tarea. - Glib::Thread* thread; + Glib::Thread* _thread; /// Señal que indica que se finalizó la tarea. - SignalFinished finished; - - protected: + SignalFinished _finished; /// Señal que indica que hubo un error. - SignalError error; + SignalError _error; - /** - * Indica si se debe frinalizar la tarea. - * - * \todo Poner como privado y poner get() set() con locks. - */ - bool stop; + /// Indica si se debe frinalizar la tarea. + bool _stop; + /// Mutex para stop. + Glib::Mutex stop_mutex; + + ///////////////////////////////////////////////////////////////////// // Métodos. private: @@ -86,7 +86,23 @@ namespace Server { protected: - /// Realiza la terea. + /** + * Indica si la tarea debe finalizar. + */ + bool stop(void); + + /** + * Establece si la tarea debe finalizar. + * + * \param stop Nuevo valor. + * + * \return Valor anterior. + */ + bool stop(bool stop); + + /** + * Realiza la terea. + */ virtual void real_run(void) = 0; public: @@ -112,13 +128,10 @@ namespace Server { /** * Finaliza la tarea. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - virtual void finish(bool attach = false); + virtual void finish(void); /** * Obtiene la señal que avisa cuando la tarea es finalizada. diff --git a/Server/include/plaqui/server/server.h b/Server/include/plaqui/server/server.h index ae83251..f8757e7 100644 --- a/Server/include/plaqui/server/server.h +++ b/Server/include/plaqui/server/server.h @@ -47,6 +47,7 @@ namespace Server { */ class Server: public TCPServer { + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -54,6 +55,7 @@ namespace Server { /// Lista de plantas químicas. typedef std::map PlantList; + ///////////////////////////////////////////////////////////////////// // Atributos. private: @@ -64,6 +66,7 @@ namespace Server { /// Mutex para las plantas. Glib::Mutex plants_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. protected: diff --git a/Server/include/plaqui/server/string.h b/Server/include/plaqui/server/string.h index 96e2bb8..9c0d72a 100644 --- a/Server/include/plaqui/server/string.h +++ b/Server/include/plaqui/server/string.h @@ -51,9 +51,12 @@ namespace Server { return p2; } - /// Conexión. + /// String con varios métodos útiles. class String: public std::string { + ///////////////////////////////////////////////////////////////////// + // Métodos. + public: /// Caracteres que son considerados espacios a la hora de parsear. diff --git a/Server/include/plaqui/server/tcpserver.h b/Server/include/plaqui/server/tcpserver.h index a64b545..d94918e 100644 --- a/Server/include/plaqui/server/tcpserver.h +++ b/Server/include/plaqui/server/tcpserver.h @@ -44,6 +44,7 @@ namespace Server { */ class TCPServer: public Runnable { + ///////////////////////////////////////////////////////////////////// // Constantes. private: @@ -51,6 +52,7 @@ namespace Server { /// Cantidad máxima de conexiones pendientes. static const unsigned MAX_PENDING_CONNECTIONS = 10; + ///////////////////////////////////////////////////////////////////// // Tipos. private: @@ -71,12 +73,14 @@ namespace Server { /// Lista de información de conexiones de control. typedef std::vector ConnectionInfoList; + ///////////////////////////////////////////////////////////////////// // Atributos. - private: + protected: //FIXME /// Socket para escuchar conexiones. sockinetbuf socket; + private: // FIXME /// Conexiones de control. ConnectionList connections; @@ -84,6 +88,7 @@ namespace Server { /// Mutex para las conexiones. Glib::Mutex connections_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. private: @@ -121,13 +126,10 @@ namespace Server { /** * Finaliza la tarea. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - //virtual void finish(bool attach = false); + //virtual void finish(void); /** * Se encarga de borrar una conexión de la lista cuando finaliza. diff --git a/Server/include/plaqui/server/transmitter.h b/Server/include/plaqui/server/transmitter.h index acf38e8..624ff3b 100644 --- a/Server/include/plaqui/server/transmitter.h +++ b/Server/include/plaqui/server/transmitter.h @@ -38,6 +38,7 @@ namespace Server { /// Conexión para transmitir el estado de una planta. class Transmitter: public Connection { + ///////////////////////////////////////////////////////////////////// // Métodos. private: diff --git a/Server/src/connection.cpp b/Server/src/connection.cpp index 75915c9..c355c86 100644 --- a/Server/src/connection.cpp +++ b/Server/src/connection.cpp @@ -74,19 +74,21 @@ Connection::Connection(const std::string& host, const Port& port): #endif // DEBUG } -void Connection::finish(bool attach) { +void Connection::finish(void) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": finish(attach = " << attach << ")." << endl; + << ": finish();" << endl; #endif // DEBUG //socket_mutex.lock(); try { socket->shutdown(sockbuf::shut_readwrite); + // FIXME socket->close(sockbuf::shut_readwrite); + // close(socket->sd()); } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); } //socket_mutex.unlock(); - Runnable::finish(attach); + Runnable::finish(); } const string& Connection::get_host(void) const { diff --git a/Server/src/controlclient.cpp b/Server/src/controlclient.cpp index 75e330b..653fcae 100644 --- a/Server/src/controlclient.cpp +++ b/Server/src/controlclient.cpp @@ -43,7 +43,9 @@ ControlClient::~ControlClient(void) { << ": destructor." << endl; #endif // DEBUG // TODO Temporal: espero que el receiver muera. - receiver->finish(true); + // Conectar señal on_receiver_finished() y esperar a que el puntero sea + // NULL para saber que terminó. + receiver->finish(); } ControlClient::ControlClient(const string& _host, @@ -75,14 +77,14 @@ void ControlClient::real_run(void) { try { } catch (const sockerr& e) { // TODO Poner una señal de error específica? - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; } // TODO sacar signal_connected? connected(); // TODO Temporal: el receiver empieza a escuchar. receiver->run(); - while (!stop) { + while (!stop()) { HTTPResponse response; try { //Glib::Mutex::Lock lock(socket_mutex); @@ -90,10 +92,10 @@ void ControlClient::real_run(void) { // Si se cerró el socket. } catch (const ios::failure& e) { // TODO poner buenos codigos de error. - error(1000000, "Se desconectó."); + signal_error().emit(1000000, "Se desconectó."); return; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; // Si hay un error al parsear la respuesta. } catch (const HTTPResponse::Error& e) { @@ -120,7 +122,7 @@ void ControlClient::send(const Command& command) { try { socket << command << flush; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); finish(); } #ifdef DEBUG diff --git a/Server/src/controlserver.cpp b/Server/src/controlserver.cpp index a9cf729..41d5419 100644 --- a/Server/src/controlserver.cpp +++ b/Server/src/controlserver.cpp @@ -63,17 +63,17 @@ void ControlServer::real_run(void) { << ": real_run()" << endl; #endif // DEBUG //char buf[BUFSIZ]; - while (!stop) { + while (!stop()) { Command command; try { //Glib::Mutex::Lock lock(socket_mutex); socket >> command; } catch (const ios::failure& e) { // TODO poner buenos codigos de error. - error(1000000, "Se desconectó."); + signal_error().emit(1000000, "Se desconectó."); return; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; // Si se cerró el socket. //} catch (const ios::failure& e) { diff --git a/Server/src/main.cpp b/Server/src/main.cpp index 7ac8ff4..08c7cd5 100644 --- a/Server/src/main.cpp +++ b/Server/src/main.cpp @@ -82,6 +82,10 @@ int main(int argc, char* argv[]) { } catch (const sockerr& e) { cerr << "Socket Error: " << e.operation() << " | serrno = " << e.serrno() << " | errstr = " << e.errstr() << endl; + if (e.serrno() == 98) { + cerr << "No se puede usar el puerto " << port << " porque ya está " + "siendo utilizado por otro programa." << endl; + } if (e.io()) { cerr << "Es: non-blocking and interrupt io recoverable error." << endl; @@ -112,16 +116,23 @@ int main(int argc, char* argv[]) { // Conecto señal para atender errores. server->signal_error().connect(SigC::slot(on_error)); + // Conecto señal para atender la finalización del server. + server->signal_finished().connect(SigC::slot(on_finished)); + // Corre el server. - server->run(false); + server->run(); // Espera a que el server se muera. while (server) { - Glib::usleep(1000000); + //cerr << "-----------------\n\nAHHHHHHH\n\n----------------" << endl; + Glib::usleep(100000); // 0,1 segundos } + // Espera un segundo más por las dudas, para asegurarse de que terminó. + Glib::usleep(1000000); // 1 segundo // Como no detachee el server, lo tengo que eliminar a mano. //delete server; return 0; } + diff --git a/Server/src/plant.cpp b/Server/src/plant.cpp index b020e21..0e70a1f 100644 --- a/Server/src/plant.cpp +++ b/Server/src/plant.cpp @@ -44,11 +44,20 @@ Plant::~Plant(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - // Termino transmisiones. - Glib::Mutex::Lock lock(transmissions_mutex); - for (TransmitterList::iterator trans = transmissions.end(); + // Mando a terminar todas las transmisiones. + transmissions_mutex.lock(); + for (TransmitterList::iterator trans = transmissions.begin(); trans != transmissions.end(); trans++) { - (*trans)->finish(true); + (*trans)->finish(); + } + TransmitterList::size_type count = transmissions.size(); + transmissions_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + transmissions_mutex.lock(); + count = transmissions.size(); + transmissions_mutex.unlock(); } } @@ -76,7 +85,7 @@ void Plant::real_run(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": real_run." << endl; #endif // DEBUG - while (!stop) { + while (!stop()) { simulator_mutex.lock(); simulator.simulate(); string plantstatus = simulator.get_state_as_xml(); @@ -87,7 +96,7 @@ void Plant::real_run(void) { (*i)->send(plantstatus); } transmissions_mutex.unlock(); - Glib::usleep(1000000); + Glib::usleep(100000); } } diff --git a/Server/src/receiver.cpp b/Server/src/receiver.cpp index 22cc1a8..6e6c503 100644 --- a/Server/src/receiver.cpp +++ b/Server/src/receiver.cpp @@ -68,13 +68,13 @@ void Receiver::real_run(void) { char buf[BUFSIZ]; bool in_frame = false; stringstream ss; - while (!stop) { + while (!stop()) { try { if (!socket.getline(buf, BUFSIZ)) { return; // Se terminó la transmision. } } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); return; } string sbuf = buf; diff --git a/Server/src/runnable.cpp b/Server/src/runnable.cpp index d9d5048..7079143 100644 --- a/Server/src/runnable.cpp +++ b/Server/src/runnable.cpp @@ -46,7 +46,7 @@ Runnable::~Runnable(void) { #endif // DEBUG } -Runnable::Runnable(void): thread(0), stop(false) { +Runnable::Runnable(void): _thread(NULL), _stop(false) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" << ": constructor." << endl; @@ -56,12 +56,10 @@ Runnable::Runnable(void): thread(0), stop(false) { void Runnable::static_run(Runnable* runner) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": static_run(runner = " << runner << ")" - << endl; + << ": static_run(runner = " << runner << ")" << endl; #endif // DEBUG runner->real_run(); - runner->finished(); - //runner->thread->join(); + runner->_finished(); delete runner; } @@ -74,9 +72,9 @@ void Runnable::run(bool detach) { if (detach) { // Corremos el thread en una funcion estática para poder destruirlo al // finalizar, pasandole el puntero al objeto. - thread = Glib::Thread::create( + _thread = Glib::Thread::create( SigC::bind(SigC::slot(&Runnable::static_run), this), - true);//false); + false);//true); // Si no corremos la tarea normalmente. } else { real_run(); @@ -84,23 +82,33 @@ void Runnable::run(bool detach) { } -void Runnable::finish(bool attach) { +void Runnable::finish(void) { #ifdef DEBUG cerr << __FILE__ << "(" << __LINE__ << ")" - << ": finish(attach = " << attach << ")" << endl; + << ": finish();" << endl; #endif // DEBUG - stop = true; - if (attach) { - thread->join(); - } + stop(true); +} + +bool Runnable::stop(void) { + Glib::Mutex::Lock lock(stop_mutex); + bool tmp = _stop; + return tmp; +} + +bool Runnable::stop(bool stop) { + Glib::Mutex::Lock lock(stop_mutex); + bool tmp = _stop; + _stop = stop; + return tmp; } Runnable::SignalFinished& Runnable::signal_finished(void) { - return finished; + return _finished; } Runnable::SignalError& Runnable::signal_error(void) { - return error; + return _error; } } // namespace Server diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 340c2f0..e332866 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -29,6 +29,7 @@ #include "plaqui/server/connection.h" #include "plaqui/server/controlserver.h" #include +#include #include #include #ifdef DEBUG @@ -47,10 +48,19 @@ Server::~Server(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - // Termino plantas. - Glib::Mutex::Lock lock(plants_mutex); - for (PlantList::iterator i = plants.end(); i != plants.end(); i++) { - i->second->finish(true); + // Mando a terminar todas las plantas. + plants_mutex.lock(); + for (PlantList::iterator i = plants.begin(); i != plants.end(); i++) { + i->second->finish(); + } + PlantList::size_type count = plants.size(); + plants_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + plants_mutex.lock(); + count = plants.size(); + plants_mutex.unlock(); } } @@ -60,7 +70,7 @@ Server::Server(const string& plant_filename, const Connection::Port& port) cerr << __FILE__ << "(" << __LINE__ << ")" << ": port = " << port << endl; #endif // DEBUG - // FIXME + // FIXME - hacer que se puedan cargar mas plantas bien. Glib::Mutex::Lock lock(plants_mutex); plants["default"] = new Plant(plant_filename); plants["default"]->signal_finished().connect( @@ -114,6 +124,19 @@ void Server::on_control_command_received(const Command& command, finish(); response = new HTTPResponse(HTTPMessage::OK, ""); + response->headers["Content-Type"] = "text/xml; charset=iso-8859-1"; + controlserver->send(*response); + delete response; + // Creo una conexión suicida para que el accept() del server retorne + // el control y el server pueda terminar realmente. + try { + sockinetbuf suicida(sockbuf::sock_stream); + suicida.connect(socket.localhost(), socket.localport()); + } catch (...) { + // FIXME + signal_error().emit(12345, "ahhhh! no puedo crear conexion suicida"); + } + return; } else { response = new HTTPResponse(HTTPMessage::NOT_FOUND, ""); diff --git a/Server/src/tcpserver.cpp b/Server/src/tcpserver.cpp index ffbdead..8272e57 100644 --- a/Server/src/tcpserver.cpp +++ b/Server/src/tcpserver.cpp @@ -27,6 +27,7 @@ #include "plaqui/server/tcpserver.h" #include +#include #ifdef DEBUG # include #endif // DEBUG @@ -42,10 +43,20 @@ TCPServer::~TCPServer(void) { cerr << __FILE__ << "(" << __LINE__ << ")" << ": destructor." << endl; #endif // DEBUG - Glib::Mutex::Lock lock(connections_mutex); + // Mando a terminar todas las conexiones. + connections_mutex.lock(); for (ConnectionList::iterator con = connections.begin(); con != connections.end(); con++) { - (*con)->finish(true); + (*con)->finish(); + } + ConnectionList::size_type count = connections.size(); + connections_mutex.unlock(); + // Espero que terminen realmente. + while (count) { + Glib::usleep(10000); // 10 milisegundos + connections_mutex.lock(); + count = connections.size(); + connections_mutex.unlock(); } } @@ -75,8 +86,13 @@ TCPServer::TCPServer(const Connection::Port& port) throw(sockerr): } /*void TCPServer::finish(bool attach) { +#ifdef DEBUG + cerr << __FILE__ << "(" << __LINE__ << ")" + << ": finish(attach = " << attach << ");" << endl; +#endif // DEBUG //socket_mutex.lock(); - socket.shutdown(sockbuf::shut_readwrite); + close(socket.sd()); + //socket.shutdown(sockbuf::shut_readwrite); //socket_mutex.unlock(); Runnable::finish(attach); }*/ @@ -106,12 +122,12 @@ void TCPServer::real_run(void) { << ": real_run()" << endl; #endif // DEBUG Connection* connection; - while (!stop) { + while (!stop()) { // Forma grasa de salir del accept: crear conexion que salga al toque. try { connection = new_connection(socket.accept()); } catch (const sockerr& e) { // No se si el accept() puede fallar. - error(e.serrno(), e.errstr()); + signal_error().emit(e.serrno(), e.errstr()); continue; // Supongo que puede seguir aceptando conexiones. } #ifdef DEBUG diff --git a/Server/src/transmitter.cpp b/Server/src/transmitter.cpp index 6ab9260..4348da6 100644 --- a/Server/src/transmitter.cpp +++ b/Server/src/transmitter.cpp @@ -71,7 +71,7 @@ void Transmitter::real_run(void) { << ": real_run()." << endl; #endif // DEBUG // No hace nada, porque solo actua cuando se manda algo con send(). - while (!stop) { + while (!stop()) { Glib::usleep(500000); // 1/2 segundo } } @@ -82,14 +82,14 @@ void Transmitter::send(const string& data) { << ": send()." << endl; // << ": send(data = " << data << ")." << endl; #endif // DEBUG - if (stop) { + if (stop()) { return; } try { socket << data << flush; } catch (const sockerr& e) { - error(e.serrno(), e.errstr()); - stop = true; + signal_error().emit(e.serrno(), e.errstr()); + stop(true); } } diff --git a/docs/cliente_servidor.dia b/docs/cliente_servidor.dia index cad9d442b557cc3c19d37c7ea440f9bbaf5cd5e8..1869c188757e8ed71d76bb0ce873756b9ab585e9 100644 GIT binary patch literal 2770 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 literal 2769 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 Xry~2T{*DBh+