]> git.llucax.com Git - z.facultad/75.42/plaqui.git/commitdiff
Se emprolija un poco:
authorLeandro Lucarella <llucax@gmail.com>
Wed, 19 Nov 2003 22:52:17 +0000 (22:52 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Wed, 19 Nov 2003 22:52:17 +0000 (22:52 +0000)
- Se mejora mucho el manejo y deteccion de errores.
- Tambien se mejora la informacion de debug poniendo el numero de linea.
- Se pone en todos los objetos que se conectan la parte de la conexion en el
  constructor para que pueda capturarse una eventual excepcion.
- Se crea una nueva signal_error para avisar sobre cualquier error que pase en
  el run() que no puede lanzar excepciones.

29 files changed:
Server/configure.in
Server/include/plaqui/server/command.h
Server/include/plaqui/server/controlclient.h
Server/include/plaqui/server/httpheaders.h
Server/include/plaqui/server/httprequest.h
Server/include/plaqui/server/httpresponse.h
Server/include/plaqui/server/receiver.h
Server/include/plaqui/server/runnable.h
Server/include/plaqui/server/server.h
Server/include/plaqui/server/tcpserver.h
Server/include/plaqui/server/transmitter.h
Server/src/command.cpp
Server/src/connection.cpp
Server/src/controlclient.cpp
Server/src/controlserver.cpp
Server/src/httperror.cpp
Server/src/httpheaders.cpp
Server/src/httpmessage.cpp
Server/src/httprequest.cpp
Server/src/httpresponse.cpp
Server/src/plant.cpp
Server/src/receiver.cpp
Server/src/runnable.cpp
Server/src/server.cpp
Server/src/tcpserver.cpp
Server/src/transmitter.cpp
Server/tests/Makefile.am
Server/tests/client_test.cpp
Server/tests/server_test.cpp

index fbbe7f8dd690d0bd0e93a1cd45d2cd3834b0efe3..8ea8f73fcc62b485e99d1fe3ac64a7d83a29b8c3 100644 (file)
@@ -26,7 +26,7 @@
 ##
 
 AC_INIT(configure.in)
-AM_INIT_AUTOMAKE(plaqui_server, 0.9)
+AM_INIT_AUTOMAKE(plaqui_server, 0.10)
 AM_MAINTAINER_MODE
 
 AC_ISC_POSIX
index cd49d43dbe3fbf2e28d7181e2697ea4e97baa1ba..d27fbe2666a6cace768bf8458656eddde66c8049 100644 (file)
@@ -28,7 +28,9 @@
 #ifndef PLAQUI_COMMAND_H
 #define PLAQUI_COMMAND_H
 
+#include "httperror.h"
 #include "httprequest.h"
+#include <socket++/sockstream.h>
 #include <string>
 #include <vector>
 #include <istream>
@@ -127,13 +129,13 @@ namespace Server {
                         * Obtiene el comando desde un pedido HTTP completo.
                         */
                        friend std::istream& operator>>(std::istream& is,
-                                       Command& command);
+                                       Command& command) throw(HTTPError, sockerr);
 
                        /**
                         * Convierte el comando a un pedido HTTP completo.
                         */
                        friend std::ostream& operator<<(std::ostream& os,
-                                       const Command& command);
+                                       const Command& command) throw(sockerr);
 
        };
 
index f2252401890ae6183915053bde6af11d2f0e4628..507d222311866a7b36ac52ac22d6ed9b6055a2bc 100644 (file)
@@ -92,8 +92,8 @@ namespace Server {
                         *                         control.
                         * \param port Puerto al cual conectarse.
                         */
-                       ControlClient(const std::string& host = "localhost",
-                                       const Connection::Port& port = 7522);
+                       ControlClient(const std::string& _host = "localhost",
+                                       const Connection::Port& _port = 7522) throw(sockerr);
 
                        /**
                         * Envía un comando al servidor.
index 86a2dd1b3d96a49430780c1356d397351ff63187..23470f3e33f0597392274265bfaf0525b5a9c9f1 100644 (file)
@@ -29,6 +29,7 @@
 #define PLAQUI_HTTPHEADERS_H
 
 #include "plaqui/server/httperror.h"
+#include <socket++/sockstream.h>
 #include <map>
 #include <string>
 #include <istream>
@@ -54,13 +55,13 @@ namespace Server {
                         * Obtiene los datos de las cabeceras HTTP desde un texto.
                         */
                        friend std::istream& operator>>(std::istream& is, HTTPHeaders& h)
-                               throw(HTTPError);
+                               throw(HTTPError, sockerr, ios::failure);
 
                        /**
                         * Convierte las cabeceras HTTP a texto.
                         */
                        friend std::ostream& operator<<(std::ostream& os,
-                                       const HTTPHeaders& h);
+                                       const HTTPHeaders& h) throw(sockerr);
 
        };
 
index 5056d15cfe8ee68f59465d1f5165cb568ca6ca8f..5f0757ef66aeb064b53a0d2a9ad63ab43b6b554b 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "plaqui/server/httperror.h"
 #include "plaqui/server/httpmessage.h"
+#include <socket++/sockstream.h>
 #include <string>
 #include <istream>
 #include <ostream>
@@ -122,13 +123,13 @@ namespace Server {
                         * Obtiene los datos del pedido HTTP desde un texto.
                         */
                        friend std::istream& operator>>(std::istream& is, HTTPRequest& req)
-                               throw(HTTPError, std::ios::failure);
+                               throw(HTTPError, sockerr, std::ios::failure);
 
                        /**
                         * Convierte el pedido HTTP en texto.
                         */
                        friend std::ostream& operator<<(std::ostream& os,
-                                       const HTTPRequest& req);
+                                       const HTTPRequest& req) throw(sockerr);
 
        };
 
index f4a2db093da3406a94cfc9e8e2ff044974d0833e..5aa8f626b1e5154ae433d1b9f7093eacd4154777 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "plaqui/server/httperror.h"
 #include "plaqui/server/httpmessage.h"
+#include <socket++/sockstream.h>
 #include <string>
 
 namespace PlaQui {
@@ -97,13 +98,14 @@ namespace Server {
                         * Obtiene los datos de la respuesta HTTP desde un texto.
                         */
                        friend std::istream& operator>>(std::istream& is,
-                                       HTTPResponse& resp) throw(Error, std::ios::failure);
+                                       HTTPResponse& resp)
+                               throw(Error, sockerr, std::ios::failure);
 
                        /**
                         * Convierte la respuesta HTTP en texto.
                         */
                        friend std::ostream& operator<<(std::ostream& os,
-                                       const HTTPResponse& resp);
+                                       const HTTPResponse& resp) throw(sockerr);
 
        };
 
