diff options
Diffstat (limited to 'src/analysis/db/client.c')
-rw-r--r-- | src/analysis/db/client.c | 272 |
1 files changed, 221 insertions, 51 deletions
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 946f202..4b807ae 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -33,6 +33,9 @@ #include "protocol.h" +#include "misc/rlestr.h" +#include "../../common/io.h" +#include "../../gui/panels/log.h" @@ -41,9 +44,12 @@ struct _GDbClient { GObject parent; /* A laisser en premier */ - int fd; - struct sockaddr_in addr; /* Adresse d'écoute */ + rle_string hash; /* Empreinte du binaire lié */ + GList *collections; /* Collections d'un binaire */ + int fd; /* Canal de communication */ + + GMutex sending_lock; /* Concurrence des envois */ GThread *update; /* Procédure de traitement */ }; @@ -118,7 +124,7 @@ static void g_db_client_init(GDbClient *client) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : client = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -128,19 +134,19 @@ static void g_db_client_init(GDbClient *client) * * ******************************************************************************/ -static void g_db_client_finalize(GDbClient *binary) +static void g_db_client_finalize(GDbClient *client) { - //free(binary->filename); + unset_rle_string(&client->hash); - G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(binary)); + G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(client)); } /****************************************************************************** * * -* Paramètres : host = hôte à représenter pour le service. * -* port = port de connexion pour les clients. * +* Paramètres : hash = empreinte d'un binaire en cours d'analyse. * +* collections = ensemble de collections existantes. * * * * Description : Prépare un client pour une connexion à une BD. * * * @@ -150,28 +156,155 @@ static void g_db_client_finalize(GDbClient *binary) * * ******************************************************************************/ -GDbClient *g_db_client_new(const char *host, short port) +GDbClient *g_db_client_new(const char *hash, GDbCollection *collections) { GDbClient *result; /* Adresse à retourner */ - struct hostent *hp; /* Informations sur l'hôte */ result = g_object_new(G_TYPE_DB_CLIENT, NULL); + set_rle_string(&result->hash, hash); + result->collections = collections; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* host = hôte à représenter pour le service. * +* port = port de connexion pour les clients. * +* username = utilisateur effectuant les évolutions. * +* * +* Description : Démarre la connexion à la base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_client_start(GDbClient *client, const char *host, unsigned short port, const char *username) +{ + struct hostent *hp; /* Informations sur l'hôte */ + struct sockaddr_in addr; /* Adresse de transmission */ + int ret; /* Bilan d'un appel */ + rle_string user; /* Nom d'utilisateur associé */ + uint32_t data; /* Mot de données lues */ + DBError error; /* Validation de la connexion */ + + /* Identification du serveur à contacter */ + hp = gethostbyname(host); - if (hp == NULL) goto gdsn_error; + if (hp == NULL) return false; - result->addr.sin_family = hp->h_addrtype; - memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); + addr.sin_family = hp->h_addrtype; + memcpy(&addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); - result->addr.sin_port = htons(port); + addr.sin_port = htons(port); - return result; + /* Création d'un canal de communication */ + + client->fd = socket(AF_INET, SOCK_STREAM, 0); + if (client->fd == -1) + { + perror("socket"); + return false; + } + + ret = connect(client->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); + if (ret == -1) + { + perror("connect"); + goto gdcs_no_listening; + } - gdsn_error: + /* Préparation du nom d'utilisateur à diffuser */ - g_object_unref(G_OBJECT(result)); + init_rle_string(&user, username); - return NULL; + /** + * On réalise l'envoi initial ; le premier paquet doit contenir : + * - la commande 'DBC_HELO'. + * - le numéro de version du client. + * - l'empreinte du binaire analysé. + * - l'identifiant de l'utilisateur effectuant des modifications. + * + * Tout ceci est à synchroniser avec la fonction g_db_server_listener(). + */ + + if (!safe_send(client->fd, (uint32_t []) { htobe32(DBC_HELO) }, sizeof(uint32_t), MSG_MORE)) + goto gdcs_error; + + if (!safe_send(client->fd, (uint32_t []) { htobe32(CDB_PROTOCOL_VERSION) }, sizeof(uint32_t), MSG_MORE)) + goto gdcs_error; + + if (!send_rle_string(&client->hash, client->fd, MSG_MORE)) + goto gdcs_error; + + if (!send_rle_string(&user, client->fd, 0)) + goto gdcs_error; + + /** + * Le serveur doit répondre pour un message type : + * - la commande 'DBC_WELCOME'. + * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION'). + */ + + if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0)) + goto gdcs_error; + + if (be32toh(data) != DBC_WELCOME) + { + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' did not welcome us!"), host, port); + goto gdcs_error; + } + + if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0)) + goto gdcs_error; + + error = be32toh(data); + + switch (error) + { + case DBE_NONE: + log_variadic_message(LMT_INFO, _("Connected to the server '%s:%hu'!"), host, port); + break; + + case DBE_WRONG_VERSION: + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' does not use our protocol version (0x%08x)..."), + host, port, CDB_PROTOCOL_VERSION); + goto gdcs_error; + break; + + default: + log_variadic_message(LMT_ERROR, _("The server '%s:%hu' uses an unknown protocol..."), host, port); + goto gdcs_error; + break; + + } + + client->update = g_thread_try_new("cdb_client", (GThreadFunc)g_db_client_update, client, NULL); + if (client->update == NULL) + { + log_variadic_message(LMT_ERROR, _("Failed to start a listening thread for the server '%s:%hu'!"), + host, port); + goto gdcs_error; + } + + return true; + + gdcs_error: + + unset_rle_string(&user); + + gdcs_no_listening: + + close(client->fd); + client->fd = -1; + + return false; } @@ -192,6 +325,10 @@ static void *g_db_client_update(GDbClient *client) { struct pollfd fds; /* Surveillance des flux */ int ret; /* Bilan d'un appel */ + uint32_t val32; /* Valeur sur 32 bits */ + bool status; /* Bilan d'une opération */ + uint32_t command; /* Commande de la requête */ + GDbCollection *collec; /* Collection visée au final */ fds.fd = client->fd; fds.events = POLLIN | POLLPRI; @@ -209,16 +346,50 @@ static void *g_db_client_update(GDbClient *client) if (fds.revents & (POLLIN | POLLPRI)) { + status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gdcu_bad_exchange; + + command = be32toh(val32); + + switch (command) + { + case DBC_COLLECTION: + + status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); + if (!status) goto gdcu_bad_exchange; + + collec = find_collection_in_list(client->collections, be32toh(val32)); + if (collec == NULL) goto gdcu_bad_exchange; + + status = g_db_collection_recv(collec, fds.fd); + if (!status) goto gdcu_bad_exchange; + + + + + printf("## CLIENT ## Got Something to read...\n"); + + break; + + } + + continue; + + gdcu_bad_exchange: + + printf("Bad reception...\n"); + + /* TODO : close conn */ + + ; - /* TODO */ - pause(); } } - g_db_client_stop(client); + //g_db_client_stop(client); return NULL; @@ -229,39 +400,44 @@ static void *g_db_client_update(GDbClient *client) * * * Paramètres : client = client pour les accès distants à manipuler. * * * -* Description : Démarre la connexion à la base de données. * +* Description : Arrête la connexion à la base de données. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_db_client_start(GDbClient *client) +void g_db_client_stop(GDbClient *client) { - int ret; /* Bilan d'un appel */ + if (client->fd != -1) + return; - client->fd = socket(AF_INET, SOCK_STREAM, 0); - if (client->fd == -1) - { - perror("socket"); - return false; - } + close(client->fd); + client->fd = -1; - ret = connect(client->fd, (struct sockaddr *)&client->addr, sizeof(struct sockaddr_in)); - if (ret == -1) - { - perror("connect"); - close(client->fd); - client->fd = -1; - return false; - } + g_thread_join(client->update); - //client->update = g_thread_new("cdb_listener", (GThreadFunc)g_db_client_update, client); +} - send(client->fd, "A", 1, 0); - return true; +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* * +* Description : Identifie le canal de communication pour envois au serveur. * +* * +* Retour : Descripteur de flux normalement ouvert. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_db_client_get_fd(GDbClient *client) +{ + g_mutex_lock(&client->sending_lock); + + return client->fd; } @@ -270,7 +446,7 @@ bool g_db_client_start(GDbClient *client) * * * Paramètres : client = client pour les accès distants à manipuler. * * * -* Description : Arrête la connexion à la base de données. * +* Description : Marque le canal de communication comme disponible. * * * * Retour : - * * * @@ -278,14 +454,8 @@ bool g_db_client_start(GDbClient *client) * * ******************************************************************************/ -void g_db_client_stop(GDbClient *client) +void g_db_client_put_fd(GDbClient *client) { - if (client->fd != -1) - return; - - close(client->fd); - client->fd = -1; - - g_thread_join(client->update); + g_mutex_unlock(&client->sending_lock); } |