From f439711a77e0719e7f1dcf4b5c5511157986c918 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 14 Oct 2019 01:24:57 +0200 Subject: Retrieved the current snapshot identifier from servers. --- plugins/pychrysalide/analysis/db/client.c | 100 +++++++++++++ src/analysis/db/cdb.c | 42 ++++++ src/analysis/db/client.c | 112 +++++++++++++++ src/analysis/db/client.h | 7 + src/analysis/db/item.c | 9 ++ src/analysis/db/misc/snapshot.c | 228 ++++++++++++++++++++++++++++++ src/analysis/db/misc/snapshot.h | 30 +++- src/analysis/db/misc/timestamp.c | 71 +++++++++- src/analysis/db/misc/timestamp.h | 8 +- src/analysis/db/protocol.h | 58 +++++++- src/common/packed.c | 2 +- src/common/xml.c | 138 ++++++++++++++++++ src/common/xml.h | 13 ++ 13 files changed, 806 insertions(+), 12 deletions(-) diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c index e5b67da..afece26 100644 --- a/plugins/pychrysalide/analysis/db/client.c +++ b/plugins/pychrysalide/analysis/db/client.c @@ -54,6 +54,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 l'identifiant de l'instantané courant. */ +static PyObject *py_hub_client_get_current_snapshot(PyObject *, void *); + /****************************************************************************** @@ -332,6 +335,102 @@ 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 l'identifiant de l'instantané courant. * +* * +* Retour : Identifiant d'instantané ou None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_hub_client_get_current_snapshot(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GHubClient *client; /* Version native du serveur */ + snapshot_id_t id; /* Identifiant à transmettre */ + bool status; /* Validité de cet identifiant */ + +#define HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + current_snapshot, py_hub_client, \ + "Identifier of the current snapshot, provided as a string." \ + "\n" \ + "The returned value is a cached version of the value stored at" \ + " server side. Thus, defining a new current snapshot is" \ + " successful as soon as the request to this server is sent." \ +) + + client = G_HUB_CLIENT(pygobject_get(self)); + + status = g_hub_client_get_current_snapshot(client, &id); + + if (status) + result = PyUnicode_FromString(snapshot_id_as_string(&id)); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = adresse non utilisée ici. * +* * +* Description : Définit l'identifiant de l'instantané courant. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_hub_client_set_current_snapshot(PyObject *self, PyObject *value, void *closure) +{ + int ret; /* Bilan d'analyse */ + void *raw; /* Valeur brute d'identifiant */ + snapshot_id_t id; /* Identifiant reconnu */ + bool status; /* Bilan d'une conversion */ + GHubClient *client; /* Version native du serveur */ + + ret = PyUnicode_Check(value); + if (!ret) return -1; + + raw = PyUnicode_DATA(value); + + status = init_snapshot_id_from_text(&id, raw); + if (!status) + { + PyErr_SetString(PyExc_TypeError, _("provided value is not a valid snapshot identifier.")); + return -1; + } + + client = G_HUB_CLIENT(pygobject_get(self)); + + status = g_hub_client_set_current_snapshot(client, &id); + if (!status) + { + PyErr_SetString(PyExc_TypeError, "unable to send the provided snapshot identifier"); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -353,6 +452,7 @@ PyTypeObject *get_python_hub_client_type(void) }; static PyGetSetDef py_hub_client_getseters[] = { + HUB_CLIENT_CURRENT_SNAPSHOT_ATTRIB, { NULL } }; diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 2013750..8e8813a 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -841,6 +841,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive) DBError error; /* Bilan d'une opération */ packed_buffer out_pbuf; /* Tampon d'émission */ GDbCollection *collec; /* Collection visée au final */ + snapshot_id_t id; /* Identifiant d'instantané */ char *msg; /* Erreur à faire remonter */ void interrupt_poll_with_sigusr1(int sig) { }; @@ -910,6 +911,8 @@ static void *g_cdb_archive_process(GCdbArchive *archive) status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].ssl_fd); if (!status) goto gcap_bad_exchange; + next_command: + status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true); if (!status) goto gcap_bad_exchange; @@ -1000,6 +1003,42 @@ static void *g_cdb_archive_process(GCdbArchive *archive) break; + case DBC_GET_CUR_SNAPSHOT: + + init_packed_buffer(&out_pbuf); + + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_CUR_SNAPSHOT_UPDATED }, + sizeof(uint32_t), true); + if (!status) goto gcap_bad_reply; + +#ifndef NDEBUG + status = g_db_snapshot_get_current_id(archive->snapshot, &id); + assert(status); +#else + g_db_snapshot_get_current_id(archive->snapshot, &id); +#endif + + status = pack_snapshot_id(&id, &out_pbuf); + 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_CUR_SNAPSHOT_UPDATED: + log_variadic_message(LMT_INFO, + _("This command is not available on this side: 0x%08x"), command); + goto gcap_bad_exchange; + break; + + case DBC_SET_CUR_SNAPSHOT: + + + break; + default: asprintf(&msg, _("Bad protocol command: 0x%08x"), command); LOG_ERROR(LMT_ERROR, msg); @@ -1009,6 +1048,9 @@ static void *g_cdb_archive_process(GCdbArchive *archive) } + if (has_more_data_in_packed_buffer(&in_pbuf)) + goto next_command; + exit_packed_buffer(&in_pbuf); continue; diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 4c525e1..3372c74 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -76,6 +76,12 @@ struct _GHubClient bool can_get_updates; /* Réception de maj possibles ?*/ GThread *update; /* Procédure de traitement */ + + + + snapshot_id_t current; /* Instantané courant */ + bool has_current; /* Validité de l'identifiant */ + }; /* Description de client à l'écoute (classe) */ @@ -162,6 +168,8 @@ static void g_hub_client_init(GHubClient *client) client->tls_fd = NULL; client->desc = NULL; + client->has_current = false; + } @@ -686,6 +694,7 @@ static void *g_hub_client_update(GHubClient *client) DBError error; /* Bilan d'une commande passée */ GDbCollection *collec; /* Collection visée au final */ uint8_t tmp8; /* Valeur sur 8 bits */ + snapshot_id_t id; /* Identifiant d'instantané */ char *msg; /* Message d'erreur à imprimer */ /** @@ -694,6 +703,13 @@ static void *g_hub_client_update(GHubClient *client) init_packed_buffer(&out_pbuf); + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_CUR_SNAPSHOT }, sizeof(uint32_t), true); + if (!status) + { + exit_packed_buffer(&out_pbuf); + goto exit; + } + status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_GET_ALL_ITEMS }, sizeof(uint32_t), true); if (!status) { @@ -798,6 +814,28 @@ static void *g_hub_client_update(GHubClient *client) client->can_get_updates = (tmp8 == 0x1); break; + case DBC_GET_CUR_SNAPSHOT: + log_variadic_message(LMT_INFO, + _("This command is not available on this side: 0x%08x"), command); + goto gdcu_bad_exchange; + break; + + case DBC_CUR_SNAPSHOT_UPDATED: + + status = unpack_snapshot_id(&id, &in_pbuf); + if (!status) goto gdcu_bad_exchange; + + copy_snapshot_id(&client->current, &id); + client->has_current = true; + + break; + + case DBC_SET_CUR_SNAPSHOT: + log_variadic_message(LMT_INFO, + _("This command is not available on this side: 0x%08x"), command); + goto gdcu_bad_exchange; + break; + } if (has_more_data_in_packed_buffer(&in_pbuf)) @@ -1092,3 +1130,77 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp) 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. * +* * +* Retour : true si l'identifiant retourné est valide, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_get_current_snapshot(GHubClient *client, snapshot_id_t *id) +{ + bool result; /* Validité à retourner */ + + result = client->has_current; + + if (result) + copy_snapshot_id(id, &client->current); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : client = client pour les accès distants à manipuler. * +* id = identifiant d'instantané à activer. * +* * +* Description : Définit l'identifiant de l'instantané courant. * +* * +* Retour : true si la commande a bien été envoyée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_hub_client_set_current_snapshot(GHubClient *client, const snapshot_id_t *id) +{ + bool result; /* Bilan partiel à remonter */ + packed_buffer out_pbuf; /* Tampon d'émission */ + SSL *tls_fd; /* Canal de communication SSL */ + + init_packed_buffer(&out_pbuf); + + tls_fd = g_hub_client_get_ssl_fd(client); + + if (tls_fd == NULL) + result = false; + + else + { + result = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SET_CUR_SNAPSHOT }, sizeof(uint32_t), true); + + if (result) + result = pack_snapshot_id(id, &out_pbuf); + + if (result) + result = ssl_send_packed_buffer(&out_pbuf, tls_fd); + + g_hub_client_put_ssl_fd(client, tls_fd); + + } + + exit_packed_buffer(&out_pbuf); + + return result; + +} diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index f7f7bcb..36d24e6 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -31,6 +31,7 @@ #include "collection.h" +#include "misc/snapshot.h" @@ -73,6 +74,12 @@ 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 l'identifiant de l'instantané courant. */ +bool g_hub_client_get_current_snapshot(GHubClient *, snapshot_id_t *); + +/* Définit l'identifiant de l'instantané courant. */ +bool g_hub_client_set_current_snapshot(GHubClient *, const snapshot_id_t *); + #endif /* _ANALYSIS_DB_CLIENT_H */ diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index 8fc1763..b3b00fe 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -200,7 +200,16 @@ DBFeatures g_db_item_get_feature(const GDbItem *item) void g_db_item_set_server_side(GDbItem *item) { +#ifndef NDEBUG + bool status; /* Bilan d'une initialisation */ +#endif + +#ifndef NDEBUG + status = init_timestamp(&item->created); + assert(status); +#else init_timestamp(&item->created); +#endif } diff --git a/src/analysis/db/misc/snapshot.c b/src/analysis/db/misc/snapshot.c index 982553b..546191b 100644 --- a/src/analysis/db/misc/snapshot.c +++ b/src/analysis/db/misc/snapshot.c @@ -210,8 +210,236 @@ bool pack_snapshot_id(const snapshot_id_t *id, packed_buffer *pbuf) /* ---------------------------------------------------------------------------------- */ +/****************************************************************************** +* * +* 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. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_snapshot_info(snapshot_info_t *info) +{ + bool result; /* Bilan à retourner */ + + result = init_snapshot_id(&info->id); + + if (result) + result = init_timestamp(&info->created); + + if (result) + { + info->name = NULL; + info->desc = NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = description d'instantané à initialiser. [OUT] * +* id = source de données pour l'identifiant. * +* created = source de données pour la date de création. * +* name = source de données éventuelle pour le nom. * +* desc = source de données éventuelle pour la description. * +* * +* Description : Construit une description pour instantané de base de données.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_snapshot_info_from_text(snapshot_info_t *info, const char *id, uint64_t created, const char *name, const char *desc) +{ + bool result; /* Bilan à retourner */ + + result = init_snapshot_id_from_text(&info->id, id); + + if (result) + result = init_timestamp_from_value(&info->created, created); + + if (result) + { + if (name == NULL) + info->name = NULL; + else + info->name = strdup(name); + + if (desc == NULL) + info->desc = NULL; + else + info->desc = strdup(desc); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = description d'instantané à initialiser. [OUT] * +* * +* Description : Libère la mémoire occupée par une description d'instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_snapshot_info(snapshot_info_t *info) +{ + if (info->name != NULL) + { + free(info->name); + info->name = NULL; + } + + if (info->desc != NULL) + { + free(info->desc); + info->desc = NULL; + } + +} + + +/****************************************************************************** +* * +* Paramètres : dest = destination de la copie de description. [OUT] * +* src = source de la description à copier. * +* * +* Description : Effectue une copie de description d'instantané. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void copy_snapshot_info(snapshot_info_t *dest, const snapshot_info_t *src) +{ + exit_snapshot_info(dest); + + copy_snapshot_id(&dest->id, &src->id); + + copy_timestamp(&dest->created, &src->created); + + if (src->name != NULL) + dest->name = strdup(src->name); + + if (src->desc != NULL) + dest->desc = strdup(src->desc); + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations à constituer. [OUT] * +* pbuf = paquet de données où venir puiser les infos. * +* * +* Description : Importe la description d'un identifiant d'instantané. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool unpack_snapshot_info(snapshot_info_t *info, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + rle_string string; /* Chaîne à transmettre */ + + result = unpack_snapshot_id(&info->id, pbuf); + + if (result) + result = unpack_timestamp(&info->created, pbuf); + + if (result) + { + result = unpack_rle_string(&string, pbuf); + if (result) + { + info->name = strdup(get_rle_string(&string)); + exit_rle_string(&string); + } + + } + if (result) + { + result = unpack_rle_string(&string, pbuf); + if (result) + { + info->desc = strdup(get_rle_string(&string)); + exit_rle_string(&string); + } + } + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = informations à sauvegarer. * +* pbuf = paquet de données où venir inscrire les infos. * +* * +* Description : Exporte la description d'un identifiant d'instantané. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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); + + if (result) + result = pack_timestamp(&info->created, pbuf); + + if (result) + { + init_static_rle_string(&string, info->name); + + result = pack_rle_string(&string, pbuf); + + exit_rle_string(&string); + + } + + if (result) + { + init_static_rle_string(&string, info->desc); + + result = pack_rle_string(&string, pbuf); + + exit_rle_string(&string); + + } + + return result; + +} diff --git a/src/analysis/db/misc/snapshot.h b/src/analysis/db/misc/snapshot.h index 4aaa6f9..e3a003c 100644 --- a/src/analysis/db/misc/snapshot.h +++ b/src/analysis/db/misc/snapshot.h @@ -29,6 +29,8 @@ #include +#include "rlestr.h" +#include "timestamp.h" #include "../../../common/packed.h" @@ -42,7 +44,7 @@ /* Représentation d'un instantané */ typedef struct _snapshot_id_t { - char name[SNAP_ID_HEX_SZ]; + char name[SNAP_ID_HEX_SZ]; /* Caractères hexadécimaux */ } snapshot_id_t; @@ -72,10 +74,36 @@ bool pack_snapshot_id(const snapshot_id_t *, packed_buffer *); /* --------------------------- PROPRIETES DES INSTANTANES --------------------------- */ +/* Description d'un instantané */ +typedef struct _snapshot_info_t +{ + snapshot_id_t id; /* Identifiant attribué */ + + timestamp_t created; /* Date de création */ + + char *name; /* Nom de l'instantané */ + char *desc; /* Description associée */ + +} snapshot_info_t; + + +/* Construit une description pour instantané de base de données. */ +bool init_snapshot_info(snapshot_info_t *); + +/* Construit une description pour instantané de base de données. */ +bool init_snapshot_info_from_text(snapshot_info_t *, const char *, uint64_t, const char *, const char *); +/* Libère la mémoire occupée par une description d'instantané. */ +void exit_snapshot_info(snapshot_info_t *); +/* Effectue une copie de description d'instantané. */ +void copy_snapshot_info(snapshot_info_t *, const snapshot_info_t *); +/* Importe la description d'un identifiant d'instantané. */ +bool unpack_snapshot_info(snapshot_info_t *, packed_buffer *); +/* Exporte la description d'un identifiant d'instantané. */ +bool pack_snapshot_info(const snapshot_info_t *, packed_buffer *); diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c index 12299eb..dfc6f25 100644 --- a/src/analysis/db/misc/timestamp.c +++ b/src/analysis/db/misc/timestamp.c @@ -29,6 +29,9 @@ #include +#include "../../../core/logs.h" + + /****************************************************************************** * * @@ -36,19 +39,59 @@ * * * Description : Obtient un horodatage initialisé au moment même. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void init_timestamp(timestamp_t *timestamp) +bool init_timestamp(timestamp_t *timestamp) { + bool result; /* Bilan à retourner */ struct timespec info; /* Détails sur l'époque */ + int ret; /* Bilan de la récupération */ + + ret = clock_gettime(CLOCK_REALTIME, &info); - clock_gettime(CLOCK_REALTIME, &info); + if (ret != 0) + { + LOG_ERROR_N("clock_gettime"); + result = false; + } - *timestamp = info.tv_sec * 1000000 + info.tv_nsec / 1000; + else + { + *timestamp = info.tv_sec * 1000000 + info.tv_nsec / 1000; + result = true; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : timestamp = horodatage à initialiser. [OUT] * +* value = valeur d'initialisation. * +* * +* Description : Obtient un horodatage initialisé avec une valeur donnée. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_timestamp_from_value(timestamp_t *timestamp, uint64_t value) +{ + bool result; /* Bilan à retourner */ + + result = true; + + *timestamp = value; + + return result; } @@ -79,6 +122,26 @@ bool timestamp_is_younger(timestamp_t stamp, timestamp_t limit) /****************************************************************************** * * +* Paramètres : dest = destination de la copie d'horodatage. [OUT] * +* src = source de l'horodatage à copier. * +* * +* Description : Effectue une copie d'horodatage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void copy_timestamp(timestamp_t *dest, const timestamp_t *src) +{ + *dest = *src; + +} + + +/****************************************************************************** +* * * Paramètres : t1 = premier horodatage à comparer. * * t2 = second horodatage à comparer. * * * diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h index 002f4d4..7f6290876 100644 --- a/src/analysis/db/misc/timestamp.h +++ b/src/analysis/db/misc/timestamp.h @@ -39,11 +39,17 @@ typedef uint64_t timestamp_t; /* Obtient un horodatage initialisé au moment même. */ -void init_timestamp(timestamp_t *); +bool init_timestamp(timestamp_t *); + +/* Obtient un horodatage initialisé avec une valeur donnée. */ +bool init_timestamp_from_value(timestamp_t *, uint64_t); /* Définit si un horodatage est plus récent qu'un autre ou non. */ bool timestamp_is_younger(timestamp_t, timestamp_t); +/* Effectue une copie d'horodatage. */ +void copy_timestamp(timestamp_t *, const timestamp_t *); + /* Effectue la comparaison entre deux horodatages. */ int cmp_timestamp(const timestamp_t *, const timestamp_t *); diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index b42ad15..22f564a 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -127,8 +127,8 @@ typedef enum _DBCommand * [ 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_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. * */ @@ -165,7 +165,7 @@ typedef enum _DBCommand * [ marqueur de fin : octet 0x0 ] * * Les traitements se réalisent dans : - * - g_db_client_update() pour la partie client. + * - g_db_client_update() pour la partie client ; * - g_cdb_archive_process() pour la partie serveur. * */ @@ -179,7 +179,7 @@ typedef enum _DBCommand * Le client connecté envoie un paquet de la forme suivante : * * [ Statut d'historique : DBC_SET_LAST_ACTIVE ] - * [ ] * * Le serveur s'exécute et notifie le client d'éventuels changements, * avec une série de paquets de la forme : @@ -189,13 +189,61 @@ typedef enum _DBCommand * [ <élément dont le statut a évolué> ] * * Les traitements se réalisent dans : - * - g_db_collection_disable_at() pour la partie serveur. + * - g_db_collection_disable_at() pour la partie serveur ; * - g_db_collection_update_item_state() pour la partie client. * */ DBC_SET_LAST_ACTIVE, /* Définition du dernier actif */ // REMME + /* ------- Gestion des instantanés ------- */ + + DBC_SNAPSHOTS_UPDATED, /* Identification d'instantanés*/ + + /** + * Gestion de la commande 'DBC_GET_CUR_SNAPSHOT'. + * + * Le client connecté envoie un paquet de la forme suivante : + * + * [ Gestion d'instantané : DBC_GET_CUR_SNAPSHOT ] + * + * 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_CUR_SNAPSHOT, /* Demande d'identification */ + + /** + * Gestion de la commande 'DBC_CUR_SNAPSHOT_UPDATED'. + * + * Le serveur envoie au client un paquet de la forme suivante : + * + * [ Gestion d'instantané : DBC_CUR_SNAPSHOT_UPDATED ] + * [ ] + * + * 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_CUR_SNAPSHOT_UPDATED, /* Mise à jour de l'instantané */ + + /** + * Gestion de la commande 'DBC_SET_CUR_SNAPSHOT'. + * + * Le client connecté envoie un paquet de la forme suivante : + * + * [ Gestion d'instantané : DBC_SET_CUR_SNAPSHOT ] + * [ ] + * + * La définition d'un nouvel identifiant d'instantané courant se réalise dans : + * - g_hub_client_set_current_snapshot() pour la partie client ; + * - + */ + + DBC_SET_CUR_SNAPSHOT, /* Définition de l'instantané */ + DBC_COUNT } DBCommand; diff --git a/src/common/packed.c b/src/common/packed.c index 163ed3b..a8ce3c5 100644 --- a/src/common/packed.c +++ b/src/common/packed.c @@ -141,7 +141,7 @@ bool has_more_data_in_packed_buffer(const packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - result = (pbuf->pos < pbuf->used); + result = (pbuf->pos < (pbuf->used + sizeof(uint32_t))); return result; diff --git a/src/common/xml.c b/src/common/xml.c index aaed2ea..3774359 100644 --- a/src/common/xml.c +++ b/src/common/xml.c @@ -25,6 +25,8 @@ #include "xml.h" +#include +#include #include #include #include @@ -453,6 +455,43 @@ bool qck_get_node_prop_long_value(xmlNodePtr node, const char *name, long *out) /****************************************************************************** * * +* Paramètres : node = noeud dont une propriété est à lire. * +* name = nom de la propriété à lire. * +* out = valeur entière lue depuis le contenu textuel. [OUT] * +* * +* Description : Obtient la valeur entière d'une propriété d'un élément. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool qck_get_node_prop_uint64_value(xmlNodePtr node, const char *name, uint64_t *out) +{ + bool result; /* Bilan à retourner */ + char *value; /* Valeur brute lue */ + + value = qck_get_node_prop_value(node, name); + + if (value) + { + result = true; + + *out = strtoull(value, NULL, 10); + free(value); + + } + else + result = false; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : xpathCtx = contexte à utiliser pour les recherches. * * path = chemin d'accès au noeud à traiter. * * name = nom de la propriété à lire. * @@ -522,6 +561,41 @@ bool get_node_prop_long_value(xmlXPathContextPtr xpathCtx, const char *path, con /****************************************************************************** * * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud à traiter. * +* name = nom de la propriété à lire. * +* out = valeur entière obtenue via contenu textuel. [OUT] * +* * +* Description : Obtient la valeur entière d'une propriété d'un élément. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_node_prop_uint64_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name, uint64_t *out) +{ + bool result; /* Bilan à retourner */ + xmlXPathObjectPtr xpathObj; /* Point de départ XML */ + + result = NULL; + + xpathObj = get_node_xpath_object(xpathCtx, path); + if (xpathObj == NULL) return NULL; + + if (xpathObj->nodesetval->nodeNr > 0) + result = qck_get_node_prop_uint64_value(xpathObj->nodesetval->nodeTab[0], name, out); + + xmlXPathFreeObject(xpathObj); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : node = noeud de texte avec un lien avec le document XML. * * * * Description : Construit un chemin d'accès complet selon le fichier XML. * @@ -1250,3 +1324,67 @@ bool add_long_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, cons return _add_long_attribute_to_node(node, name, value); } + + +/****************************************************************************** +* * +* Paramètres : node = noeud dont le contenu est à mettre à jour. * +* name = nom de la propriété à créer. * +* value = valeur numérique à placer. * +* * +* Description : Ajoute une propriété à un noeud existant donné. * +* * +* Retour : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _add_uint64_attribute_to_node(xmlNodePtr node, const char *name, uint64_t value) +{ + bool result; /* Bilan à retourner */ + char *tmp; /* Stockage temporaire */ + int ret; /* Bilan de l'impression */ + + ret = asprintf(&tmp, "%" PRIu64, value); + + if (ret == -1) + result = false; + + else + { + result = _add_string_attribute_to_node(node, name, tmp); + free(tmp); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* name = nom de la propriété à créer. * +* value = valeur numérique à placer. * +* * +* Description : Ajoute une propriété à un noeud existant donné. * +* * +* Retour : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_uint64_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, uint64_t value) +{ + xmlNodePtr node; /* Noeud à modifier */ + + node = ensure_node_exist(xdoc, context, path); + if (node == NULL) return false; + + return _add_uint64_attribute_to_node(node, name, value); + +} diff --git a/src/common/xml.h b/src/common/xml.h index ed009c6..5ae7664 100644 --- a/src/common/xml.h +++ b/src/common/xml.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -79,12 +80,18 @@ char *qck_get_node_prop_value(xmlNodePtr, const char *); /* Obtient la valeur entière d'une propriété d'un élément. */ bool qck_get_node_prop_long_value(xmlNodePtr, const char *, long *); +/* Obtient la valeur entière d'une propriété d'un élément. */ +bool qck_get_node_prop_uint64_value(xmlNodePtr, const char *, uint64_t *); + /* Obtient la valeur d'une propriété d'un élément. */ char *get_node_prop_value(xmlXPathContextPtr, const char *, const char *); /* Obtient la valeur entière d'une propriété d'un élément. */ bool get_node_prop_long_value(xmlXPathContextPtr, const char *, const char *, long *); +/* Obtient la valeur entière d'une propriété d'un élément. */ +bool get_node_prop_uint64_value(xmlXPathContextPtr, const char *, const char *, uint64_t *); + /* Construit un chemin d'accès complet selon le fichier XML. */ char *qck_build_filename_with_doc_url(xmlNodePtr); @@ -158,6 +165,12 @@ bool _add_long_attribute_to_node(xmlNodePtr, const char *, long); /* Ajoute une propriété à un noeud existant donné. */ bool add_long_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, long); +/* Ajoute une propriété à un noeud existant donné. */ +bool _add_uint64_attribute_to_node(xmlNodePtr, const char *, uint64_t); + +/* Ajoute une propriété à un noeud existant donné. */ +bool add_uint64_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, uint64_t); + #endif /* _XML_H */ -- cgit v0.11.2-87-g4458