index 1ac45efc3ad6f8dc7d588a2052a3460db66877e3..462c739bbaadd2b91d97df40f342a2282e624efe 100644 (file)
@@ -90,7 +90,7 @@ namespace Server {
                         * \param host Host del cual recibir el estado de la planta.
                         */
                        Receiver(const Connection::Port& port = 7528,
-                                       const std::string& host = "localhost");
+                                       const std::string& host = "localhost") throw(sockerr);
 
                        /**
                         * Obtiene la señal que avisa cuando se recibió un cuadro.
index 7896090370af01d016ff3da2bd31b84326a80db3..c46cf8cffedb9eea836e5e42bb6dde6972fa127a 100644 (file)
@@ -42,9 +42,15 @@ namespace Server {
 
                public:
 
+                       /// Error.
+                       typedef unsigned Error;
+
                        /// Tipo de señal para indicar que se finalizó la tarea.
                        typedef SigC::Signal0<void> SignalFinished;
 
+                       /// Tipo de señal para indicar que hubo un error.
+                       typedef SigC::Signal2<void, const Error&, const std::string&> SignalError;
+
                // Atributos.
 
                private:
@@ -57,6 +63,9 @@ namespace Server {
 
                protected:
 
+                       /// Señal que indica que hubo un error.
+                       SignalError error;
+
                        /**
                         * Indica si se debe frinalizar la tarea.
                         *
@@ -113,11 +122,14 @@ namespace Server {
 
                        /**
                         * Obtiene la señal que avisa cuando la tarea es finalizada.
-                        *
-                        * \see finish().
                         */
                        SignalFinished& signal_finished(void);
 
+                       /**
+                        * Obtiene la señal que avisa que hubo un error.
+                        */
+                       SignalError& signal_error(void);
+
        };
 
 }
index b29548350bd3b87449a72295fe65b096195d23e3..9953fd908e9cc2d7e353ba8db2451a0ce8bf5a0c 100644 (file)
@@ -140,7 +140,7 @@ namespace Server {
                         * \param port Puerto en el cual escuchar.
                         */
                        Server(const std::string& plant_filename,
-                                       const Connection::Port& port = 7522);
+                                       const Connection::Port& port = 7522) throw(sockerr);
 
                        /**
                         * Maneja los comandos recibidos por las conexiones.
index 17ce3b12ca79c71d9dc95578e2c4c905e3b13cab..a64b545eeaf9b64f7296d6872ca523c0b82f551e 100644 (file)
@@ -116,7 +116,7 @@ namespace Server {
                         *
                         * \param port Puerto en el cual escuchar.
                         */
-                       TCPServer(const Connection::Port& port);
+                       TCPServer(const Connection::Port& port) throw(sockerr);
 
                        /**
                         * Finaliza la tarea.
@@ -127,7 +127,7 @@ namespace Server {
                         * \note Para saber cuando la tarea fue finalizada puede utilizar
                         *       la señal signal_finished().
                         */
-                       virtual void finish(bool attach = false);
+                       //virtual void finish(bool attach = false);
 
                        /**
                         * Se encarga de borrar una conexión de la lista cuando finaliza.
index 211a31ea9b73fc001ca95d6f99ddfa7a57ff168d..98957fea0042e2e3979d7773e1577eccb9497b8e 100644 (file)
@@ -64,7 +64,8 @@ namespace Server {
                         * \param host Host al cual transmitir.
                         * \param port Puerto al cual transmitir.
                         */
