summaryrefslogtreecommitdiff
path: root/src/analysis/db/server.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-03-20 22:52:48 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-03-20 22:52:48 (GMT)
commit18d6b808db6e31e867525d68f92d6f928a7ab5a7 (patch)
treed534c8e374004866696322a4c3f58ae2a7a545d9 /src/analysis/db/server.c
parent84790a5b420d0a9ce658013573b180ce059db325 (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.c426
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);
+
+ }
+
+}