From d7c69bcb27a7d06932cd25021144b6cbbe4eb82f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 19 Oct 2019 14:50:37 +0200 Subject: Exchanged the list of all snapshots. --- plugins/pychrysalide/analysis/db/client.c | 137 ++++++++++++++++++++++ src/analysis/db/cdb.c | 21 ++++ src/analysis/db/client.c | 185 +++++++++++++++++++++++++++++- src/analysis/db/client.h | 3 + src/analysis/db/misc/rlestr.c | 2 +- src/analysis/db/misc/snapshot.c | 78 ++++++++++++- src/analysis/db/misc/snapshot.h | 14 ++- src/analysis/db/misc/timestamp.c | 19 +++ src/analysis/db/misc/timestamp.h | 3 + src/analysis/db/protocol.h | 31 +++++ src/analysis/db/snapshot.c | 63 +++++++++- src/analysis/db/snapshot.h | 3 + src/common/packed.c | 110 +++++++++++++----- src/common/packed.h | 6 + 14 files changed, 633 insertions(+), 42 deletions(-) diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c index afece26..f9ce001 100644 --- a/plugins/pychrysalide/analysis/db/client.c +++ b/plugins/pychrysalide/analysis/db/client.c @@ -25,6 +25,7 @@ #include "client.h" +#include #include @@ -36,6 +37,7 @@ #include "collection.h" #include "../../access.h" #include "../../helpers.h" +#include "../../struct.h" @@ -54,6 +56,9 @@ static PyObject *py_hub_client_save(PyObject *, PyObject *); /* Active les éléments en amont d'un horodatage donné. */ static PyObject *py_hub_client_set_last_active(PyObject *, PyObject *); +/* Fournit la liste des instantanés existants. */ +static PyObject *py_hub_client_get_snapshots(PyObject *, void *); + /* Fournit l'identifiant de l'instantané courant. */ static PyObject *py_hub_client_get_current_snapshot(PyObject *, void *); @@ -338,6 +343,137 @@ static PyObject *py_hub_client_set_last_active(PyObject *self, PyObject *args) * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * +* Description : Fournit la liste des instantanés existants. * +* * +* Retour : Liste d'instantanés ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_hub_client_get_snapshots(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GHubClient *client; /* Version native du serveur */ + snapshot_info_t *info; /* Liste d'instantanés présents*/ + size_t count; /* Taille de cette liste */ + bool status; /* Validité de cet identifiant */ + PyTypeObject *base; /* Modèle d'objet à créer */ + size_t i; /* Boucle de parcours */ + PyObject *item; /* Nouvelle description */ + char *text; /* Valeur textuelle à placer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + bool failed; /* Détection d'une erreur */ + +#define HUB_CLIENT_SNAPSHOTS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + snapshots, py_hub_client, \ + "List of all existing snapshots, provided as a tuple of pychrysalide.PyStructObject." \ + "\n" \ + "Each snapshot is characterised by the following properties :\n" \ + "* parent_id : identifier of the parent snapshot;\n" \ + "* id : identifier of the snapshot;\n" \ + "* created : timestamp of the creation date;\n" \ + "* name : name of the snapshot, or None;\n" \ + "* desc : description of the snapshot, or None." \ +) + + client = G_HUB_CLIENT(pygobject_get(self)); + + status = g_hub_client_get_snapshots(client, &info, &count); + + if (status) + { + result = PyTuple_New(count); + + base = get_python_py_struct_type(); + + failed = false; + + for (i = 0; i < count; i++) + { + item = PyObject_CallFunction((PyObject *)base, NULL); + assert(item != NULL); + + text = snapshot_id_as_string(get_snapshot_info_parent_id(&info[i])); + attrib = PyUnicode_FromString(text); + ret = PyDict_SetItemString(item, "parent_id", attrib); + if (ret != 0) break; + + text = snapshot_id_as_string(get_snapshot_info_id(&info[i])); + attrib = PyUnicode_FromString(text); + ret = PyDict_SetItemString(item, "id", attrib); + if (ret != 0) break; + + attrib = PyLong_FromUnsignedLongLong(get_snapshot_info_created(&info[i])); + ret = PyDict_SetItemString(item, "created", attrib); + if (ret != 0) break; + + text = get_snapshot_info_name(&info[i]); + + if (text != NULL) + attrib = PyUnicode_FromString(text); + else + { + attrib = Py_None; + Py_INCREF(attrib); + } + + ret = PyDict_SetItemString(item, "name", attrib); + if (ret != 0) break; + + text = get_snapshot_info_desc(&info[i]); + + if (text != NULL) + attrib = PyUnicode_FromString(text); + else + { + attrib = Py_None; + Py_INCREF(attrib); + } + + ret = PyDict_SetItemString(item, "desc", attrib); + if (ret != 0) break; + + PyTuple_SetItem(result, i, item); + + } + + failed = (i < count); + + for (i = 0; i < count; i++) + exit_snapshot_info(&info[i]); + + free(info); + + if (failed) + goto on_failure; + + } + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + + on_failure: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * * Description : Fournit l'identifiant de l'instantané courant. * * * * Retour : Identifiant d'instantané ou None. * @@ -452,6 +588,7 @@ PyTypeObject *get_python_hub_client_type(void) }; static PyGetSetDef py_hub_client_getseters[] = { + HUB_CLIENT_SNAPSHOTS_ATTRIB, HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB, { NULL } }; diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 8e8813a..2df556b 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -1003,6 +1003,27 @@ static void *g_cdb_archive_process(GCdbArchive *archive) break; + case DBC_GET_SNAPSHOTS: + + init_packed_buffer(&out_pbuf); + + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SNAPSHOTS_UPDATED }, + sizeof(uint32_t), true); + if (!status) goto gcap_bad_reply; + + status = g_db_snapshot_pack_all(archive->snapshot, &out_pbuf); + if (!status) goto gcap_bad_reply; + + status = extend_packed_buffer(&out_pbuf, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ, false); + if (!status) goto gcap_bad_reply; + + status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].ssl_fd); + if (!status) goto gcap_bad_reply; + + exit_packed_buffer(&out_pbuf); + + break; + case DBC_GET_CUR_SNAPSHOT: init_packed_buffer(&out_pbuf); diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 3372c74..2cab655 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -76,11 +77,13 @@ struct _GHubClient bool can_get_updates; /* Réception de maj possibles ?*/ GThread *update; /* Procédure de traitement */ - - + snapshot_info_t *snapshots; /* Liste des instantanés */ + size_t snap_count; /* Taille de cette liste */ + GMutex snap_lock; /* Concurrence des accès */ snapshot_id_t current; /* Instantané courant */ bool has_current; /* Validité de l'identifiant */ + GMutex cur_lock; /* Concurrence des accès */ }; @@ -110,6 +113,9 @@ static bool g_hub_client_start_common(GHubClient *, char *); /* Assure l'accueil des nouvelles mises à jour. */ static void *g_hub_client_update(GHubClient *); +/* Met à jour la liste des instantanés courants. */ +static bool g_hub_client_update_snapshots(GHubClient *, packed_buffer *); + /* Identifie le canal de communication pour envois au serveur. */ static SSL *g_hub_client_get_ssl_fd(GHubClient *); @@ -160,6 +166,9 @@ static void g_hub_client_class_init(GHubClientClass *klass) static void g_hub_client_init(GHubClient *client) { + init_static_rle_string(&client->hash, NULL); + client->collections = NULL; + client->working = NULL; client->tls_ctx = NULL; @@ -168,7 +177,16 @@ static void g_hub_client_init(GHubClient *client) client->tls_fd = NULL; client->desc = NULL; + g_mutex_init(&client->sending_lock); + client->can_get_updates = false; + client->update = NULL; + + client->snapshots = NULL; + client->snap_count = 0; + g_mutex_init(&client->snap_lock); + client->has_current = false; + g_mutex_init(&client->cur_lock); } @@ -189,6 +207,12 @@ static void g_hub_client_dispose(GHubClient *client) { g_hub_client_stop(client); + g_mutex_clear(&client->cur_lock); + + g_mutex_clear(&client->snap_lock); + + g_mutex_clear(&client->sending_lock); + G_OBJECT_CLASS(g_hub_client_parent_class)->dispose(G_OBJECT(client)); } @@ -208,18 +232,28 @@ static void g_hub_client_dispose(GHubClient *client) static void g_hub_client_finalize(GHubClient *client) { + size_t i; /* Boucle de parcours */ + unset_rle_string(&client->hash); if (client->working != NULL) free(client->working); assert(client->tls_ctx == NULL); - assert(client->tls_fd == NULL); if (client->desc != NULL) free(client->desc); + if (client->snapshots != NULL) + { + for (i = 0; i < client->snap_count; i++) + exit_snapshot_info(&client->snapshots[i]); + + free(client->snapshots); + + } + G_OBJECT_CLASS(g_hub_client_parent_class)->finalize(G_OBJECT(client)); } @@ -703,6 +737,13 @@ static void *g_hub_client_update(GHubClient *client) init_packed_buffer(&out_pbuf); + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_SNAPSHOTS }, sizeof(uint32_t), true); + if (!status) + { + exit_packed_buffer(&out_pbuf); + goto exit; + } + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_CUR_SNAPSHOT }, sizeof(uint32_t), true); if (!status) { @@ -814,6 +855,13 @@ static void *g_hub_client_update(GHubClient *client) client->can_get_updates = (tmp8 == 0x1); break; + case DBC_SNAPSHOTS_UPDATED: + + status = g_hub_client_update_snapshots(client, &in_pbuf); + if (!status) goto gdcu_bad_exchange; + + break; + case DBC_GET_CUR_SNAPSHOT: log_variadic_message(LMT_INFO, _("This command is not available on this side: 0x%08x"), command); @@ -825,9 +873,13 @@ static void *g_hub_client_update(GHubClient *client) status = unpack_snapshot_id(&id, &in_pbuf); if (!status) goto gdcu_bad_exchange; + g_mutex_lock(&client->cur_lock); + copy_snapshot_id(&client->current, &id); client->has_current = true; + g_mutex_unlock(&client->cur_lock); + break; case DBC_SET_CUR_SNAPSHOT: @@ -872,6 +924,82 @@ static void *g_hub_client_update(GHubClient *client) /****************************************************************************** * * * Paramètres : client = client pour les accès distants à manipuler. * +* pbuf = données présentes à traiter. * +* * +* Description : Met à jour la liste des instantanés courants. * +* * +* Retour : true si la liste retournée est valide, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_hub_client_update_snapshots(GHubClient *client, packed_buffer *pbuf) +{ + bool result; /* Validité à retourner */ + size_t i; /* Boucle de parcours */ + char id[SNAP_ID_HEX_SZ]; /* Caractères hexadécimaux */ + snapshot_info_t info; /* Description d'instantané */ + snapshot_info_t *dest; /* Destination de description */ + + result = true; + + g_mutex_lock(&client->snap_lock); + + if (client->snapshots != NULL) + { + for (i = 0; i < client->snap_count; i++) + exit_snapshot_info(&client->snapshots[i]); + + free(client->snapshots); + + client->snapshots = NULL; + client->snap_count = 0; + + } + + do + { + result = peek_packed_buffer(pbuf, id, SNAP_ID_HEX_SZ, false); + if (!result) break; + + if (strncmp(id, SNAPSHOT_END_MARK, SNAP_ID_HEX_SZ) == 0) + { + advance_packed_buffer(pbuf, SNAP_ID_HEX_SZ); + break; + } + + else + { + setup_empty_snapshot_info(&info); + + result = unpack_snapshot_info(&info, pbuf); + if (!result) break; + + client->snapshots = realloc(client->snapshots, ++client->snap_count * sizeof(snapshot_info_t)); + + dest = &client->snapshots[client->snap_count - 1]; + + setup_empty_snapshot_info(dest); + copy_snapshot_info(dest, &info); + + exit_snapshot_info(&info); + + } + + } + while (true); + + g_mutex_unlock(&client->snap_lock); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * * * * Description : Arrête la connexion à la base de données. * * * @@ -1135,6 +1263,53 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp) /****************************************************************************** * * * Paramètres : client = client pour les accès distants à manipuler. * +* info = description des instantanés présents. [OUT] * +* count = taille de la liste retournée. [OUT] * +* * +* Description : Fournit la liste des instantanés existants. * +* * +* Retour : true si la liste retournée est valide, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_get_snapshots(GHubClient *client, snapshot_info_t **info, size_t *count) +{ + bool result; /* Validité à retourner */ + size_t i; /* Boucle de parcours */ + snapshot_info_t *dest; /* Destination de description */ + + g_mutex_lock(&client->snap_lock); + + result = (client->snap_count > 0); + + if (result) + { + *info = malloc(client->snap_count * sizeof(snapshot_info_t)); + *count = client->snap_count; + + for (i = 0; i < client->snap_count; i++) + { + dest = &(*info)[i]; + + setup_empty_snapshot_info(dest); + copy_snapshot_info(dest, &client->snapshots[i]); + + } + + } + + g_mutex_unlock(&client->snap_lock); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * * id = identifiant d'instantané à renseigner. [OUT] * * * * Description : Fournit l'identifiant de l'instantané courant. * @@ -1149,11 +1324,15 @@ bool g_hub_client_get_current_snapshot(GHubClient *client, snapshot_id_t *id) { bool result; /* Validité à retourner */ + g_mutex_lock(&client->cur_lock); + result = client->has_current; if (result) copy_snapshot_id(id, &client->current); + g_mutex_unlock(&client->cur_lock); + return result; } diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index 36d24e6..039631e 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -74,6 +74,9 @@ bool g_hub_client_add_item(GHubClient *, const GDbItem *); /* Active les éléments en amont d'un horodatage donné. */ bool g_hub_client_set_last_active(GHubClient *, timestamp_t); +/* Fournit la liste des instantanés existants. */ +bool g_hub_client_get_snapshots(GHubClient *, snapshot_info_t **, size_t *); + /* Fournit l'identifiant de l'instantané courant. */ bool g_hub_client_get_current_snapshot(GHubClient *, snapshot_id_t *); diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c index 0fe182b..c1cc866 100644 --- a/src/analysis/db/misc/rlestr.c +++ b/src/analysis/db/misc/rlestr.c @@ -286,7 +286,7 @@ bool unpack_rle_string(rle_string *str, packed_buffer *pbuf) if (result && str->length > 0) { - str->data = (char *)malloc(str->length + 1); + str->data = malloc(str->length + 1); str->dynamic = true; result = extract_packed_buffer(pbuf, str->data, str->length + 1, false); diff --git a/src/analysis/db/misc/snapshot.c b/src/analysis/db/misc/snapshot.c index 546191b..9aa096f 100644 --- a/src/analysis/db/misc/snapshot.c +++ b/src/analysis/db/misc/snapshot.c @@ -41,6 +41,25 @@ * * * Paramètres : id = identifiant d'instantané à initialiser. [OUT] * * * +* Description : Prépare un identifiant pour instantané à une définition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void setup_empty_snapshot_id(snapshot_id_t *id) +{ + memset(id, 0, sizeof(snapshot_id_t)); + +} + + +/****************************************************************************** +* * +* Paramètres : id = identifiant d'instantané à initialiser. [OUT] * +* * * Description : Construit un identifiant pour instantané de base de données. * * * * Retour : Bilan de l'opération. * @@ -214,6 +233,32 @@ bool pack_snapshot_id(const snapshot_id_t *id, packed_buffer *pbuf) * * * Paramètres : info = description d'instantané à initialiser. [OUT] * * * +* Description : Prépare une description pour instantané à une définition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void setup_empty_snapshot_info(snapshot_info_t *info) +{ + setup_empty_snapshot_id(&info->parent_id); + + setup_empty_snapshot_id(&info->id); + + setup_empty_timestamp(&info->created); + + info->name = NULL; + info->desc = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : info = description d'instantané à initialiser. [OUT] * +* * * Description : Construit une description pour instantané de base de données.* * * * Retour : Bilan de l'opération. * @@ -226,7 +271,10 @@ bool init_snapshot_info(snapshot_info_t *info) { bool result; /* Bilan à retourner */ - result = init_snapshot_id(&info->id); + result = init_snapshot_id_from_text(&info->parent_id, NO_SNAPSHOT_ROOT); + + if (result) + result = init_snapshot_id(&info->id); if (result) result = init_timestamp(&info->created); @@ -262,7 +310,10 @@ bool init_snapshot_info_from_text(snapshot_info_t *info, const char *id, uint64_ { bool result; /* Bilan à retourner */ - result = init_snapshot_id_from_text(&info->id, id); + result = init_snapshot_id_from_text(&info->parent_id, NO_SNAPSHOT_ROOT); + + if (result) + result = init_snapshot_id_from_text(&info->id, id); if (result) result = init_timestamp_from_value(&info->created, created); @@ -332,6 +383,8 @@ void copy_snapshot_info(snapshot_info_t *dest, const snapshot_info_t *src) { exit_snapshot_info(dest); + copy_snapshot_id(&dest->parent_id, &src->parent_id); + copy_snapshot_id(&dest->id, &src->id); copy_timestamp(&dest->created, &src->created); @@ -362,19 +415,26 @@ bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ rle_string string; /* Chaîne à transmettre */ + const char *text; /* Valeur textuelle obtenue */ - result = unpack_snapshot_id(&info->id, pbuf); + result = unpack_snapshot_id(&info->parent_id, pbuf); + + if (result) + result = unpack_snapshot_id(&info->id, pbuf); if (result) result = unpack_timestamp(&info->created, pbuf); if (result) { + init_static_rle_string(&string, NULL); + result = unpack_rle_string(&string, pbuf); if (result) { - info->name = strdup(get_rle_string(&string)); + text = get_rle_string(&string); + info->name = (text != NULL ? strdup(text) : NULL); exit_rle_string(&string); } @@ -382,11 +442,14 @@ bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf) if (result) { + init_static_rle_string(&string, NULL); + result = unpack_rle_string(&string, pbuf); if (result) { - info->desc = strdup(get_rle_string(&string)); + text = get_rle_string(&string); + info->desc = (text != NULL ? strdup(text) : NULL); exit_rle_string(&string); } @@ -415,7 +478,10 @@ bool pack_snapshot_info(const snapshot_info_t *info, packed_buffer *pbuf) bool result; /* Bilan à retourner */ rle_string string; /* Chaîne à transmettre */ - result = pack_snapshot_id(&info->id, pbuf); + result = pack_snapshot_id(&info->parent_id, pbuf); + + if (result) + result = pack_snapshot_id(&info->id, pbuf); if (result) result = pack_timestamp(&info->created, pbuf); diff --git a/src/analysis/db/misc/snapshot.h b/src/analysis/db/misc/snapshot.h index 37fad7f..8f9a598 100644 --- a/src/analysis/db/misc/snapshot.h +++ b/src/analysis/db/misc/snapshot.h @@ -49,6 +49,13 @@ typedef struct _snapshot_id_t } snapshot_id_t; +/* Identifiant d'un parent de racine */ +#define NO_SNAPSHOT_ROOT "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + +/* Prépare un identifiant pour instantané à une définition. */ +void setup_empty_snapshot_id(snapshot_id_t *); + /* Construit un identifiant pour instantané de base de données. */ bool init_snapshot_id(snapshot_id_t *); @@ -77,6 +84,7 @@ bool pack_snapshot_id(const snapshot_id_t *, packed_buffer *); /* Description d'un instantané */ typedef struct _snapshot_info_t { + snapshot_id_t parent_id; /* Identifiant du propriétaire */ snapshot_id_t id; /* Identifiant attribué */ timestamp_t created; /* Date de création */ @@ -87,6 +95,9 @@ typedef struct _snapshot_info_t } snapshot_info_t; +/* Prépare une description pour instantané à une définition. */ +void setup_empty_snapshot_info(snapshot_info_t *); + /* Construit une description pour instantané de base de données. */ bool init_snapshot_info(snapshot_info_t *); @@ -96,8 +107,9 @@ bool init_snapshot_info_from_text(snapshot_info_t *, const char *, uint64_t, con /* Libère la mémoire occupée par une description d'instantané. */ void exit_snapshot_info(snapshot_info_t *); +#define get_snapshot_info_parent_id(nfo) &(nfo)->parent_id #define get_snapshot_info_id(nfo) &(nfo)->id -#define get_snapshot_info_creation(nfo) (nfo)->created +#define get_snapshot_info_created(nfo) (nfo)->created #define get_snapshot_info_name(nfo) (nfo)->name #define get_snapshot_info_desc(nfo) (nfo)->desc diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c index dfc6f25..4d457e2 100644 --- a/src/analysis/db/misc/timestamp.c +++ b/src/analysis/db/misc/timestamp.c @@ -37,6 +37,25 @@ * * * Paramètres : timestamp = horodatage à initialiser. [OUT] * * * +* Description : Prépare un horodatage à une définition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void setup_empty_timestamp(timestamp_t *timestamp) +{ + *timestamp = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : timestamp = horodatage à initialiser. [OUT] * +* * * Description : Obtient un horodatage initialisé au moment même. * * * * Retour : Bilan de l'opération. * diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h index 7f6290876..52b99f8 100644 --- a/src/analysis/db/misc/timestamp.h +++ b/src/analysis/db/misc/timestamp.h @@ -38,6 +38,9 @@ typedef uint64_t timestamp_t; +/* Prépare un horodatage à une définition. */ +void setup_empty_timestamp(timestamp_t *); + /* Obtient un horodatage initialisé au moment même. */ bool init_timestamp(timestamp_t *); diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 22f564a..273be8e 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -103,6 +103,9 @@ typedef enum _DBAction +/* Marqueur de fin pour une transmission d'identifiants */ +#define SNAPSHOT_END_MARK "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + @@ -198,6 +201,34 @@ typedef enum _DBCommand /* ------- Gestion des instantanés ------- */ + /** + * Gestion de la commande 'DBC_GET_SNAPSHOTS'. + * + * Le client connecté envoie un paquet de la forme suivante : + * + * [ Gestion d'instantané : DBC_GET_SNAPSHOTS ] + * + * La définition d'un nouvel identifiant d'instantané courant se réalise dans : + * - g_hub_client_update() pour la partie client ; + * - g_cdb_archive_process() pour la partie serveur. + */ + + DBC_GET_SNAPSHOTS, + + /** + * Gestion de la commande 'DBC_SNAPSHOTS_UPDATED'. + * + * Le serveur envoie au client un paquet de la forme suivante : + * + * [ Gestion d'instantané : DBC_SNAPSHOTS_UPDATED ] + * [ ] + * [ Marqueur de fin : SNAPSHOT_END_MARK ] + * + * La définition d'un nouvel identifiant d'instantané courant se réalise dans : + * - g_cdb_archive_process() pour la partie serveur ; + * - g_hub_client_update() pour la partie client. + */ + DBC_SNAPSHOTS_UPDATED, /* Identification d'instantanés*/ /** diff --git a/src/analysis/db/snapshot.c b/src/analysis/db/snapshot.c index 6b762b7..79128ef 100644 --- a/src/analysis/db/snapshot.c +++ b/src/analysis/db/snapshot.c @@ -82,6 +82,9 @@ static snapshot_node_t *find_snapshot_node(snapshot_node_t *, const snapshot_id_ /* Ajoute un instantané comme prolongement d'un instantané. */ static void add_snapshot_node(snapshot_node_t *, snapshot_node_t *); +/* Collecte les descriptions d'une arborescence d'instantanés. */ +static bool pack_snapshot_node(const snapshot_node_t *, packed_buffer *); + /* --------------------- MANIPULATIONS D'ENSEMBLE D'INSTANTANES --------------------- */ @@ -378,7 +381,7 @@ static DBError save_snapshot_node(const snapshot_node_t *node, xmlDocPtr xdoc, x goto exit; } - created = get_snapshot_info_creation(&node->info); + created = get_snapshot_info_created(&node->info); status = _add_uint64_attribute_to_node(xml_node, "created", created); @@ -497,13 +500,47 @@ static snapshot_node_t *find_snapshot_node(snapshot_node_t *node, const snapshot static void add_snapshot_node(snapshot_node_t *node, snapshot_node_t *child) { + snapshot_id_t *src; /* Identifiant d'instantané #0 */ + snapshot_id_t *dest; /* Identifiant d'instantané #1 */ + node->children = realloc(node->children, ++node->count * sizeof(snapshot_node_t *)); node->children[node->count - 1] = child; + src = get_snapshot_info_id(&node->info); + dest = get_snapshot_info_parent_id(&child->info); + + copy_snapshot_id(dest, src); + } +/****************************************************************************** +* * +* Paramètres : node = définition d'instantané à consulter. * +* pbuf = paquet de données où venir inscrire des infos. * +* * +* Description : Collecte les descriptions d'une arborescence d'instantanés. * +* * +* Retour : Bilan du déroulement des opérations. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool pack_snapshot_node(const snapshot_node_t *node, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = pack_snapshot_info(&node->info, pbuf); + + for (i = 0; i < node->count && result; i++) + result = pack_snapshot_node(node->children[i], pbuf); + + return result; + +} @@ -1044,3 +1081,27 @@ sqlite3 *g_db_snapshot_get_database(const GDbSnapshot *snap, const snapshot_id_t return result; } + + +/****************************************************************************** +* * +* Paramètres : snap = gestionnaire d'instantanés à consulter. * +* pbuf = paquet de données où venir inscrire des infos. * +* * +* Description : Collecte les descriptions de l'ensemble des instantanés. * +* * +* Retour : Bilan du déroulement des opérations. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_snapshot_pack_all(const GDbSnapshot *snap, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = pack_snapshot_node(snap->nodes, pbuf); + + return result; + +} diff --git a/src/analysis/db/snapshot.h b/src/analysis/db/snapshot.h index f568ba3..543d184 100644 --- a/src/analysis/db/snapshot.h +++ b/src/analysis/db/snapshot.h @@ -74,6 +74,9 @@ bool g_db_snapshot_get_current_id(const GDbSnapshot *, snapshot_id_t *); /* Fournit la base de données correspondant à instanné donné. */ sqlite3 *g_db_snapshot_get_database(const GDbSnapshot *, const snapshot_id_t *); +/* Collecte les descriptions de l'ensemble des instantanés. */ +bool g_db_snapshot_pack_all(const GDbSnapshot *, packed_buffer *); + #endif /* _ANALYSIS_DB_SNAPSHOT_H */ diff --git a/src/common/packed.c b/src/common/packed.c index a8ce3c5..a10155d 100644 --- a/src/common/packed.c +++ b/src/common/packed.c @@ -241,7 +241,7 @@ bool extend_packed_buffer(packed_buffer *pbuf, const void *buf, size_t len, bool * * ******************************************************************************/ -bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh) +bool peek_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh) { bool result; /* Bilan à retourner */ uint16_t tmp16; /* Valeur intermédiaire 16b */ @@ -250,52 +250,102 @@ bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh result = ((pbuf->pos + len - sizeof(uint32_t)) <= pbuf->used); + if (!result) + goto failed; + /* Conversion au formalisme du réseau */ if (!ntoh) goto skip_conversion; - if (result) + switch (len) { - switch (len) - { - case 1: - *((uint8_t *)buf) = *((uint8_t *)(pbuf->data + pbuf->pos)); - break; + case 1: + *((uint8_t *)buf) = *((uint8_t *)(pbuf->data + pbuf->pos)); + break; - case 2: - tmp16 = be16toh(*(uint16_t *)(pbuf->data + pbuf->pos)); - *((uint16_t *)buf) = tmp16; - break; + case 2: + tmp16 = be16toh(*(uint16_t *)(pbuf->data + pbuf->pos)); + *((uint16_t *)buf) = tmp16; + break; - case 4: - tmp32 = be32toh(*(uint32_t *)(pbuf->data + pbuf->pos)); - *((uint32_t *)buf) = tmp32; - break; + case 4: + tmp32 = be32toh(*(uint32_t *)(pbuf->data + pbuf->pos)); + *((uint32_t *)buf) = tmp32; + break; - case 8: - tmp64 = be64toh(*(uint64_t *)(pbuf->data + pbuf->pos)); - *((uint64_t *)buf) = tmp64; - break; + case 8: + tmp64 = be64toh(*(uint64_t *)(pbuf->data + pbuf->pos)); + *((uint64_t *)buf) = tmp64; + break; - default: + default: skip_conversion: - /** - * Dans ce cas de figure, c'est à l'appelant de s'assurer que la - * conversion a bien été réalisée. - */ - assert(!ntoh); + /** + * Dans ce cas de figure, c'est à l'appelant de s'assurer que la + * conversion a bien été réalisée. + */ + assert(!ntoh); + + memcpy(buf, pbuf->data + pbuf->pos, len); + break; - memcpy(buf, pbuf->data + pbuf->pos, len); - break; + } - } + failed: - pbuf->pos += len; + return result; - } +} + + +/****************************************************************************** +* * +* Paramètres : pbuf = paquet de données à consulter. * +* len = quantité de ces données. * +* * +* Description : Avance la tête de lecture dans les données d'un paquet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void advance_packed_buffer(packed_buffer *pbuf, size_t len) +{ + pbuf->pos += len; + + assert((pbuf->pos - sizeof(uint32_t)) <= pbuf->used); + +} + + +/****************************************************************************** +* * +* Paramètres : pbuf = paquet de données à consulter. * +* buf = nouvelles données à définir. * +* len = quantité de ces données. * +* ntoh = indique si une conversion est à réaliser. * +* * +* Description : Récupère des données depuis un paquet après une réception. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool extract_packed_buffer(packed_buffer *pbuf, void *buf, size_t len, bool ntoh) +{ + bool result; /* Bilan à retourner */ + + result = peek_packed_buffer(pbuf, buf, len, ntoh); + + if (result) + advance_packed_buffer(pbuf, len); return result; diff --git a/src/common/packed.h b/src/common/packed.h index 4403ad0..019d21a 100644 --- a/src/common/packed.h +++ b/src/common/packed.h @@ -66,6 +66,12 @@ bool has_more_data_in_packed_buffer(const packed_buffer *); bool extend_packed_buffer(packed_buffer *, const void *, size_t, bool); /* Récupère des données depuis un paquet après une réception. */ +bool peek_packed_buffer(packed_buffer *, void *, size_t, bool); + +/* Avance la tête de lecture dans les données d'un paquet. */ +void advance_packed_buffer(packed_buffer *, size_t); + +/* Récupère des données depuis un paquet après une réception. */ bool extract_packed_buffer(packed_buffer *, void *, size_t, bool); /* Lit des données depuis un flux local. */ -- cgit v0.11.2-87-g4458