#
# 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
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) {
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;
*/
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.
//
#include "controlclient.h"
+// XXX
+#include <iostream>
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;
+ }
+}
+
/// 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:
/**
//
#include "controlserver.h"
+#include <cstring>
+#include <sstream>
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;
+ }
+}
/// 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:
/**
/**
* 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);
};
#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;
+ }
+}
* \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);
};
--- /dev/null
+// 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 <llucare@fi.uba.ar>
+//----------------------------------------------------------------------------
+//
+// $Id$
+//
+
+#include "runnable.h"
+#include <sigc++/class_slot.h>
+#include <glibmm/thread.h>
+#ifdef DEBUG
+# include <iostream>
+#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();
+ }
+
+}
+
#ifndef PLAQUI_RUNNABLE_H
#define PLAQUI_RUNNABLE_H
+#include <glibmm/thread.h>
+
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);
};
//
#include "server.h"
+#ifdef DEBUG
+# include <iostream>
+#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();
+ }
+}
+
typedef std::list<Transmitter*> TransmitterList;
/// Socket para escuchar conexiones.
- sockbuf socket;
+ sockinetbuf socket;
/// Conexiones de control.
ControllerList controllers;
/// Transmisiones del estado de las plantas.
TransmitterList transmissions;
+ /**
+ * Entra en el loop para atender conexiones.
+ */
+ virtual void real_run(void);
+
public:
/**
--- /dev/null
+// 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 <llucare@fi.uba.ar>
+//----------------------------------------------------------------------------
+//
+// $Id$
+//
+
+#include "server.h"
+#include <socket++/sockinet.h>
+#include <iostream>
+#include <sstream>
+#include <exception>
+
+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;
+}
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;
+ }
+}
+
/// Conexión para transmitir el estado de una planta.
class Transmitter: public Connection {
+ private:
+
+ /**
+ * Comienza a transmitir.
+ */
+ virtual void real_run(void);
+
public:
/**