#include "plaqui/server/runnable.h"
#include "plaqui/server/connection.h"
#include <socket++/sockinet.h>
+#include <sigc++/signal.h>
#include <list>
+#include <vector>
namespace PlaQui {
namespace Server {
/**
- * Servidor de plantas químicas.
- * Maneja muchas conexiones, de control o de transmisión.
+ * Servidor genéríco TCP/IP.
+ *
+ * Maneja muchas conexiones, en threads. En términos generales todo lo que
+ * hace es algo parecido a esto:
+ * \code
+ * while (!stop) {
+ * Connection* conexion = new_connection(accept());
+ * connections.push_back(conexion);
+ * }
+ * \endcode
+ *
+ * new_connection() es un método virtual puro que hay que definir en las
+ * subclases para hacer un servidor específico que trabaje con un protocolo
+ * determinado. new_connection() devuelve un puntero a una
+ * \ref Connection "conexión".
+ *
+ * on_connection_finished() maneja la
+ * \ref Runnable::signal_finished "señal para indicar que una conexión terminó"
+ * para eliminarla de la \ref connections "lista de conexiones".
*/
class TCPServer: public Runnable {
+ /////////////////////////////////////////////////////////////////////
// Constantes.
private:
/// Cantidad máxima de conexiones pendientes.
static const unsigned MAX_PENDING_CONNECTIONS = 10;
+ /////////////////////////////////////////////////////////////////////
// Tipos.
private:
/// Lista de conexiones de control.
typedef std::list<Connection*> ConnectionList;
+ public:
+
+ /// Información sobre una conexión de contro.
+ struct ConnectionInfo {
+ /// Host.
+ std::string host;
+ /// Port.
+ Connection::Port port;
+ };
+
+ /// Lista de información de conexiones de control.
+ typedef std::vector<ConnectionInfo> ConnectionInfoList;
+
+ /////////////////////////////////////////////////////////////////////
+ /// \name Señales
+ //@{
+
+ public:
+
+ /// Tipo de señal para indicar que se inició una conexión.
+ typedef SigC::Signal2<void, const std::string&,
+ const Connection::Port&> SignalConnectionOpened;
+
+ /// Obtiene la señal que avisa que se inició una conexión.
+ SignalConnectionOpened& signal_connection_opened(void);
+
+ //@}
+
+ /////////////////////////////////////////////////////////////////////
// Atributos.
- private:
+ protected:
/// Socket para escuchar conexiones.
sockinetbuf socket;
- /// Mutex para las conexiones.
- Glib::Mutex connections_mutex;
+ private:
+
+ /// Señal que indica que se inició una conexión.
+ SignalConnectionOpened _connection_opened;
/// Conexiones de control.
ConnectionList connections;
+ /// Mutex para las conexiones.
+ Glib::Mutex connections_mutex;
+
+ /////////////////////////////////////////////////////////////////////
// Métodos.
private:
/**
* Entra en el loop para atender conexiones.
*/
- virtual void real_run(void);
+ virtual void real_run(void) throw();
protected:
*
* \param port Puerto en el cual escuchar.
*/
- TCPServer(int port);
+ TCPServer(const Connection::Port& port) throw(sockerr);
+
+ /**
+ * Finaliza la tarea.
+ *
+ * \note Para saber cuando la tarea fue finalizada puede utilizar
+ * la señal signal_finished().
+ */
+ virtual void finish(void);
/**
* Se encarga de borrar una conexión de la lista cuando finaliza.
*/
void on_connection_finished(Connection* connection);
+ /**
+ * Detiene una conexión.
+ */
+ bool disconnect(const std::string& host,
+ const Connection::Port& port);
+
+ /**
+ * Obtiene una lista conexiones de control abiertas.
+ */
+ ConnectionInfoList get_connected(void);
+
};
}