server.h 9.27 KB
/** @file 
* \brief Header de la clase Server
* \author Imanol Barba Sabariego
* \date 11/06/2013
*
* En este fichero se define la clase Server y algunos métodos globales usados por ésta para la gestión de threads y otros aspectos.
*/

#ifndef SERVER_H_
#define SERVER_H_

#include "Socket.h"
#include "SocketException.h"
#include <iostream>
#include <sstream>
#include <signal.h>
#include <fstream>
#include <list>
#include <fstream>

//! Numero de conexiones permitidas activas (en espera o activas)
/*! Esta constante controla cuantas conexiones puede haber en espera o cuantas puede haber establecias en cualquier momento: habrá N activas
y N en espera como mucho, no N en espera o activas. */
#define N 5
//! Ruta a la llave privada
/*! Ruta relativa o absoluta a la llave privada RSA, si no existe o es inválida, se creará una nueva en esa localización. */
#define PRIVATEKEY "bin/private.key"
//! Ruta a la llave pública
/*! Ruta relativa o absoluta a la llave pública RSA, si no existe o es inválida, se creará una nueva en esa localización. */
#define PUBLICKEY "bin/public.key"
//! Ruta al fichero de configuración
/*! Ruta relativa o absoluta al fichero de configuración, de no existir o ser inválido el programa no funcionará. */
#define CONFFILE "socket.conf"
//! Nombre del socket del módulo de control
/*! Nombre y ruta del socket UNIX del módulo de control */

using namespace std;

//! Clase de aplicación servidor
/**
Esta clase define un objeto con los métodos y atributos necesarios para lanzar una aplicación servidor y atender las conexiones. Para realizar
la comunicación con el cliente, usa un objeto de la clase Socket
*/
class Server
{
        private:
            //! Contador de threads
            /*! Esta variable se encarga de mantener la cuenta de threads activos, por tanto, el número de conexiones que estan siendo antendidas
            simultáneamente. */
        	int nWorkers;
            //! Variable de apagado
            /*! Esta variable controla el apagado del servidor, al ponerla a true, la siguiente iteración del bucle que atiende las conexiones
            no se producirá y el programa terminará. */
            bool shutdownServer;
            //! Contador de ID de thread
            /*! Esta variable contiene el ID del próximo thread que se creará, por tanto, indica el número de conexiones que han sido atendidas desde
            el inicio del servidor */
            int workerID;
            //! Pila de threads terminados
            /*! Esta variable contiene una lista de threads que han finalizado su ejecución. A cada iteración del bucle que atiende conexiones,
            se libera toda la memoria de los threads que hay almacenados aquí. */
            list<pthread_t*> stoppedThreads;
            //! Pila de threads empezados
            /*! \brief Esta variable contiene una lista de threads que han empezado su ejecución. Si el programa finalizara prematuramente, se liberarían los punteros
            de los threads almacenados en esta pila.

            __NOTA: No se liberará la memoria asignada a los argumentos de los threads, dando lugar a memory leaks; sin embargo, esto se produciria al finalizar
            el programa, por tanto no es relevante.__ */
            list<pthread_t*> startedThreads;
            //! Socket de comunicación
            /*! Esta variable contiene el objeto de la clase Socket que la aplicación servidor usa para poder atender las peticiones. Su función
            es quedarse escuchando el el puerto e IP introducidas en el fichero de configuración y crear un objeto de la clase Socket para cada
            petición de cada cliente nuevo, siendo este último objeto creado el que se usa para la comuncación. */
            Socket ss;

