diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2014-03-20 22:52:48 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2014-03-20 22:52:48 (GMT) |
commit | 18d6b808db6e31e867525d68f92d6f928a7ab5a7 (patch) | |
tree | d534c8e374004866696322a4c3f58ae2a7a545d9 /src/analysis/db/server.c | |
parent | 84790a5b420d0a9ce658013573b180ce059db325 (diff) |
Created the first steps for a distributed storage.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@368 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/db/server.c')
-rw-r--r-- | src/analysis/db/server.c | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c new file mode 100644 index 0000000..b636d02 --- /dev/null +++ b/src/analysis/db/server.c @@ -0,0 +1,426 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * server.c - mise en place d'un fournisseur d'éléments ajoutés + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "server.h" + + +#include <malloc.h> +#include <netdb.h> +#include <poll.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> + + +#include "protocol.h" + + + +/* Informations relatives à un client */ +typedef struct _cdb_client +{ + GDbServer *server; /* Accès facile en mémoire */ + + int fd; /* Canal de communication */ + struct sockaddr_in peer; /* Adresse distante */ + + GThread *thread; /* Procédure de traitement */ + +} cdb_client; + +/* Description de serveur à l'écoute (instance) */ +struct _GDbServer +{ + GObject parent; /* A laisser en premier */ + + int fd; + struct sockaddr_in addr; /* Adresse d'écoute */ + + GThread *listener; /* Procédure de traitement */ + + cdb_client **clients; /* Connexions en place */ + size_t count; /* Quantité de clients */ + GMutex mutex; /* Verrou pour l'accès */ + +}; + +/* Description de serveur à l'écoute (classe) */ +struct _GDbServerClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des descriptions de fichier binaire. */ +static void g_db_server_class_init(GDbServerClass *); + +/* Initialise une description de fichier binaire. */ +static void g_db_server_init(GDbServer *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_server_finalize(GDbServer *); + +/* Assure l'accueil des nouveaux clients. */ +static void *g_db_server_listener(GDbServer *); + +/* Assure le traitement des requêtes de clients. */ +static void *g_db_server_process(cdb_client **); + + + +/* Indique le type défini pour une description de serveur à l'écoute. */ +G_DEFINE_TYPE(GDbServer, g_db_server, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des descriptions de fichier binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_server_class_init(GDbServerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->finalize = (GObjectFinalizeFunc)g_db_server_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : server = instance à initialiser. * +* * +* Description : Initialise une description de fichier binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_server_init(GDbServer *server) +{ + server->fd = -1; + + g_mutex_init(&server->mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_server_finalize(GDbServer *binary) +{ + //free(binary->filename); + + G_OBJECT_CLASS(g_db_server_parent_class)->finalize(G_OBJECT(binary)); + +} + + +/****************************************************************************** +* * +* Paramètres : host = hôte à représenter pour le service. * +* port = port de connexion pour les clients. * +* * +* Description : Prépare un serveur de BD pour les clients. * +* * +* Retour : Structure mise en plae ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbServer *g_db_server_new(const char *host, short port) +{ + GDbServer *result; /* Adresse à retourner */ + struct hostent *hp; /* Informations sur l'hôte */ + + result = g_object_new(G_TYPE_DB_SERVER, NULL); + + hp = gethostbyname(host); + if (hp == NULL) goto gdsn_error; + + result->addr.sin_family = hp->h_addrtype; + memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); + + result->addr.sin_port = htons(port); + + return result; + + gdsn_error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : server = serveur pour les accès distants à manipuler. * +* * +* Description : Assure l'accueil des nouveaux clients. * +* * +* Retour : NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *g_db_server_listener(GDbServer *server) +{ + struct pollfd fds; /* Surveillance des flux */ + int ret; /* Bilan d'un appel */ + struct sockaddr_in peer; /* Adresse cliente */ + int fd; /* Canal établi vers un client */ + cdb_client *client; /* Mémorisation pour poursuite */ + + fds.fd = server->fd; + fds.events = POLLIN | POLLPRI; + + while (1) + { + ret = poll(&fds, 1, -1); + if (ret != 1) continue; + + /* Le canal est fermé, une sortie doit être demandée... */ + if (fds.revents & POLLNVAL) + break; + + if (fds.revents & (POLLIN | POLLPRI)) + { + fd = accept(server->fd, &peer, (socklen_t []) { sizeof(struct sockaddr_in) }); + if (fd == -1) continue; + + g_mutex_lock(&server->mutex); + + client = (cdb_client *)calloc(1, sizeof(cdb_client)); + + g_object_ref(G_OBJECT(server)); + client->server = server; + + client->fd = fd; + client->peer = peer; + + server->clients = (cdb_client **)realloc(server->clients, + ++server->count * sizeof(cdb_client *)); + server->clients[server->count - 1] = client; + + client->thread = g_thread_new("cdb_process", (GThreadFunc)g_db_server_process, + &server->clients[server->count - 1]); + + g_mutex_unlock(&server->mutex); + + } + + } + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : client = informations sur une connexion établie à utiliser. * +* * +* Description : Assure le traitement des requêtes de clients. * +* * +* Retour : NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void *g_db_server_process(cdb_client **client) +{ + struct pollfd fds; /* Surveillance des flux */ + int ret; /* Bilan d'un appel */ + GDbServer *server; /* Accès facile en mémoire */ + size_t index; /* Indice courant du client */ + size_t remaining; /* Quantité à déplacer */ + + fds.fd = (*client)->fd; + fds.events = POLLIN | POLLPRI; + + while (1) + { + ret = poll(&fds, 1, -1); + if (ret != 1) continue; + + printf("fds.revents :: %x\n", fds.revents); + + /* Le canal est fermé, une sortie doit être demandée... */ + if (fds.revents & POLLNVAL) + break; + + if (fds.revents & (POLLIN | POLLPRI)) + { + + /* TODO */ + pause(); + + + } + + } + + /* Retrait de la liste avant la terminaison */ + + server = (*client)->server; + + g_mutex_lock(&server->mutex); + + index = (client - server->clients); + remaining = server->count - index - 1; + + if (remaining > 0) + memmove(&server->clients[index], &server->clients[index + 1], + remaining * sizeof(cdb_client *)); + + g_object_unref(G_OBJECT(server)); + + free(*client); + + g_mutex_unlock(&server->mutex); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : server = serveur pour les accès distants à manipuler. * +* * +* Description : Démarre le serveur de base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_server_start(GDbServer *server) +{ + int ret; /* Bilan d'un appel */ + + server->fd = socket(AF_INET, SOCK_STREAM, 0); + if (server->fd == -1) + { + perror("socket"); + return false; + } + + ret = setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, (int []) { 1 }, sizeof(int)); + if (ret == -1) + { + perror("setsockopt"); + close(server->fd); + server->fd = -1; + return false; + } + + ret = bind(server->fd, (struct sockaddr *)&server->addr, sizeof(struct sockaddr_in)); + if (ret == -1) + { + perror("bind"); + close(server->fd); + server->fd = -1; + return false; + } + + ret = listen(server->fd, CDB_SEVER_BACKLOG); + if (ret == -1) + { + perror("listen"); + close(server->fd); + server->fd = -1; + return false; + } + + server->listener = g_thread_new("cdb_listener", (GThreadFunc)g_db_server_listener, server); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : server = serveur pour les accès distants à manipuler. * +* * +* Description : Arrête le serveur de base de données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_server_stop(GDbServer *server) +{ + size_t i; /* Boucle de parcours */ + GThread *thread; /* Procédure de traitement */ + + if (server->fd != -1) + return; + + close(server->fd); + server->fd = -1; + + g_thread_join(server->listener); + + for (i = 0; i < server->count; i++) + { + /* Sauvegarde de la référene, qui peut disparaître */ + thread = server->clients[i]->thread; + + close(server->clients[i]->fd); + g_thread_join(thread); + + } + +} |