-                       Transmitter(std::string& _host, Connection::Port& _port);
+                       Transmitter(const std::string& _host,
+                                       const Connection::Port& _port) throw(sockerr);
 
                        /**
                         * Envia datos.
index 5087d9e783464e97adcd48170d9256a10178cefd..517d3527582461d1b5e39045da708a46dc6b6e5a 100644 (file)
@@ -28,6 +28,7 @@
 #include "plaqui/server/command.h"
 #include "plaqui/server/string.h"
 #include <algorithm>
+//#include <exception>
 #ifdef DEBUG
 #      include <iostream>
 #endif // DEBUG
@@ -40,13 +41,15 @@ namespace Server {
 
 Command::~Command(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 Command::Command(const string& _target, const string& _command) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": target = " << target << " | "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": target = " << target << " | "
                        << "command = " << command << endl;
 #endif // DEBUG
        set_target(_target);
@@ -62,7 +65,8 @@ void Command::build(void) {
                }
        }
 #ifdef DEBUG
-       cerr << __FILE__ << ": build() = " << uri << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": build() = " << uri << endl;
 #endif // DEBUG
 }
 
@@ -100,16 +104,18 @@ void Command::add_arg(const std::string& arg) {
 
 void Command::add_arg(const unsigned& arg) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": add_arg(arg = " << arg << ") = "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": add_arg(arg = " << arg << ") = "
                << String().from(arg) << endl;
 #endif // DEBUG
        args.push_back(String().from(arg));
        build();
 }
 
-istream& operator>>(istream& is, Command& command) {
+istream& operator>>(istream& is, Command& command) throw(HTTPError, sockerr) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator>>()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator>>()" << endl;
 #endif // DEBUG
        // Obtengo datos del Request HTTP.
        is >> static_cast<HTTPRequest&>(command);
@@ -133,9 +139,10 @@ istream& operator>>(istream& is, Command& command) {
        return is;
 }
 
-ostream& operator<<(ostream& os, const Command& command) {
+ostream& operator<<(ostream& os, const Command& command) throw (sockerr) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator<<()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator<<()" << endl;
 #endif // DEBUG
        // Manda el request HTTP con la URI que representa el comando.
        os << static_cast<const HTTPRequest&>(command);
index a8f17ea3c2521d02a2a46c1d0046789d6e51a61f..75915c96918ff34ab05e7ccd18d1d23c95eb2949 100644 (file)
@@ -39,14 +39,16 @@ namespace Server {
 
 Connection::~Connection(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 Connection::Connection(const sockbuf::sockdesc& sd):
                socket(sd) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": sd = " << sd.sock;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": sd = " << sd.sock;
 #endif // DEBUG
        host = socket->peerhost();
        port = socket->peerport();
@@ -58,7 +60,8 @@ Connection::Connection(const sockbuf::sockdesc& sd):
 Connection::Connection(const sockbuf::type& type, const std::string& host,
                const Port& port): socket(type), host(host), port(port) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": type = " << type << " | host = " << host
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": type = " << type << " | host = " << host
                << " | port = " << port << endl;
 #endif // DEBUG
 }
@@ -66,13 +69,22 @@ Connection::Connection(const sockbuf::type& type, const std::string& host,
 Connection::Connection(const std::string& host, const Port& port):
                host(host), port(port) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": host = " << host << " | port = " << port << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": host = " << host << " | port = " << port << endl;
 #endif // DEBUG
 }
 
 void Connection::finish(bool attach) {
+#ifdef DEBUG
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": finish(attach = " << attach << ")." << endl;
+#endif // DEBUG
        //socket_mutex.lock();
-       socket->shutdown(sockbuf::shut_readwrite);
+       try {
+               socket->shutdown(sockbuf::shut_readwrite);
+       } catch (const sockerr& e) {
+               error(e.serrno(), e.errstr());
+       }
        //socket_mutex.unlock();
        Runnable::finish(attach);
 }
index 48ef3283427c74f99c7046df90328e1a54c6e108..15b576e54801a17cbe22728017f0d4db4650e7da 100644 (file)
@@ -39,34 +39,37 @@ namespace Server {
 
 ControlClient::~ControlClient(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
        // TODO Temporal: espero que el receiver muera.
        receiver.finish(true);
 }
 
-ControlClient::ControlClient(const string& host, const Connection::Port& port):
-               Connection(sockbuf::sock_stream, host, port) {
+ControlClient::ControlClient(const string& _host,
+               const Connection::Port& _port) throw(sockerr):
+               Connection(sockbuf::sock_stream, _host, _port) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": host = " << host
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": host = " << host
                << " | port = " << port << endl;
 #endif // DEBUG
+       socket->connect(host.c_str(), port);
+       host = socket->localhost();
+       port = socket->localport();
 }
 
 void ControlClient::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": real_run." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": real_run." << endl;
 #endif // DEBUG
        try {
-               socket->connect(host.c_str(), port);
        } catch (const sockerr& e) {
-               // Poner una señal de error específica?
-               error_received(1);
-               finish();
+               // TODO Poner una señal de error específica?
+               error(e.serrno(), e.errstr());
                return;
        }
-       host = socket->localhost();
-       port = socket->localport();
        // TODO sacar signal_connected?
        connected();
        // TODO Temporal: el receiver empieza a escuchar.
@@ -78,14 +81,19 @@ void ControlClient::real_run(void) {
                        socket >> response;
                // Si se cerró el socket.
                } catch (const ios::failure& e) {
-                       stop = true;
-                       continue;
+                       // TODO poner buenos codigos de error.
+                       error(1000000, "Se desconectó.");
+                       return;
+               } catch (const sockerr& e) {
+                       error(e.serrno(), e.errstr());
+                       return;
                // Si hay un error al parsear la respuesta.
                } catch (const HTTPResponse::Error& e) {
 #ifdef DEBUG
-                       cerr << __FILE__ << " : real_run() ERROR nro: " << e << endl;
+                       cerr << __FILE__ << "(" << __LINE__ << ")"
+                               << " : real_run() ERROR nro: " << e << endl;
 #endif // DEBUG
-                       // TODO - pasar como parametro codigo de error o algo.
+                       // TODO - es un error recuperable? O manda señal error()?
                        error_received(e);
                        continue;
                }
@@ -101,9 +109,15 @@ void ControlClient::real_run(void) {
 }
 
 void ControlClient::send(const Command& command) {
-       socket << command << flush;
+       try {
+               socket << command << flush;
+       } catch (const sockerr& e) {
+               error(e.serrno(), e.errstr());
+               finish();
+       }
 #ifdef DEBUG
-       cerr << __FILE__ << ": send() Enviado!" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": send() Enviado!" << endl;
 #endif // DEBUG
 }
 
@@ -121,6 +135,9 @@ ControlClient::SignalErrorReceived& ControlClient::signal_error_received(void) {
 
 // TODO - temporal
 Receiver::SignalFrameReceived& ControlClient::signal_frame_received(void) {
+       // XXX - cuidado, esto puede dar quilombo si no esta protegido por un mutex,
+       // aunque no deberia porque la señal no es llamada hasta que no se empice
+       // la transmision y la señal se conecta antes de pedir la transmision.
        return receiver.signal_frame_received();
 }
 
index 23f89c40f0a0f53a561b5991658ebb5f13f64bcc..a9cf729fd091c1662b6733c0a0b3b4cb47d914ee 100644 (file)
@@ -44,20 +44,23 @@ namespace Server {
 
 ControlServer::~ControlServer(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 ControlServer::ControlServer(const sockbuf::sockdesc& sd):
                Connection(sd) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": sd = " << sd.sock << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": sd = " << sd.sock << endl;
 #endif // DEBUG
 }
 
 void ControlServer::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": real_run()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": real_run()" << endl;
 #endif // DEBUG
        //char buf[BUFSIZ];
        while (!stop) {
@@ -65,15 +68,23 @@ void ControlServer::real_run(void) {
                try {
                        //Glib::Mutex::Lock lock(socket_mutex);
                        socket >> command;
-               // Si se cerró el socket.
                } catch (const ios::failure& e) {
-                       stop = true;
-                       continue;
+                       // TODO poner buenos codigos de error.
+                       error(1000000, "Se desconectó.");
+                       return;
+               } catch (const sockerr& e) {
+                       error(e.serrno(), e.errstr());
+                       return;
+               // Si se cerró el socket.
+               //} catch (const ios::failure& e) {
+               //      stop = true;
+               //      continue;
                // Si hay un error al parsear el comando, se envia una respuesta con el
                // error.
                } catch (const HTTPError& e) {
 #ifdef DEBUG
-                       cerr << __FILE__ << " : real_run() ERROR: status_code = "
+                       cerr << __FILE__ << "(" << __LINE__ << ")"
+                               << " : real_run() ERROR: status_code = "
                                << e.code << " | reason = " << HTTPMessage::reason(e.code)
                                << " | desc = " << e.what() << endl;
 #endif // DEBUG
@@ -89,7 +100,8 @@ void ControlServer::real_run(void) {
                bool is_first = true;
                while (!stop && socket.getline(buf, BUFSIZ)) {
 #ifdef DEBUG
-                       cerr << __FILE__ << "  Recibiendo inea: " << buf << endl;
+                       cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << "  Recibiendo inea: " << buf << endl;
 #endif // DEBUG
                        int len = strlen(buf);
                        // Si tiene un retorno de carro, lo elimina.
@@ -119,7 +131,8 @@ void ControlServer::real_run(void) {
                }
 */
 #ifdef DEBUG
