From fbb80d00d8ac456451963d52af24fcccbbc1d751 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 8 Sep 2019 09:47:41 +0200 Subject: Updated the database protocol for bookmarks. --- plugins/pychrysalide/analysis/binary.c | 58 +++ plugins/pychrysalide/analysis/db/item.c | 45 +++ plugins/pychrysalide/analysis/db/item.h | 3 + plugins/pychrysalide/analysis/db/items/Makefile.am | 1 + plugins/pychrysalide/analysis/db/items/bookmark.c | 397 +++++++++++++++++++++ plugins/pychrysalide/analysis/db/items/bookmark.h | 45 +++ plugins/pychrysalide/analysis/db/items/module.c | 2 + src/analysis/binary.c | 20 +- src/analysis/db/cdb.c | 10 + src/analysis/db/client.c | 44 ++- src/analysis/db/client.h | 5 +- src/analysis/db/items/bookmark.c | 59 +-- src/analysis/db/items/bookmark.h | 30 +- src/analysis/db/protocol.h | 47 +-- src/common/packed.c | 29 ++ src/common/packed.h | 3 + 16 files changed, 720 insertions(+), 78 deletions(-) create mode 100644 plugins/pychrysalide/analysis/db/items/bookmark.c create mode 100644 plugins/pychrysalide/analysis/db/items/bookmark.h diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c index e137f87..98b20dc 100644 --- a/plugins/pychrysalide/analysis/binary.c +++ b/plugins/pychrysalide/analysis/binary.c @@ -38,12 +38,16 @@ #include "../access.h" #include "../helpers.h" #include "../format/executable.h" +#include "db/item.h" /* Crée un nouvel objet Python de type 'LoadedBinary'. */ static PyObject *py_loaded_binary_new(PyTypeObject *, PyObject *, PyObject *); +/* Demande l'intégration d'une modification dans une collection. */ +static PyObject *py_loaded_binary_add_to_collection(PyObject *, PyObject *); + /* Fournit le nom associé à l'élément binaire. */ static PyObject *py_loaded_binary_get_name(PyObject *, void *); @@ -96,6 +100,59 @@ static PyObject *py_loaded_binary_new(PyTypeObject *type, PyObject *args, PyObje /****************************************************************************** * * +* Paramètres : self = objet représentant un binaire chargé. * +* args = arguments fournis pour l'opération. * +* * +* Description : Demande l'intégration d'une modification dans une collection.* +* * +* Retour : Bilan partiel de l'opération demandée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_loaded_binary_add_to_collection(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GDbItem *item; /* Elément à intégrer */ + int ret; /* Bilan de lecture des args. */ + GLoadedBinary *binary; /* Binaire en cours d'analyse */ + bool status; /* Bilan de l'opération */ + +#define LOADED_BINARY_ADD_TO_COLLECTION_METHOD PYTHON_METHOD_DEF \ +( \ + add_to_collection, "$self, item, /", \ + METH_VARARGS, py_loaded_binary, \ + "Ask a server to include the given item into the update database." \ + "\n" \ + "The server type (internal or remote) depends on the collection type" \ + " linked to the item and the user configuration." \ + "\n" \ + "The item has to be a subclass of pychrysalide.analysis.db.DbItem." \ + "\n" \ + "The method returns True if the item has been successfully forwarded" \ + " to a server, False otherwise." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_db_item, &item); + if (!ret) return NULL; + + binary = G_LOADED_BINARY(pygobject_get(self)); + + g_object_ref(G_OBJECT(item)); + + status = g_loaded_binary_add_to_collection(binary, item); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -246,6 +303,7 @@ static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *self, void *c PyTypeObject *get_python_loaded_binary_type(void) { static PyMethodDef py_loaded_binary_methods[] = { + LOADED_BINARY_ADD_TO_COLLECTION_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index 0544d86..981e0c0 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -188,3 +188,48 @@ bool ensure_python_db_item_is_registered(void) return true; } + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en élément pour base de données. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_db_item(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_db_item_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to database item"); + break; + + case 1: + *((GDbItem **)dst) = G_DB_ITEM(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/db/item.h b/plugins/pychrysalide/analysis/db/item.h index 376371b..09a6a07 100644 --- a/plugins/pychrysalide/analysis/db/item.h +++ b/plugins/pychrysalide/analysis/db/item.h @@ -37,6 +37,9 @@ PyTypeObject *get_python_db_item_type(void); /* Prend en charge l'objet 'pychrysalide.analysis.db.DbItem'. */ bool ensure_python_db_item_is_registered(void); +/* Tente de convertir en élément pour base de données. */ +int convert_to_db_item(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ITEM_H */ diff --git a/plugins/pychrysalide/analysis/db/items/Makefile.am b/plugins/pychrysalide/analysis/db/items/Makefile.am index fbb3e22..bea86de 100644 --- a/plugins/pychrysalide/analysis/db/items/Makefile.am +++ b/plugins/pychrysalide/analysis/db/items/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libpychrysaanalysisdbitems.la libpychrysaanalysisdbitems_la_SOURCES = \ + bookmark.h bookmark.c \ comment.h comment.c \ module.h module.c diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.c b/plugins/pychrysalide/analysis/db/items/bookmark.c new file mode 100644 index 0000000..8a33357 --- /dev/null +++ b/plugins/pychrysalide/analysis/db/items/bookmark.c @@ -0,0 +1,397 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.c - équivalent Python du fichier "analysis/db/items/bookmark.c" + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "bookmark.h" + + +#include +#include + + +#include +#include + + +#include "../item.h" +#include "../../../access.h" +#include "../../../helpers.h" +#include "../../../arch/vmpa.h" + + + +/* Crée un nouvel objet Python de type 'DbBookmark'. */ +static PyObject *py_db_bookmark_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_db_bookmark_init(PyObject *, PyObject *, PyObject *); + +/* Fournit l'adresse associée à un signet. */ +static PyObject *py_db_bookmark_get_address(PyObject *, void *); + +/* Fournit le commentaire associé à un signet. */ +static PyObject *py_db_bookmark_get_comment(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : type = type de l'objet à instancier. * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Crée un nouvel objet Python de type 'DbBookmark'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_bookmark_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_db_bookmark_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_DB_BOOKMARK, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0 en cas de succès, -1 sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_db_bookmark_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int result; /* Bilan à renvoyer */ + vmpa2t addr; /* Emplacement ciblé */ + const char *comment; /* Commentaire éventuel associé*/ + int ret; /* Bilan de lecture des args. */ + PyObject *new_args; /* Nouveaux arguments épurés */ + PyObject *new_kwds; /* Nouveau dictionnaire épuré */ + GDbBookmark *bookmark; /* Version GLib du signet */ + bool status; /* Bilan de l'initialisation */ + +#define DB_BOOKMARK_DOC \ + "DbBookmark provides support for bookmarks inside the disassembled code.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " DbBookmark(addr, comment=None)" \ + "\n" \ + "Where addr is a location of type pychrysalide.arch.vmpa and" \ + " comment is a string or None." + + result = -1; + + /* Récupération des paramètres */ + + comment = NULL; + + ret = PyArg_ParseTuple(args, "O&|s", convert_any_to_vmpa, &addr, &comment); + if (!ret) goto exit; + + /* Initialisation d'un objet GLib */ + + new_args = PyTuple_New(0); + new_kwds = PyDict_New(); + + ret = PyGObject_Type.tp_init(self, new_args, new_kwds); + + Py_DECREF(new_kwds); + Py_DECREF(new_args); + + if (ret == -1) goto exit; + + /* Eléments de base */ + + bookmark = G_DB_BOOKMARK(pygobject_get(self)); + + status = g_db_bookmark_fill(bookmark, &addr, comment); + if (!status) goto exit; + + result = 0; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'adresse associée à un signet. * +* * +* Retour : Adresse mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_bookmark_get_address(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GDbBookmark *bookmark; /* Signet à consulter */ + const vmpa2t *addr; /* Localisation de ce signet */ + +#define DB_BOOKMARK_ADDRESS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + address, py_db_bookmark, \ + "Location of the bookmark." \ +) + + bookmark = G_DB_BOOKMARK(pygobject_get(self)); + + addr = g_db_bookmark_get_address(bookmark); + + result = build_from_internal_vmpa(addr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le commentaire associé à un signet. * +* * +* Retour : Commentaire existant ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_bookmark_get_comment(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GDbBookmark *bookmark; /* Signet à consulter */ + const char *comment; /* Contenu textuel associé */ + +#define DB_BOOKMARK_COMMENT_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + comment, py_db_bookmark, \ + "Comment linked to the bookmark or None if the bookmark has been unset." \ +) + + bookmark = G_DB_BOOKMARK(pygobject_get(self)); + + comment = g_db_bookmark_get_comment(bookmark); + + if (comment != NULL) + result = PyUnicode_FromString(comment); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_db_bookmark_type(void) +{ + static PyMethodDef py_db_bookmark_methods[] = { + { NULL } + }; + + static PyGetSetDef py_db_bookmark_getseters[] = { + DB_BOOKMARK_ADDRESS_ATTRIB, + DB_BOOKMARK_COMMENT_ATTRIB, + { NULL } + }; + + static PyTypeObject py_db_bookmark_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.db.items.DbBookmark", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = DB_BOOKMARK_DOC, + + .tp_methods = py_db_bookmark_methods, + .tp_getset = py_db_bookmark_getseters, + + .tp_init = py_db_bookmark_init, + .tp_new = py_db_bookmark_new, + + }; + + return &py_db_bookmark_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide...db.items.DbBookmark'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_db_bookmark_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'DbBookmark' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_db_bookmark_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.db.items"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_db_item_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_DB_BOOKMARK, type, get_python_db_item_type())) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en signet de collection. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_db_bookmark(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_db_bookmark_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to collection bookmark"); + break; + + case 1: + *((GDbBookmark **)dst) = G_DB_BOOKMARK(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.h b/plugins/pychrysalide/analysis/db/items/bookmark.h new file mode 100644 index 0000000..bcf1c11 --- /dev/null +++ b/plugins/pychrysalide/analysis/db/items/bookmark.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.h - prototypes pour l'équivalent Python du fichier "analysis/db/items/bookmark.h" + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ITEMS_BOOKMARK_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ITEMS_BOOKMARK_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_db_bookmark_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.db.items.DbBookmark'. */ +bool ensure_python_db_bookmark_is_registered(void); + +/* Tente de convertir en signet de collection. */ +int convert_to_db_bookmark(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_DB_ITEMS_BOOKMARK_H */ diff --git a/plugins/pychrysalide/analysis/db/items/module.c b/plugins/pychrysalide/analysis/db/items/module.c index 1f9e580..fcf636f 100644 --- a/plugins/pychrysalide/analysis/db/items/module.c +++ b/plugins/pychrysalide/analysis/db/items/module.c @@ -28,6 +28,7 @@ #include +#include "bookmark.h" #include "comment.h" #include "../../../helpers.h" @@ -88,6 +89,7 @@ bool populate_analysis_db_items_module(void) result = true; + if (result) result = ensure_python_db_bookmark_is_registered(); if (result) result = ensure_python_db_comment_is_registered(); assert(result); diff --git a/src/analysis/binary.c b/src/analysis/binary.c index cf680c3..639d6cc 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1068,7 +1068,7 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bo DBStorage storage; /* Forme d'enregistrement */ GHubClient *client; /* Liaison à utiliser */ packed_buffer out_pbuf; /* Tampon d'émission */ - int fd; /* Identifiant du canal de com.*/ + SSL *tls_fd; /* Canal de communication SSL */ feature = g_db_item_get_feature(item); @@ -1099,14 +1099,14 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bo { init_packed_buffer(&out_pbuf); - fd = g_hub_client_get_fd(client); + tls_fd = g_hub_client_get_ssl_fd(client); result = g_db_collection_pack(collec, &out_pbuf, DBA_ADD_ITEM, item); - g_hub_client_put_fd(client); - if (result) - result = send_packed_buffer(&out_pbuf, fd); + result = ssl_send_packed_buffer(&out_pbuf, tls_fd); + + g_hub_client_put_ssl_fd(client, tls_fd); exit_packed_buffer(&out_pbuf); @@ -1144,7 +1144,7 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures f DBStorage storage; /* Forme d'enregistrement */ GHubClient *client; /* Liaison à utiliser */ packed_buffer out_pbuf; /* Tampon d'émission */ - int fd; /* Identifiant du canal de com.*/ + SSL *tls_fd; /* Canal de communication SSL */ collec = g_loaded_binary_find_collection(binary, feature); if (collec == NULL) return false; @@ -1168,14 +1168,14 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *binary, DBFeatures f init_packed_buffer(&out_pbuf); - fd = g_hub_client_get_fd(client); + tls_fd = g_hub_client_get_ssl_fd(client); result = g_db_collection_pack(collec, &out_pbuf, DBA_REM_ITEM, item); - g_hub_client_put_fd(client); - if (result) - result = send_packed_buffer(&out_pbuf, fd); + result = ssl_send_packed_buffer(&out_pbuf, tls_fd); + + g_hub_client_put_ssl_fd(client, tls_fd); exit_packed_buffer(&out_pbuf); diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 74e8501..597242f 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -939,9 +939,19 @@ static void *g_cdb_archive_process(GCdbArchive *archive) sizeof(uint32_t), true); if (!status) goto gcap_bad_reply; + status = extend_packed_buffer(&out_pbuf, (uint8_t []) { 0x1 }, sizeof(uint8_t), true); + if (!status) goto gcap_bad_reply; + status = pack_all_collection_updates(archive->collections, &out_pbuf); if (!status) goto gcap_bad_reply; + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SET_ALL_ITEMS }, + sizeof(uint32_t), true); + if (!status) goto gcap_bad_reply; + + status = extend_packed_buffer(&out_pbuf, (uint8_t []) { 0x0 }, sizeof(uint8_t), true); + if (!status) goto gcap_bad_reply; + status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd); if (!status) goto gcap_bad_reply; diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 9252ccc..2bfa978 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -31,7 +31,6 @@ #include #include #include -#include #include @@ -682,6 +681,7 @@ static void *g_hub_client_update(GHubClient *client) uint32_t command; /* Commande de la requête */ DBError error; /* Bilan d'une commande passée */ GDbCollection *collec; /* Collection visée au final */ + uint8_t tmp8; /* Valeur sur 8 bits */ char *msg; /* Message d'erreur à imprimer */ /** @@ -740,6 +740,8 @@ static void *g_hub_client_update(GHubClient *client) status = ssl_recv_packed_buffer(&in_pbuf, client->tls_fd); if (!status) goto gdcu_bad_exchange; + next_command: + status = extract_packed_buffer(&in_pbuf, &command, sizeof(uint32_t), true); if (!status) goto gdcu_bad_exchange; @@ -785,11 +787,18 @@ static void *g_hub_client_update(GHubClient *client) break; case DBC_SET_ALL_ITEMS: - client->can_get_updates = true; + + status = extract_packed_buffer(&in_pbuf, &tmp8, sizeof(uint8_t), true); + if (!status) goto gdcu_bad_exchange; + + client->can_get_updates = (tmp8 == 0x1); break; } + if (has_more_data_in_packed_buffer(&in_pbuf)) + goto next_command; + continue; gdcu_bad_exchange: @@ -882,11 +891,25 @@ void g_hub_client_stop(GHubClient *client) * * ******************************************************************************/ -int g_hub_client_get_fd(GHubClient *client) +SSL *g_hub_client_get_ssl_fd(GHubClient *client) { + SSL *result; /* Canal à retourner */ +#ifndef NDEBUG + int ret; /* Validation de transmission */ +#endif + g_mutex_lock(&client->sending_lock); - return client->fd; + result = client->tls_fd; + +#ifndef NDEBUG + ret = SSL_up_ref(result); + assert(ret == 1); +#else + SSL_up_ref(result); +#endif + + return result; } @@ -894,6 +917,7 @@ int g_hub_client_get_fd(GHubClient *client) /****************************************************************************** * * * Paramètres : client = client pour les accès distants à manipuler. * +* tls_fd = canal de communication SSL. * * * * Description : Marque le canal de communication comme disponible. * * * @@ -903,10 +927,12 @@ int g_hub_client_get_fd(GHubClient *client) * * ******************************************************************************/ -void g_hub_client_put_fd(GHubClient *client) +void g_hub_client_put_ssl_fd(GHubClient *client, SSL *tls_fd) { g_mutex_unlock(&client->sending_lock); + SSL_free(tls_fd); + } @@ -927,13 +953,13 @@ bool g_hub_client_save(GHubClient *client) bool result; /* Bilan partiel à remonter */ int sent; /* Quantité de données traitées*/ - g_hub_client_get_fd(client); + g_hub_client_get_ssl_fd(client); sent = SSL_write(client->tls_fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t)); result = (sent == sizeof(uint32_t)); - g_hub_client_put_fd(client); + g_hub_client_put_ssl_fd(client, client->tls_fd); return result; @@ -960,14 +986,14 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp) init_packed_buffer(&out_pbuf); - g_hub_client_get_fd(client); + g_hub_client_get_ssl_fd(client); result = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SET_LAST_ACTIVE }, sizeof(uint32_t), true); if (result) result = pack_timestamp(×tamp, &out_pbuf); - g_hub_client_put_fd(client); + g_hub_client_put_ssl_fd(client, client->tls_fd); if (result) result = ssl_send_packed_buffer(&out_pbuf, client->tls_fd); diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index 66ca6ab..2915f77 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -27,6 +27,7 @@ #include #include +#include #include "collection.h" @@ -64,10 +65,10 @@ bool g_hub_client_start_remote(GHubClient *, const char *, const char *, bool); void g_hub_client_stop(GHubClient *); /* Identifie le canal de communication pour envois au serveur. */ -int g_hub_client_get_fd(GHubClient *); +SSL *g_hub_client_get_ssl_fd(GHubClient *); /* Marque le canal de communication comme disponible. */ -void g_hub_client_put_fd(GHubClient *); +void g_hub_client_put_ssl_fd(GHubClient *, SSL *); /* Effectue une demande de sauvegarde de l'état courant. */ bool g_hub_client_save(GHubClient *); diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 1dc299b..266b04c 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -266,12 +266,47 @@ static void g_db_bookmark_finalize(GDbBookmark *bookmark) GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment) { GDbBookmark *result; /* Instance à retourner */ + bool status; /* Bilan de l'initialisation */ result = g_object_new(G_TYPE_DB_BOOKMARK, NULL); - copy_vmpa(&result->addr, addr); + status = g_db_bookmark_fill(result, addr, comment); + if (!status) goto error; - g_db_bookmark_set_comment(result, comment); + return result; + + error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = signet à initialiser. * +* addr = adresse inamovible localisant une position donnée.* +* comment = commentaire construit ou NULL. * +* * +* Description : Initialise la définition d'un signet dans une zone de texte. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_bookmark_fill(GDbBookmark *bookmark, const vmpa2t *addr, const char *comment) +{ + bool result; /* Bilan à retourner */ + + result = true; + + copy_vmpa(&bookmark->addr, addr); + + dup_into_rle_string(&bookmark->comment, comment); return result; @@ -601,26 +636,6 @@ const char *g_db_bookmark_get_comment(const GDbBookmark *bookmark) } -/****************************************************************************** -* * -* Paramètres : bookmark = informations à consulter. * -* comment = commentaire construit ou NULL. * -* * -* Description : Définit le commentaire associé à un signet. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_db_bookmark_set_comment(GDbBookmark *bookmark, const char *comment) -{ - dup_into_rle_string(&bookmark->comment, comment); - -} - - /* ---------------------------------------------------------------------------------- */ /* DEFINITION DE LA COLLECTION ASSOCIEE */ diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h index a8526f7..47a7955 100644 --- a/src/analysis/db/items/bookmark.h +++ b/src/analysis/db/items/bookmark.h @@ -36,12 +36,12 @@ /* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ -#define G_TYPE_DB_BOOKMARK g_db_bookmark_get_type() -#define G_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_bookmark_get_type(), GDbBookmark)) -#define G_IS_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_bookmark_get_type())) -#define G_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) -#define G_IS_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_BOOKMARK)) -#define G_DB_BOOKMARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) +#define G_TYPE_DB_BOOKMARK g_db_bookmark_get_type() +#define G_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DB_BOOKMARK, GDbBookmark)) +#define G_IS_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DB_BOOKMARK)) +#define G_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) +#define G_IS_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_BOOKMARK)) +#define G_DB_BOOKMARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_BOOKMARK, GDbBookmarkClass)) /* Signet à l'intérieur d'une zone de texte (instance) */ @@ -57,26 +57,26 @@ GType g_db_bookmark_get_type(void); /* Crée une définition d'un signet dans une zone de texte. */ GDbBookmark *g_db_bookmark_new(const vmpa2t *, const char *); +/* Initialise la définition d'un signet dans une zone de texte. */ +bool g_db_bookmark_fill(GDbBookmark *, const vmpa2t *, const char *); + /* Fournit l'adresse associée à un signet. */ const vmpa2t *g_db_bookmark_get_address(GDbBookmark *); /* Fournit le commentaire associé à un signet. */ const char *g_db_bookmark_get_comment(const GDbBookmark *); -/* Définit le commentaire associé à un signet. */ -void g_db_bookmark_set_comment(GDbBookmark *, const char *); - /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ -#define G_TYPE_BM_COLLECTION g_bookmark_collection_get_type() -#define G_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_bookmark_collection_get_type(), GBookmarkCollection)) -#define G_IS_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_bookmark_collection_get_type())) -#define G_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) -#define G_IS_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BM_COLLECTION)) -#define G_BM_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) +#define G_TYPE_BM_COLLECTION g_bookmark_collection_get_type() +#define G_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BM_COLLECTION, GBookmarkCollection)) +#define G_IS_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BM_COLLECTION)) +#define G_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) +#define G_IS_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BM_COLLECTION)) +#define G_BM_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) /* Collection dédiée aux signets (instance) */ diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 1c03d62..5c3eed6 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -114,7 +114,28 @@ typedef enum _DBCommand { DBC_HELO, /* Connexion initiale C -> S */ DBC_WELCOME, /* Réponse initiale S -> C */ + + /** + * Gestion de la commande 'DBC_SAVE'. + * + * Le client connecté envoie un paquet de la forme suivante : + * + * [ Ordre de sauvegarde : DBC_SAVE ] + * + * Le serveur s'exécute et renvoie un bilan : + * + * [ Ordre de sauvegarde : DBC_SAVE ] + * [ Statut d'exécution ; cf. DBError ] + * + * Les traitements se réalisent dans : + * - g_db_client_save() pour la partie client en émission. + * - g_cdb_archive_process() pour la partie serveur. + * - g_db_client_update() pour la partie client en réception. + * + */ + DBC_SAVE, /* Enregistrement de l'archive */ + DBC_COLLECTION, /* Implication d'une collection*/ /** @@ -131,6 +152,7 @@ typedef enum _DBCommand * De son côté, le serveur répond par une requête : * * [ Notification de maj : DBC_SET_ALL_ITEMS ] + * [ marqueur de démarrage : octet 0x1 ] * * Dans la foulée, il enverra ensuite les éléments avec des paquets classiques : * @@ -138,6 +160,11 @@ typedef enum _DBCommand * [ Action : DBA_ADD_ITEM ] * ... * + * La séquence se termine par une requête finale : + * + * [ Notification de maj : DBC_SET_ALL_ITEMS ] + * [ marqueur de fin : octet 0x0 ] + * * Les traitements se réalisent dans : * - g_db_client_update() pour la partie client. * - g_cdb_archive_process() pour la partie serveur. @@ -202,26 +229,6 @@ typedef enum _DBError -/** - * Gestion de la commande 'DBC_SAVE'. - * - * Le client connecté envoie un paquet de la forme suivante : - * - * [ Ordre de sauvegarde : DBC_SAVE ] - * - * Le serveur s'exécute et renvoie un bilan : - * - * [ Ordre de sauvegarde : DBC_SAVE ] - * [ Statut d'exécution ; cf. DBError ] - * - * Les traitements se réalisent dans : - * - g_db_client_save() pour la partie client en émission. - * - g_cdb_archive_process() pour la partie serveur. - * - g_db_client_update() pour la partie client en réception. - * - */ - - diff --git a/src/common/packed.c b/src/common/packed.c index e06e4bb..163ed3b 100644 --- a/src/common/packed.c +++ b/src/common/packed.c @@ -30,6 +30,9 @@ #include +#include "../core/logs.h" + + /* Taille d'allocation en cas de besoin */ #define PACKET_BLOCK_SIZE 1000 @@ -124,6 +127,29 @@ size_t get_packed_buffer_payload_length(const packed_buffer *pbuf) /****************************************************************************** * * +* Paramètres : pbuf = paquet de données à consulter. * +* * +* Description : Détermine si des données sont disponibles en lecture. * +* * +* Retour : true si des données peuvent être dépilées, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool has_more_data_in_packed_buffer(const packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = (pbuf->pos < pbuf->used); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : pbuf = paquet de données à compléter. * * buf = nouvelles données à ajouter. * * len = quantité de ces données. * @@ -430,6 +456,7 @@ bool ssl_recv_packed_buffer(packed_buffer *pbuf, SSL *fd) int got; /* Quantité de données traitées*/ got = SSL_read(fd, &used, sizeof(uint32_t)); + if (got <= 0) LOG_ERROR_OPENSSL; result = (got == sizeof(uint32_t)); @@ -446,6 +473,7 @@ bool ssl_recv_packed_buffer(packed_buffer *pbuf, SSL *fd) pbuf->used = used; got = SSL_read(fd, pbuf->data + pbuf->pos, used); + if (got <= 0) LOG_ERROR_OPENSSL; result = (got == used); @@ -480,6 +508,7 @@ bool ssl_send_packed_buffer(packed_buffer *pbuf, SSL *fd) quantity = sizeof(uint32_t) + pbuf->used; sent = SSL_write(fd, pbuf->data, quantity); + if (sent <= 0) LOG_ERROR_OPENSSL; result = (quantity == sent); diff --git a/src/common/packed.h b/src/common/packed.h index 5c724e0..4403ad0 100644 --- a/src/common/packed.h +++ b/src/common/packed.h @@ -59,6 +59,9 @@ void exit_packed_buffer(packed_buffer *); /* Indique le nombre d'octets de la charge utile d'un paquet. */ size_t get_packed_buffer_payload_length(const packed_buffer *); +/* Détermine si des données sont disponibles en lecture. */ +bool has_more_data_in_packed_buffer(const packed_buffer *); + /* Ajoute des données à un paquet en amont à un envoi. */ bool extend_packed_buffer(packed_buffer *, const void *, size_t, bool); -- cgit v0.11.2-87-g4458