From: Leandro Lucarella Date: Sun, 19 Oct 2003 05:23:25 +0000 (+0000) Subject: - Muchas pequeñas correcciones. X-Git-Tag: svn_import~401 X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/commitdiff_plain/a9cb053146d2f1dc73e536ed87597f458deebea3?ds=inline - Muchas pequeñas correcciones. - Algunos grandes cambios: - Se agrega soporte de threads a Runneable. - Estan funcionando Server y ControlServer de forma básica. Server puede atender peticiones y cuando se conecta alguien crea un nuevo ControlServer que maneja la conexión (falta liberar memoria, porque por ahora solo se puede salir con Ctr-C). ControlServer recibe línea por línea hasta que una línea sea vacía (detección simple de cabeceras HTTP). - Se agrega un test del servidor: server_test.cpp. - El diagrama de clases queda un poco desactualizado (y tal vez deprecated, debería pasarlo a Dia así queda todo con el mismo formato). --- diff --git a/Server/src/Makefile b/Server/src/Makefile index 146f7a8..861231c 100644 --- a/Server/src/Makefile +++ b/Server/src/Makefile @@ -26,31 +26,50 @@ # # Opciones para el compilador. -CXXFLAGS=-ansi -pedantic -Wall -g -LDFLAGS=-lsocket++ +CXXFLAGS=-ansi -pedantic -Wall `pkg-config --cflags glibmm-2.0` `pkg-config --cflags gthread-2.0` +CXXFLAGS+=-g -DDEBUG +#CXXFLAGS+=-g +#CXXFLAGS+=-O3 +LDFLAGS=-lsocket++ `pkg-config --libs glibmm-2.0` `pkg-config --libs gthread-2.0` TARGETS=connection.o controlclient.o controlserver.o receiver.o transmitter.o \ server.o +TESTS=server_test + # Regla por defecto. -all: $(TARGETS) +all: $(TARGETS) $(TESTS) runnable_h=runnable.h +objects+=runnable.o +runnable.o: $(runnable_h) runnable.cpp connection_h=$(runnable_h) connection.h -connection.o: $(connection_h) +objects+=connection.o +connection.o: $(connection_h) connection.cpp controlclient_h=$(connection_h) controlclient.h -controlclient.o: $(controlclient_h) +objects+=controlclient.o +controlclient.o: $(controlclient_h) controlclient.cpp controlserver_h=$(connection_h) controlserver.h -controlserver.o: $(controlserver_h) +objects+=controlserver.o +controlserver.o: $(controlserver_h) controlserver.cpp receiver_h=$(connection_h) receiver.h -receiver.o: $(receiver_h) +objects+=receiver.o +receiver.o: $(receiver_h) receiver.cpp transmitter_h=$(connection_h) transmitter.h -transmitter.o: $(transmitter_h) +objects+=transmitter.o +transmitter.o: $(transmitter_h) transmitter.cpp + +server_h=$(controlserver_h) $(transmitter_h) server.h +objects+=server.o +server.o: $(server_h) server.cpp + +# Tests +server_test: $(objects) server_test.cpp clean: - rm -f $(TARGETS) *.o + rm -f $(TARGETS) $(TESTS) *.o diff --git a/Server/src/connection.cpp b/Server/src/connection.cpp index 086548a..6d48727 100644 --- a/Server/src/connection.cpp +++ b/Server/src/connection.cpp @@ -30,9 +30,18 @@ using namespace Plaqui; +Connection::Connection(const sockbuf::sockdesc& sd): + socket(sd) { +#ifdef DEBUG + std::cerr << __FILE__ << ": sd = " << sd.sock << std::endl; +#endif // DEBUG +} + +/* Connection::Connection(const sockinetbuf& sb): socket(sb) { } +*/ Connection::Connection(sockbuf::type type): socket(type) { diff --git a/Server/src/connection.h b/Server/src/connection.h index 306e273..df4cf2c 100644 --- a/Server/src/connection.h +++ b/Server/src/connection.h @@ -38,6 +38,9 @@ namespace Plaqui { protected: + /// Tamaño del buffer usado para enviar y recibir datos. + static const int BUFFER_SIZE = 4096; + /// Socket a usar en la conexión. iosockinet socket; @@ -48,12 +51,19 @@ namespace Plaqui { */ virtual ~Connection(void) {} + /** + * Constructor. + * + * \param socket Descriptor de socket a usar en la conexión. + */ + Connection(const sockbuf::sockdesc& sd); + /** * Constructor. * * \param socket Socket a usar en la conexión. */ - Connection(const sockinetbuf& sb); + //Connection(const sockinetbuf& sb); /** * Constructor. diff --git a/Server/src/controlclient.cpp b/Server/src/controlclient.cpp index 3ad35f8..3ad70b6 100644 --- a/Server/src/controlclient.cpp +++ b/Server/src/controlclient.cpp @@ -26,11 +26,25 @@ // #include "controlclient.h" +// XXX +#include using namespace Plaqui; ControlClient::ControlClient(std::string host, int port): Connection(sockbuf::sock_stream) { + // FIXME - poner en run(). socket->connect(host.c_str(), port); } +void ControlClient::real_run(void) { + // FIXME - debería tirar una excepción? + if (!socket->is_open()) { + std::cerr << "No se pudo conectar a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } else { + std::cerr << "Conectado a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } +} + diff --git a/Server/src/controlclient.h b/Server/src/controlclient.h index ce32d86..adbfb5b 100644 --- a/Server/src/controlclient.h +++ b/Server/src/controlclient.h @@ -36,6 +36,13 @@ namespace Plaqui { /// Conexión para enviar comandos de control a una planta. class ControlClient: public Connection { + private: + + /** + * Atiende la conexión. + */ + virtual void real_run(void); + public: /** diff --git a/Server/src/controlserver.cpp b/Server/src/controlserver.cpp index c9007c5..4b88849 100644 --- a/Server/src/controlserver.cpp +++ b/Server/src/controlserver.cpp @@ -26,9 +26,43 @@ // #include "controlserver.h" +#include +#include using namespace Plaqui; -//ControlServer::ControlServer(const iosockinet& socket) { -//} +ControlServer::ControlServer(const sockbuf::sockdesc& sd): + Connection(sd) { +#ifdef DEBUG + std::cerr << __FILE__ << ": sd = " << sd.sock << std::endl; +#endif // DEBUG +} + +void ControlServer::real_run(void) { + // FIXME se tiene que ir a la clase para poder frenarlo desde afuera. + bool stop = false; + char buf[BUFFER_SIZE]; + while (!stop) { + stringstream sstr; + while (!stop && socket.getline(buf, BUFFER_SIZE)) { +#ifdef DEBUG + std::cerr << "Reciviendo: " << buf << std::endl; +#endif // DEBUG + // Si tiene contenido, lo almaceno en el buffer de comandos. + if (strlen(buf)) { + sstr << buf << endl; + // Si viene la línea vacía, terminan las cabeceras HTTP. + } else { + stop = true; + } + } + // Manda mensaje a la planta. + //dispatch_command(parse_command(sstr.str())); +#ifdef DEBUG + std::cerr << "Recivido:" << std::endl << sstr.str() << std::endl; +#endif // DEBUG + // FIXME - hacer respuesta XML. + socket << "Ok!" << std::endl; + } +} diff --git a/Server/src/controlserver.h b/Server/src/controlserver.h index c973134..28cd032 100644 --- a/Server/src/controlserver.h +++ b/Server/src/controlserver.h @@ -36,6 +36,13 @@ namespace Plaqui { /// Conexión para recibir comandos de control para una planta. class ControlServer: public Connection { + protected: + + /** + * Atiende la conexión. + */ + virtual void real_run(void); + public: /** @@ -46,9 +53,9 @@ namespace Plaqui { /** * Constructor. * - * \param socket Socket a usar para recibir comandos. + * \param sd Descriptor del socket a usar para recibir comandos. */ - ControlServer(const sockinetbuf& socket): Connection(socket) {} + ControlServer(const sockbuf::sockdesc& sd); }; diff --git a/Server/src/receiver.cpp b/Server/src/receiver.cpp index 172a19f..0f9f32c 100644 --- a/Server/src/receiver.cpp +++ b/Server/src/receiver.cpp @@ -27,9 +27,22 @@ #include "receiver.h" -/* -Receiver::Receiver(int port, std::string host): Connection(sockbuf::dgram) { +using namespace Plaqui; + +Receiver::Receiver(int port, std::string host): + Connection(sockbuf::sock_dgram) { + // FIXME - deberia ir en run(). socket->bind(port); } -*/ + +void Receiver::run(void) { + // FIXME - debería tirar una excepción? + if (!socket->is_open()) { + std::cerr << "No se pudo conectar a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } else { + std::cerr << "Conectado a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } +} diff --git a/Server/src/receiver.h b/Server/src/receiver.h index 8be4e30..6de8634 100644 --- a/Server/src/receiver.h +++ b/Server/src/receiver.h @@ -50,8 +50,12 @@ namespace Plaqui { * \param port Puerto por el cual recibir estado de la planta. * \param host Host del cual recibir el estado de la planta. */ - Receiver(int port = 7528 /*, std::string host = "localhost"*/): - Connection(sockbuf::sock_dgram) { socket->bind(port); } + Receiver(int port = 7528, std::string host = "localhost"); + + /** + * Recibe la transmisión. + */ + virtual void run(void); }; diff --git a/Server/src/runnable.cpp b/Server/src/runnable.cpp new file mode 100644 index 0000000..d962980 --- /dev/null +++ b/Server/src/runnable.cpp @@ -0,0 +1,59 @@ +// vim: set noexpandtab tabstop=4 shiftwidth=4: +//---------------------------------------------------------------------------- +// PlaQui +//---------------------------------------------------------------------------- +// This file is part of PlaQui. +// +// PlaQui is free software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// PlaQui is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along +// with PlaQui; if not, write to the Free Software Foundation, Inc., 59 Temple +// Place, Suite 330, Boston, MA 02111-1307 USA +//---------------------------------------------------------------------------- +// Creado: dom oct 19 01:13:33 ART 2003 +// Autores: Leandro Lucarella +//---------------------------------------------------------------------------- +// +// $Id$ +// + +#include "runnable.h" +#include +#include +#ifdef DEBUG +# include +#endif // DEBUG + +using namespace Plaqui; + +Runnable::Runnable(void): thread(0) { +} + +void Runnable::run(bool detach) { +#ifdef DEBUG + std::cerr << __FILE__ << ": detach = " << detach << std::endl; +#endif // DEBUG + // Si vamos a correr la tarea en un thread. + if (detach) { + // Nos aseguramos de tener threads. + if (!Glib::thread_supported()) { + Glib::thread_init(); + } + // Corremos el thread. + thread = Glib::Thread::create( + SigC::slot_class(*this, &Runnable::real_run), true); + // Si no corremos la tarea normalmente. + } else { + real_run(); + } + +} + diff --git a/Server/src/runnable.h b/Server/src/runnable.h index 04cb094..39a221f 100644 --- a/Server/src/runnable.h +++ b/Server/src/runnable.h @@ -28,15 +28,41 @@ #ifndef PLAQUI_RUNNABLE_H #define PLAQUI_RUNNABLE_H +#include + namespace Plaqui { /// ealizauna tarea (generalmente en un thread). class Runnable { + private: + // Thread en el cual correr la tarea. + Glib::Thread* thread; + + protected: + + /// Realiza la terea. + virtual void real_run(void) = 0; + public: - /// Realiza la tarea. - virtual void run(void) = 0; + /** + * Destructor. + */ + virtual ~Runnable(void) {} + + /** + * Constructor. + */ + Runnable(void); + + /** + * Comienza la tares. + * + * \param detach Si es true se corre en un thread propio. Si no no + * retorna hasta que finaliza. + */ + virtual void run(bool detach = true); }; diff --git a/Server/src/server.cpp b/Server/src/server.cpp index bbf41c0..c0d0341 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -26,24 +26,40 @@ // #include "server.h" +#ifdef DEBUG +# include +#endif // DEBUG using namespace Plaqui; Server::Server(int port): socket(sockbuf::sock_stream) { -#warning Not implemented! - // TODO + socket.bind(port); +#ifdef DEBUG + std::cerr << "Escuchando en " << socket.localhost() << + ":" << socket.localport() << "." << std::endl; +#endif // DEBUG + socket.listen(); } bool Server::start_transmission(std::string host, int port) { -#warning Not implemented! // TODO return false; } bool Server::stop_transmission(std::string host, int port) { -#warning Not implemented! // TODO return false; } +void Server::real_run(void) { + // FIXME se tiene que ir a la clase para poder frenarlo desde afuera. + bool stop = false; + ControlServer* control_server; + while (!stop) { + control_server = new ControlServer(socket.accept()); + controllers.push_back(control_server); + control_server->run(); + } +} + diff --git a/Server/src/server.h b/Server/src/server.h index ccd2c0e..eccbd9a 100644 --- a/Server/src/server.h +++ b/Server/src/server.h @@ -51,7 +51,7 @@ namespace Plaqui { typedef std::list TransmitterList; /// Socket para escuchar conexiones. - sockbuf socket; + sockinetbuf socket; /// Conexiones de control. ControllerList controllers; @@ -59,6 +59,11 @@ namespace Plaqui { /// Transmisiones del estado de las plantas. TransmitterList transmissions; + /** + * Entra en el loop para atender conexiones. + */ + virtual void real_run(void); + public: /** diff --git a/Server/src/server_test.cpp b/Server/src/server_test.cpp new file mode 100644 index 0000000..e0753b9 --- /dev/null +++ b/Server/src/server_test.cpp @@ -0,0 +1,61 @@ +// vim: set noexpandtab tabstop=4 shiftwidth=4: +//---------------------------------------------------------------------------- +// PlaQui +//---------------------------------------------------------------------------- +// This file is part of PlaQui. +// +// PlaQui is free software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// PlaQui is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along +// with PlaQui; if not, write to the Free Software Foundation, Inc., 59 Temple +// Place, Suite 330, Boston, MA 02111-1307 USA +//---------------------------------------------------------------------------- +// Creado: Sat Oct 18 18:18:36 2003 +// Autores: Leandro Lucarella +//---------------------------------------------------------------------------- +// +// $Id$ +// + +#include "server.h" +#include +#include +#include +#include + +using namespace std; +using namespace Plaqui; + +int main(int argc, char* argv[]) { + + // Termina con mas informacion si hay una excepcion no manejada. + std::set_terminate (__gnu_cxx::__verbose_terminate_handler); + + // Necesita argumentos. + if (argc != 2) { + cerr << "Faltan argumentos: " << endl; + cerr << "\t" << argv[0] << " port" << endl; + return 1; + } + + // Obtengo puerto. + unsigned port; + { + stringstream str(argv[1]); + str >> port; + } + + // Corre el server. + Server server(port); + server.run(false); + + return 0; +} diff --git a/Server/src/transmitter.cpp b/Server/src/transmitter.cpp index b8635fa..bd6d06b 100644 --- a/Server/src/transmitter.cpp +++ b/Server/src/transmitter.cpp @@ -33,7 +33,18 @@ using namespace Plaqui; Transmitter::Transmitter(std::string host, int port): Connection(sockbuf::sock_dgram) { -#warning Not implemented! + // FIXME - deberia ir en run(). socket->connect(host.c_str(), port); } +void Transmitter::real_run(void) { + // FIXME - debería tirar una excepción? + if (!socket->is_open()) { + std::cerr << "No se pudo conectar a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } else { + std::cerr << "Conectado a " << socket->peerhost() << + ":" << socket->peerport() << "." << std::endl; + } +} + diff --git a/Server/src/transmitter.h b/Server/src/transmitter.h index 2100c1f..2b622b8 100644 --- a/Server/src/transmitter.h +++ b/Server/src/transmitter.h @@ -36,6 +36,13 @@ namespace Plaqui { /// Conexión para transmitir el estado de una planta. class Transmitter: public Connection { + private: + + /** + * Comienza a transmitir. + */ + virtual void real_run(void); + public: /**