        public:
            //! Constructor de la clase Server
            /*! Incializa los argumentos inciales del servidor */
        	Server() : nWorkers(0), workerID(0), shutdownServer(false) {}
            //! Getter del número de threads activos
            /*! Devuelve el número de threads activos en ese instante, por tanto, del número de conexiones que están siendo atendidas. */
            int getNWorkers();
            //! Setter del número de threads activos
            /*! Establece el número de threads activos, para poder cambiarlo cuando alguno de los threads activos finaliza */
            void setNWorkers(int n /*!<Nuevo número de threads activos*/);
            //! Getter de la pila de threads activos
            /*! Devuelve un contenedor con la lista de threads que estan activos, para terminarlos en caso de que el programa finalice prematuramente */
            list<pthread_t*>* getStartedThreads();
            //! Getter de la pila de threads terminados
            /*! Devuelve un contenedor con la lista de threads que han terminado, para poder liberar la memoria que se le ha asignado */
            list<pthread_t*>* getStoppedThreads();
            //! Método de inicialización del servidor
            /*! Incializa el servidor en el puerto e IP especificados para empezar a recibir conexiones entrantes */
            void startServer(string i /*!<IP donde se aceptan las conexiones */, int p/*!<Puerto donde se aceptan las conexiones*/);
            //! Método para liberar memória de threads
            /*! Este método se llama para que libere la memoria de todos los threads que se le proporcionan por argumento */
            void freeRAM(list<pthread_t*> *threadList/*!<Contenedor con los threads a liberar */);
            //! Método para terminar el servidor
            /*! Este método inicia la secuencia de finalización del servidor */
            void requestExit();
            //!Método de petición de datos al módulo de control
            /*! Éste método envía un string al módulo de control donde se define una petición de información que es interpretada por el módulo de
            control y traducida a comandos SQL, la respuesta se recibe como otro string y se devuelve al thread TCP que ha hecho la petición */
            string queryDB(string query);
};

//!Argumentos de los threads
/**
\brief Este struct define los argumentos que recibe un thread abierto por la aplicación servidor al recibir una conexión entrante 
\author Imanol Barba Sabariego
\date 11/06/2013 */ 
struct thread_args
{
    //! Variable de control de la exclusión mútua entre threads
    /** Esta variable se usa para bloquear otros threads en operaciones de exclusion mútua donde se modifican variables compartidas */
    pthread_mutex_t *mutex;
    //! Variable de notificación a otros threads
    /*! \brief Esta variable se usa para notificar a otros threads cuando deben realizar otras acciones. 

    *Actualmente se usa para notificar al thread principal cuando el thread que lo invoca ha terminado, en caso de que el principal haya
    quedado bloqueado y no admita más conexiones.* */
    pthread_cond_t *condition;
    //! Puntero al thread
    /*! \brief Esta variable representa el puntero del propio thread. Al finalizar, este enviará su puntero a la lista de threads terminados,
    donde la memoria asignada al thread se destruirá. */
    pthread_t *thread;
    //! Puntero al socket
    /*! \brief Esta variable representa el puntero al socket que proviene de la conexión entrante recibida por el servidor. Con este, el thread 
    puede recibir y enviar los datos. */
    Socket *s;
    //! Puntero al servidor
    /*! \brief Esta variable representa el puntero al servidor de la aplicación. Con este puntero, los threads se mueven a la pila de threads 
    terminados una vez terminan la ejecución para que el thread principal (el propio servidor), vaya liberando la memoria asignada. */
    Server *serv;
    //! ID del thread
    /*! \brief Identifica al thread con un ID único */
    int id;
};

//! Método de finalización de Threads
/*! \brief Éste método se ejecuta para liberar la memoria de los argumentos del thread y mandarlo a la pila de threads terminados. */
void killThread(thread_args *t_arg /*!<Puntero al struct que contiene los argumentos del thread */);
//! Método gestión de conexiones
/*! \brief Éste método es el que los threads ejecutan al crearse, aquí es donde se define el comportamiento del servidor, ya que cada conexión
se gestionará como aquí se detalla.

_Por defecto, el comportamiento que lleva programado es el de un servidor "echo", esperará que el cliente le envíe un mensaje y responderá con el 
mismo mensaje._ */
void *WorkerThread(void* args /*!< Puntero al struct de los argumentos del thread casteado a tipo void**/);
//! Método auxiliar de procesado de texto
/*! \brief Éste método usa para procesar las entradas de texto del fichero de configuración para adaptarlas a un formato adecuado.

_De momento se limita a eliminar whitespace (tabulaciones, saltos de línea y espacios)._ */
void processText(string *str/*!<Línea de texto a procesar*/);
//! Método de lectura de configuración
/*! \brief Éste método lee el fichero de configuración espeficado para obtener parámetros de configuración para el funcionamiento del servidor. */
bool readConf(string *ip/*!Puntero donde se almacena la IP leída*/, int *port/*!<Puntero donde se almacena el puerto leído*/);

#endif /* SERVER_H_ */