-               cerr << __FILE__ << " : real_run() Despachando comando: target = "
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << " : real_run() Despachando comando: target = "
                        << command.get_target() << " | command = " << command.get_command()
                        << " | args = [" << String::join(command.get_args(), ", ") << "]"
                        << endl;
@@ -133,7 +146,8 @@ void ControlServer::send(const HTTPResponse& response) {
        //Glib::Mutex::Lock lock(socket_mutex);
        socket << response << flush;
 #ifdef DEBUG
-       cerr << __FILE__ << ": send() Enviado!" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": send() Enviado!" << endl;
 #endif // DEBUG
 }
 
index b00ded58f778bfd7de779ab31323455ab9d056ec..b833ad1377084e7215750744c56e9b985e011217 100644 (file)
@@ -38,14 +38,16 @@ namespace Server {
 
 HTTPError::~HTTPError(void) throw() {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 HTTPError::HTTPError(unsigned code, const std::string& desc) throw():
                runtime_error(desc), code(code) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": code = " << code << " | desc = " << desc << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": code = " << code << " | desc = " << desc << endl;
 #endif // DEBUG
 }
 
index 04bd6c823de5f41bf37a62d90f4d9380e7088415..b54201e6dc7daf862c2e16feba675974a103ae81 100644 (file)
@@ -25,8 +25,9 @@
 // $Id$
 //
 
-#include "plaqui/server/httpheaders.h"
 #include "plaqui/server/httperror.h"
+#include "plaqui/server/httpmessage.h"
+#include "plaqui/server/httpheaders.h"
 #include "plaqui/server/string.h"
 //#include <cstdlib>
 #ifdef DEBUG
@@ -41,33 +42,41 @@ namespace Server {
 
 HTTPHeaders::~HTTPHeaders(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
-istream& operator>>(istream& is, HTTPHeaders& h) throw(HTTPError) {
+istream& operator>>(istream& is, HTTPHeaders& h)
+               throw(HTTPError, sockerr, ios::failure) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator>>()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator>>()" << endl;
 #endif // DEBUG
        char buf[BUFSIZ];
-       is.getline(buf, BUFSIZ);
+       // Fin del stream, no había cabeceras.
+       if (!is.getline(buf, BUFSIZ)) {
+               throw ios::failure("eof");
+       }
        string sbuf = buf;
        string::size_type pos = sbuf.find(":");
        if (pos == string::npos) {
                // FIXME poner mejores excepciones.
-               throw HTTPError(400, sbuf + ": No es una cabecera válida.");
+               throw HTTPError(HTTPMessage::BAD_REQUEST, sbuf + ": No es una cabecera válida.");
        }
        h[sbuf.substr(0, pos)] = String(sbuf.substr(pos + 1)).trim();
 #ifdef DEBUG
-       cerr << __FILE__ << "    " << sbuf.substr(0, pos) << " = "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << "    " << sbuf.substr(0, pos) << " = "
                << h[sbuf.substr(0, pos)] << endl;
 #endif // DEBUG
        return is;
 }
 
-ostream& operator<<(ostream& os, const HTTPHeaders& h) {
+ostream& operator<<(ostream& os, const HTTPHeaders& h) throw(sockerr) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator<<()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator<<()" << endl;
 #endif // DEBUG
        for (HTTPHeaders::const_iterator i = h.begin();
                        i != h.end(); ++i) {
index c97da08abc2d9712c494b6f24607e9cfda5d545b..260fe80fcc8b76b56e6f1bc0fbe015400bfe50d8 100644 (file)
@@ -41,14 +41,16 @@ namespace Server {
 
 HTTPMessage::~HTTPMessage(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 HTTPMessage::HTTPMessage(const string& _body, const string& _version):
                version(_version) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": version = " << version << " | body ("
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": version = " << version << " | body ("
                << _body.length() << ") = " << _body << endl;
 #endif // DEBUG
        headers["Accept-Ranges"] = "bytes";
@@ -66,7 +68,8 @@ const string& HTTPMessage::get_body(void) const {
 
 istream& operator>>(istream& is, HTTPMessage& m) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator>>()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator>>()" << endl;
 #endif // DEBUG
        char buf[BUFSIZ];
        while (is.getline(buf, BUFSIZ)) {
@@ -97,7 +100,8 @@ istream& operator>>(istream& is, HTTPMessage& m) {
 
 ostream& operator<<(ostream& os, const HTTPMessage& m) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator<<()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator<<()" << endl;
 #endif // DEBUG
        return os << m.headers << "\r\n" // Fin de cabeceras
                << m.body;
index d62b7859f1aa320f61f6651e69f698e2b1388ba2..1da38a7404bcd69bfb3d15daad2ce11d4973871d 100644 (file)
@@ -39,7 +39,8 @@ namespace Server {
 
 HTTPRequest::~HTTPRequest(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
@@ -47,7 +48,8 @@ HTTPRequest::HTTPRequest(const string& uri, const HTTPMethod& method,
                const string& query, const string& body, const string& version):
                HTTPMessage(body, version), method(method), uri(uri), query(query) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": uri = " << uri << " | "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": uri = " << uri << " | "
                        << "method = " << method_str() << " | "
                        << "query = " << query << " | "
                        << "body.length = " << body.length() << " | "
@@ -66,18 +68,20 @@ string HTTPRequest::method_str(void) const {
 }
 
 istream& operator>>(istream& is, HTTPRequest& req)
-               throw(HTTPError, ios::failure) {
+               throw(HTTPError, sockerr, ios::failure) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator>>()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator>>()" << endl;
 #endif // DEBUG
        char buf[BUFSIZ];
        // Obtengo primera línea (request)
        if (!is.getline(buf, BUFSIZ)) {
-               // No hay más líneas.
-               throw ios::failure("socket closed");
+               // Fin de archivo.
+               throw ios::failure("eof");
        }
 #ifdef DEBUG
-       cerr << __FILE__ << ":\tRecibiendo linea: " << buf << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ":\tRecibiendo linea: " << buf << endl;
 #endif // DEBUG
        String line(buf);
        // Si es la primera línea, es el request.
@@ -144,9 +148,10 @@ istream& operator>>(istream& is, HTTPRequest& req)
        return is;
 }
 
-ostream& operator<<(ostream& os, const HTTPRequest& req) {
+ostream& operator<<(ostream& os, const HTTPRequest& req) throw(sockerr) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator<<()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator<<()" << endl;
 #endif // DEBUG
        os << req.method_str() << " " << req.uri;
        if (req.query.length()) {
index 46cc55e11db4fe6adc760eb980fad69c409110ba..0177ae35cf44c9b5aef2f0c0f687569af5b4d85e 100644 (file)
@@ -40,14 +40,16 @@ namespace Server {
 
 HTTPResponse::~HTTPResponse(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
 HTTPResponse::HTTPResponse(const string& body, const string& version):
                HTTPMessage(body, version) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": body.length = " << body.length()
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": body.length = " << body.length()
                << " | version = " << version << endl;
 #endif // DEBUG
 }
@@ -55,34 +57,38 @@ HTTPResponse::HTTPResponse(const string& body, const string& version):
 HTTPResponse::HTTPResponse(const HTTPError& error):
                status_code(error.code) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": HTTPError(status_code = " << error.code
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": HTTPError(status_code = " << error.code
                << ", reason = " << HTTPMessage::reason(error.code) << ", desc = " << error.what()
                << ")" << endl;
 #endif // DEBUG
-       set_body(string("<plaqui><error desc=\"") + error.what() + "\" /></plaqui>");
+       set_body(string("<response desc=\"") + error.what() + "\" />");
 }
 
 HTTPResponse::HTTPResponse(unsigned status_code, const string& body):
                HTTPMessage(body), status_code(status_code) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": status_code = " << status_code
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": status_code = " << status_code
                << " | body.length = " << body.length() << endl;
 #endif // DEBUG
 }
 
 istream& operator>>(istream& is, HTTPResponse& resp)
-               throw (HTTPResponse::Error, ios::failure) {
+               throw (HTTPResponse::Error, sockerr, ios::failure) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator>>()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator>>()" << endl;
 #endif // DEBUG
        char buf[BUFSIZ];
        // Obtengo primera línea (request)
        if (!is.getline(buf, BUFSIZ)) {
-               // No hay mas líneas.
-               throw ios::failure("socket closed");
+               // Fin de archivo.
+               throw ios::failure("eof");
        }
 #ifdef DEBUG
-       cerr << __FILE__ << ":\tRecibiendo linea: " << buf << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ":\tRecibiendo linea: " << buf << endl;
 #endif // DEBUG
        String line(buf);
        // Si es la primera línea, es el request.
@@ -123,9 +129,10 @@ istream& operator>>(istream& is, HTTPResponse& resp)
        return is;
 }
 
-ostream& operator<<(ostream& os, const HTTPResponse& resp) {
+ostream& operator<<(ostream& os, const HTTPResponse& resp) throw(sockerr) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": operator<<()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": operator<<()" << endl;
 #endif // DEBUG
        os << "HTTP/" << resp.version << " " << resp.status_code << " "
                << HTTPMessage::reason(resp.status_code) << "\r\n";
index e46e692671fb7dc864a909e7862b4f338794ee49..b01f1a51ee6c7c153eeda30b7964f9d90f5efdba 100644 (file)
@@ -29,8 +29,6 @@
 #include <glibmm/timer.h>
 #include <sigc++/slot.h>
 #include <fstream>
-#include <iterator>
-#include <algorithm>
 #ifdef DEBUG
 #      include <iostream>
 #endif // DEBUG
@@ -43,7 +41,8 @@ namespace Server {
 
 Plant::~Plant(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
        // Termino transmisiones.
        Glib::Mutex::Lock lock(transmissions_mutex);
@@ -55,7 +54,8 @@ Plant::~Plant(void) {
 
 Plant::Plant(const string& filename): simulator(filename), filename(filename) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": constructor. filename = " << filename << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": constructor. filename = " << filename << endl;
 #endif // DEBUG
        // TODO plant
 /*     simulator.add_pump("bomba1");
@@ -73,7 +73,8 @@ Plant::Plant(const string& filename): simulator(filename), filename(filename) {
 
 void Plant::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": real_run." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": real_run." << endl;
 #endif // DEBUG
        while (!stop) {
                simulator_mutex.lock();
@@ -90,27 +91,57 @@ void Plant::real_run(void) {
 }
 
 bool Plant::transmission_start(string& host, Connection::Port& port) {
+#ifdef DEBUG
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << ": transmission_start(host = " << host <<
+                       ", port = " << port << ")." << endl;
+#endif // DEBUG
        Glib::Mutex::Lock lock(transmissions_mutex);
        for (TransmitterList::iterator i = transmissions.begin();
                        i != transmissions.end(); i++) {
                if (((*i)->get_host() == host) && ((*i)->get_port() == port)) {
+#ifdef DEBUG
+                       cerr << __FILE__ << "(" << __LINE__ << ")"
+                               << ": transmission_start ERROR: ya existe."
+                               << endl;
+#endif // DEBUG
                        return false;
                }
        }
        Transmitter* trans;
        try {
                trans = new Transmitter(host, port);
-       } catch (...) { // TODO - Hace mas selectivo el catch?
-               delete trans;
+       } catch (const sockerr& e) { // TODO - Hace mas selectivo el catch?
+#ifdef DEBUG
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << ": transmission_start ERROR (" << e.serrno()
+                       << "): " << e.errstr() << endl;
+#endif // DEBUG
+               //delete trans;
                return false;
+//     } catch (...) { // TODO - Hace mas selectivo el catch?
+//#ifdef DEBUG
+//             cerr << __FILE__ << "(" << __LINE__ << ")"
+//                     << ": transmission_start ERROR: desconocido."
+//                     << endl;
+//#endif // DEBUG
+//             //delete trans;
+//             return false;
        }
        transmissions.push_back(trans);
        trans->run();
+       host = trans->get_host();
+       port = trans->get_port();
        return true;
 }
 
 bool Plant::transmission_stop(const string& host,
                const Connection::Port& port) {
+#ifdef DEBUG
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << ": transmission_stop(host = " << host <<
+                       ", port = " << port << ")." << endl;
+#endif // DEBUG
        Glib::Mutex::Lock lock(transmissions_mutex);
        for (TransmitterList::iterator i = transmissions.begin();
                        i != transmissions.end(); i++) {
@@ -123,20 +154,23 @@ bool Plant::transmission_stop(const string& host,
 }
 
 bool Plant::set_open(const std::string& element, bool open) {
+#ifdef DEBUG
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << ": set_open(element = " << element <<
+                       ", open = " << open << ")." << endl;
+#endif // DEBUG
        Glib::Mutex::Lock lock(simulator_mutex);
        return simulator.set_open(element, open);
 }
 
 const string Plant::get_xml(void) const {
+#ifdef DEBUG
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       << ": get_xml()." << endl;
+#endif // DEBUG
        ostringstream oss;
-       try {
-               ifstream ifs(filename.c_str());
-               ifs >> noskipws;
-               copy(istream_iterator<char>(ifs), istream_iterator<char>(),
-                               ostream_iterator<char>(oss));
-       } catch (...) { // TODO hacerlo mas selectivo?
-               return "";
-       }
+       ifstream ifs(filename.c_str());
+       ifs >> oss.rdbuf();
        return oss.str();
 }
 
@@ -154,8 +188,8 @@ bool Plant::transmission_exists(const string& host,
 }
 */
 
-//const std::string& Plant::get_name(void) const {
-//     return name;
+//const std::string& Plant::get_filename(void) const {
+//     return filename;
 //}
 
 /// \todo FIXME esto deberia estar protegido por un mutex.
index 8185727b8efd1c6da896df2054fd3dfbf348bf41..22cc1a89d5a03a4b4bd5f524fd80efe7baf4a012 100644 (file)
@@ -43,14 +43,16 @@ const string Receiver::FRAME_END("</plantstatus>");
 
 Receiver::~Receiver(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
-Receiver::Receiver(const Connection::Port& port, const string& host):
-               Connection(sockbuf::sock_dgram, host, port) {
+Receiver::Receiver(const Connection::Port& port, const string& host)
+           throw(sockerr): Connection(sockbuf::sock_dgram, host, port) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": port = " << port
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": port = " << port
                << " | host = " << host << endl;
 #endif // DEBUG
        //socket->bind(port);
@@ -60,12 +62,21 @@ Receiver::Receiver(const Connection::Port& port, const string& host):
 // XXX EL XML DEBE EMPEZAR Y FINALIZAR EN UNA LINEA SEPARADA.
 void Receiver::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": real_run." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": real_run." << endl;
 #endif // DEBUG
        char buf[BUFSIZ];
        bool in_frame = false;
        stringstream ss;
-       while (!stop && socket.getline(buf, BUFSIZ)) {
+       while (!stop) {
+               try {
+                       if (!socket.getline(buf, BUFSIZ)) {
+                               return; // Se terminó la transmision.
+                       }
+               } catch (const sockerr& e) {
+                       error(e.serrno(), e.errstr());
+                       return;
+               }
                string sbuf = buf;
                if (in_frame) {
                        string::size_type pos = sbuf.find(FRAME_END);
index 68296e4442e7762e6bc3493cf25eaa5a63a2d6ab..c134b834fbe0709a0314b241a72d93b9cce74661 100644 (file)
@@ -40,20 +40,23 @@ namespace Server {
 
 Runnable::~Runnable(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor(this = " << this << ")"
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor(this = " << this << ")"
                << endl;
 #endif // DEBUG
 }
 
 Runnable::Runnable(void): thread(0), stop(false) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": constructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": constructor." << endl;
 #endif // DEBUG
 }
 
 void Runnable::static_run(Runnable* runner) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": static_run(runner = " << runner << ")"
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": static_run(runner = " << runner << ")"
                << endl;
 #endif // DEBUG
        runner->real_run();
@@ -63,7 +66,8 @@ void Runnable::static_run(Runnable* runner) {
 
 void Runnable::run(bool detach) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": run(detach = " << detach << ")" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": run(detach = " << detach << ")" << endl;
 #endif // DEBUG
        // Si vamos a correr la tarea en un thread.
        if (detach) {
@@ -81,7 +85,8 @@ void Runnable::run(bool detach) {
 
 void Runnable::finish(bool attach) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": finish(attach = " << attach << ")" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": finish(attach = " << attach << ")" << endl;
 #endif // DEBUG
        stop = true;
        if (attach) {
@@ -93,6 +98,10 @@ Runnable::SignalFinished& Runnable::signal_finished(void) {
        return finished;
 }
 
+Runnable::SignalError& Runnable::signal_error(void) {
+       return error;
+}
+
 } // namespace Server
 
 } // namespace PlaQui
index 4247d9124297fda8dfbc22326379983da3ae8ee7..340c2f05801dbeebdc216f63a056e851f5413b16 100644 (file)
@@ -29,8 +29,8 @@
 #include "plaqui/server/connection.h"
 #include "plaqui/server/controlserver.h"
 #include <sigc++/class_slot.h>
-// FIXME - sacar sstream (a menos que se necesite)
 #include <sstream>
+#include <exception>
 #ifdef DEBUG
 #      include "plaqui/server/string.h"
 #      include <iostream>
@@ -44,7 +44,8 @@ namespace Server {
 
 Server::~Server(void) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": destructor." << endl;
 #endif // DEBUG
        // Termino plantas.
        Glib::Mutex::Lock lock(plants_mutex);
@@ -53,10 +54,11 @@ Server::~Server(void) {
        }
 }
 
-Server::Server(const string& plant_filename, const Connection::Port& port):
-               TCPServer(port) {
+Server::Server(const string& plant_filename, const Connection::Port& port)
+               throw(sockerr): TCPServer(port) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": port = " << port << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": port = " << port << endl;
 #endif // DEBUG
        // FIXME
        Glib::Mutex::Lock lock(plants_mutex);
@@ -68,10 +70,10 @@ Server::Server(const string& plant_filename, const Connection::Port& port):
        plants["default"]->run();
 }
 
-Connection* Server::new_connection(
-               const sockbuf::sockdesc& sd) {
+Connection* Server::new_connection(const sockbuf::sockdesc& sd) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": new_connection(sd = " << sd.sock << ")"
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": new_connection(sd = " << sd.sock << ")"
                << endl;
 #endif // DEBUG
        ControlServer* connection = new ControlServer(sd);
@@ -84,15 +86,10 @@ Connection* Server::new_connection(
        return connection;
 }
 
-void Server::on_plant_updated(const Plant* plant) {
-#ifdef DEBUG
-       cerr << __FILE__ << ": on_plant_updated(plant = " << plant << ")." << endl;
-#endif // DEBUG
-}
-
 void Server::on_plant_finished(const char* plant) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": on_plant_finished(plant_name = " << plant << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": on_plant_finished(plant_name = " << plant << endl;
 #endif // DEBUG
        Glib::Mutex::Lock lock(plants_mutex);
        plants.erase(plant);
@@ -102,7 +99,8 @@ void Server::on_plant_finished(const char* plant) {
 void Server::on_control_command_received(const Command& command,
                ControlServer* controlserver) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": on_control_command_received(target = "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": on_control_command_received(target = "
                << command.get_target() << ", command = " << command.get_command()
                << ", args = [" << String::join(command.get_args(), ", ") << "])"
                << endl;
@@ -173,7 +171,7 @@ HTTPResponse* Server::cmd_server_status(void) const {
        // FIXME
        stringstream xml;
        xml << "<serverstatus>" << endl;
-       xml << "\t<version>0.9</version>" << endl;
+       xml << "\t<version>" VERSION "</version>" << endl;
        xml << "\t<authors>" << endl;
        xml << "\t\t<author>Nicolás Dimov</author>" << endl;
        xml << "\t\t<author>Leandro Lucarella</author>" << endl;
@@ -313,6 +311,7 @@ HTTPResponse* Server::cmd_plant_get(const Command& command) {
                return new HTTPResponse(HTTPMessage::NOT_FOUND,
                                string("<response desc=\"No existe la planta ") + plant + "\" />");
        }
+       // TODO try/catch?
        string xml = plants[plant]->get_xml();
        if (xml.length()) {
                return new HTTPResponse(HTTPMessage::OK, xml);
index e78e53ca82e65012b5c35fbcd08f4d38308140ed..ffbdead609cf9ae0ac28fe20fef4f232ae3780fc 100644 (file)
@@ -39,7 +39,8 @@ namespace Server {
 
 TCPServer::~TCPServer(void) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": destructor." << endl;
 #endif // DEBUG
        Glib::Mutex::Lock lock(connections_mutex);
        for (ConnectionList::iterator con = connections.begin();
@@ -48,9 +49,11 @@ TCPServer::~TCPServer(void) {
        }
 }
 
-TCPServer::TCPServer(const Connection::Port& port): socket(sockbuf::sock_stream) {
+TCPServer::TCPServer(const Connection::Port& port) throw(sockerr):
+               socket(sockbuf::sock_stream) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": port = " << port << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": port = " << port << endl;
 #endif // DEBUG
        // FIXME
        //cerr << "recvtimeout = " << socket.recvtimeout(1) << endl;
@@ -59,32 +62,36 @@ TCPServer::TCPServer(const Connection::Port& port): socket(sockbuf::sock_stream)
        //cerr << "sendtimeout = " << socket.sendtimeout(1) << endl;
        socket.bind(port);
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": escuchando en " << socket.localhost()
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": escuchando en " << socket.localhost()
                << ":" << socket.localport() << "." << endl;
 #endif // DEBUG
        socket.listen(MAX_PENDING_CONNECTIONS);
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": [despues de listen()] escuchando en "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": [despues de listen()] escuchando en "
                << socket.localhost() << ":" << socket.localport() << "." << endl;
 #endif // DEBUG
 }
 
-void TCPServer::finish(bool attach) {
+/*void TCPServer::finish(bool attach) {
        //socket_mutex.lock();
        socket.shutdown(sockbuf::shut_readwrite);
        //socket_mutex.unlock();
        Runnable::finish(attach);
-}
+}*/
 
 void TCPServer::on_connection_finished(Connection* connection) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": on_connection_finished(connection = "
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": on_connection_finished(connection = "
                << connection << ")" << endl;
 #endif // DEBUG
        Glib::Mutex::Lock lock(connections_mutex);
        connections.remove(connection);
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": lista de conexiones" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": lista de conexiones" << endl;
        for (ConnectionList::const_iterator i = connections.begin();
                        i != connections.end(); i++) {
                cerr << "\t " << *i << endl;
@@ -95,21 +102,29 @@ void TCPServer::on_connection_finished(Connection* connection) {
 /// \todo TODO: ver tema de timeout o como salir de un accept().
 void TCPServer::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": real_run()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": real_run()" << endl;
 #endif // DEBUG
        Connection* connection;
        while (!stop) {
                // Forma grasa de salir del accept: crear conexion que salga al toque.
-               connection = new_connection(socket.accept());
+               try {
+                       connection = new_connection(socket.accept());
+               } catch (const sockerr& e) { // No se si el accept() puede fallar.
+                       error(e.serrno(), e.errstr());
+                       continue; // Supongo que puede seguir aceptando conexiones.
+               }
 #ifdef DEBUG
-               cerr << __FILE__ <<  ": real_run(): connection = " << connection
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       <<  ": real_run(): connection = " << connection
                        << endl;
 #endif // DEBUG
                Glib::Mutex::Lock lock(connections_mutex);
                // XXX connections_mutex.lock();
                connections.push_back(connection);
 #ifdef DEBUG
-               cerr << __FILE__ <<  ": real_run(): lista de conexiones" << endl;
+               cerr << __FILE__ << "(" << __LINE__ << ")"
+                       <<  ": real_run(): lista de conexiones" << endl;
                for (ConnectionList::const_iterator i = connections.begin();
                                i != connections.end(); i++) {
                        cerr << "\t " << *i << endl;
@@ -129,7 +144,8 @@ void TCPServer::real_run(void) {
 
 bool TCPServer::disconnect(const std::string& host, const Connection::Port& port) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": disconnect(host = " << host
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": disconnect(host = " << host
                << ", port = " << port << ")" << endl;
 #endif // DEBUG
        Glib::Mutex::Lock lock(connections_mutex);
@@ -143,9 +159,11 @@ bool TCPServer::disconnect(const std::string& host, const Connection::Port& port
        return false;
 }
 
+/// \todo TODO Hay que reemplazarlo por una lista generica.
 TCPServer::ConnectionInfoList TCPServer::get_connected(void) {
 #ifdef DEBUG
-       cerr << __FILE__ <<  ": get_connected()" << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               <<  ": get_connected()" << endl;
 #endif // DEBUG
        TCPServer::ConnectionInfoList cl;
        Glib::Mutex::Lock lock(connections_mutex);
index de940f98c187097db7a050c543e96876781c0b8c..b59992edfd6c44dd584b45ac041034a5f2537d34 100644 (file)
@@ -41,41 +41,55 @@ namespace Server {
 
 Transmitter::~Transmitter(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": destructor." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": destructor." << endl;
 #endif // DEBUG
 }
 
-Transmitter::Transmitter(string& _host, Connection::Port& _port):
-               Connection(sockbuf::sock_dgram, _host, _port) {
+Transmitter::Transmitter(const string& _host, const Connection::Port& _port)
+               throw(sockerr): Connection(sockbuf::sock_dgram, _host, _port) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": _host = " << _host
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": _host = " << _host
                << " | _port = " << _port << endl;
 #endif // DEBUG
        socket->connect(host.c_str(), port);
-       // Reasigno el host y puerto bien, tanto de este objeto como los que se
-       // environ para indicar su valor correcto.
-       host  = socket->peerhost();
-       port  = socket->peerport();
-       _host = socket->peerhost();
-       _port = socket->peerport();
+       // Reasigno el host y puerto bien.
+       host = socket->peerhost();
+       port = socket->peerport();
+#ifdef DEBUG
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": (real) host = " << _host
+               << " | port = " << _port << endl;
+#endif // DEBUG
 }
 
 /// \todo debría dar una excepción (?)
 void Transmitter::real_run(void) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": real_run()." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": real_run()." << endl;
 #endif // DEBUG
        // No hace nada, porque solo actua cuando se manda algo con send().
        while (!stop) {
-               Glib::usleep(1000);
+               Glib::usleep(500000); // 1/2 segundo
        }
 }
 
 void Transmitter::send(const string& data) {
 #ifdef DEBUG
-       cerr << __FILE__ << ": send(data = " << data << ")." << endl;
+       cerr << __FILE__ << "(" << __LINE__ << ")"
+               << ": send(data = " << data << ")." << endl;
 #endif // DEBUG
-       socket << data << flush;
+       if (stop) {
+               return;
+       }
+       try {
+               socket << data << flush;
+       } catch (const sockerr& e) {
+               error(e.serrno(), e.errstr());
+               stop = true;
+       }
 }
 
 } // namespace Server
index 025269fcaccc5aadac3da1530db1d34e4ac75af8..60b952fe649a9d13fb5faa5635263225072dfb0e 100644 (file)
@@ -46,7 +46,7 @@ server_test_LDADD = \
        @PACKAGE_LIBS@ \
        -lsocket++ \
        ../src/libplaquiserver.a \
-       ../../Model/src/model.a
+       ../../Model/src/libplaquimodel.a
 
 client_test_LDADD = \
        @PACKAGE_LIBS@ \
index 88027e16442410bf37b1a72546f2733151c13d37..9ff2fbb54f9c9fe041032c630b0f4ee12888b36d 100644 (file)
@@ -36,6 +36,14 @@ using namespace PlaQui::Server;
 
 ControlClient* client = NULL;
 
+void on_error(const Runnable::Error& code, const string& desc) {
+       cerr << "--------------------------------------------------------" << endl;
+       cerr << "Error en el cliente:" << endl;
+       cerr << "Código: " << code << endl;
+       cerr << "Descripción: " << desc << endl;
+       cerr << "--------------------------------------------------------" << endl;
+}
+
 void on_finished(void) {
        client = NULL;
 }
@@ -87,6 +95,7 @@ int main(int argc, char* argv[]) {
        try {
                // Corre el cliente.
                client = new ControlClient(host, port);
+               client->signal_error().connect(SigC::slot(on_error));
                client->signal_finished().connect(SigC::slot(on_finished));
                client->signal_connected().connect(SigC::slot(on_connected));
                client->signal_ok_received().connect(SigC::slot(on_ok_received));
index bdb6190c7b88e29c0f16de19085307134c70290f..25d01a676dcbaf258cd9ab1222c02b58790775fe 100644 (file)
 using namespace std;
 using namespace PlaQui::Server;
 
+void on_error(const Runnable::Error& code, const string& desc) {
+       cerr << "--------------------------------------------------------" << endl;
+       cerr << "Error en el servidor:" << endl;
+       cerr << "Código: " << code << endl;
+       cerr << "Descripción: " << desc << endl;
+       cerr << "--------------------------------------------------------" << endl;
+}
+
 int main(int argc, char* argv[]) {
 
        // Termina con mas informacion si hay una excepcion no manejada.
@@ -60,10 +68,10 @@ int main(int argc, char* argv[]) {
        // Inicializa threads.
        Glib::thread_init();
 
+       Server* server = NULL;
        try {
-               // Corre el server.
-               Server server(filename, port);
-               server.run(false);
+               // Crea el server (empieza a escuchar).
+               server = new Server(filename, port);
        } catch (const sockerr& e) {
                cerr << "Socket Error: " << e.operation() << " | serrno = "
                        << e.serrno() << " | errstr = " << e.errstr() << endl;
@@ -82,13 +90,26 @@ int main(int argc, char* argv[]) {
                } else if (e.benign()) {
                        cerr << "Es: recoverable read/write error like EINTR etc." << endl;
                }
+               return e.serrno();
        } catch (const exception& e) {
                cerr << "Error: " << e.what() << endl;
+               return 1;
        } catch (const char* e) {
                cerr << "Error: " << e << endl;
+               return 2;
        } catch (...) {
                cerr << "Error desconocido!" << endl;
+               return 3;
        }
 
+       // Conecto señal para atender errores.
+       server->signal_error().connect(SigC::slot(on_error));
+
+       // Corre el server.
+       server->run(false);
+
+       // Como no detachee el server, lo tengo que eliminar a mano.
+       delete server;
+
        return 0;
 }