diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/db/analyst.c | 140 | ||||
| -rw-r--r-- | src/analysis/db/analyst.h | 14 | ||||
| -rw-r--r-- | src/analysis/db/cdb.c | 133 | ||||
| -rw-r--r-- | src/analysis/db/protocol.h | 31 | ||||
| -rw-r--r-- | src/analysis/db/server.c | 4 | 
5 files changed, 290 insertions, 32 deletions
diff --git a/src/analysis/db/analyst.c b/src/analysis/db/analyst.c index ab12cc1..2e1cc23 100644 --- a/src/analysis/db/analyst.c +++ b/src/analysis/db/analyst.c @@ -35,6 +35,17 @@ + + + + +/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */ + + + + + +  /* Description de client à l'écoute (instance) */  struct _GAnalystClient  { @@ -65,6 +76,8 @@ struct _GAnalystClientClass      /* Signaux */ +    void (* ready) (GAnalystClient *); +    void (* server_status_changed) (GAnalystClient *, LoadingStatusHint);      void (* snapshots_updated) (GAnalystClient *);      void (* snapshot_changed) (GAnalystClient *); @@ -97,6 +110,56 @@ static bool g_analyst_client_update_current_snapshot(GAnalystClient *, packed_bu +/* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */ + + +/* Prend en compte une évolution du statut côté serveur. */ +static bool g_analyst_client_handle_loading_hints(GAnalystClient *, packed_buffer_t *); + + + + +/* ---------------------------------------------------------------------------------- */ +/*                                 GLUES POUR LA GLIB                                 */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Définit un type GLib pour l'énumération "LoadingStatusHint". * +*                                                                             * +*  Retour      : Type GLib enregistré.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GType g_loading_status_hint_type(void) +{ +    static GType result = 0; + +    static const GEnumValue values[] = { +        { LSH_READY, "LSH_READY", "ready" }, +        { LSH_ON_WAIT_LIST, "LSH_ON_WAIT_LIST", "on_wait_list" }, +        { LSH_NEED_CONTENT, "LSH_NEED_CONTENT", "need_content" }, +        { LSH_NEED_FORMAT, "LSH_NEED_FORMAT", "need_format" }, +        { LSH_NEED_ARCH, "LSH_NEED_ARCH", "need_arch" }, +        { 0, NULL, NULL } +    }; + +    if (result == 0) +        result = g_enum_register_static(g_intern_static_string("LoadingStatusHint"), values); + +    return result; + +} + + + + +  /* Indique le type défini pour une description de client à l'écoute. */  G_DEFINE_TYPE(GAnalystClient, g_analyst_client, G_TYPE_HUB_CLIENT); @@ -129,6 +192,22 @@ static void g_analyst_client_class_init(GAnalystClientClass *klass)      client->complete_hello = (complete_client_hello_fc)g_analyst_client_complete_hello;      client->recv_func = (GThreadFunc)g_analyst_client_update; +    g_signal_new("ready", +                 G_TYPE_ANALYST_CLIENT, +                 G_SIGNAL_RUN_LAST, +                 G_STRUCT_OFFSET(GAnalystClientClass, ready), +                 NULL, NULL, +                 g_cclosure_marshal_VOID__VOID, +                 G_TYPE_NONE, 0); + +    g_signal_new("server-status-changed", +                 G_TYPE_ANALYST_CLIENT, +                 G_SIGNAL_RUN_LAST, +                 G_STRUCT_OFFSET(GAnalystClientClass, server_status_changed), +                 NULL, NULL, +                 g_cclosure_marshal_VOID__ENUM, +                 G_TYPE_NONE, 1, G_TYPE_LOADING_STATUS_HINT); +      g_signal_new("snapshots-updated",                   G_TYPE_ANALYST_CLIENT,                   G_SIGNAL_RUN_LAST, @@ -430,6 +509,11 @@ static void *g_analyst_client_update(GAnalystClient *client)              switch (command)              { +                case DBC_LOADING_STATUS: +                    status = g_analyst_client_handle_loading_hints(client, &in_pbuf); +                    if (!status) goto gdcu_bad_exchange; +                    break; +                  case DBC_SAVE:                      status = extract_packed_buffer(&in_pbuf, &tmp32, sizeof(uint32_t), true); @@ -1285,3 +1369,59 @@ bool g_analyst_client_remove_snapshot(GAnalystClient *client, const snapshot_id_      return result;  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                           PRISES EN COMPTE DES COMMANDES                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : archive  = archive à connecter avec un utilisateur.          * +*                in_pbuf  = paquet à consulter.                               * +*                                                                             * +*  Description : Prend en compte une évolution du statut côté serveur.        * +*                                                                             * +*  Retour      : Indication pour le maintien de la communication.             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_analyst_client_handle_loading_hints(GAnalystClient *client, packed_buffer_t *in_pbuf) +{ +    bool result;                            /* Bilan à retourner           */ +    uleb128_t hint;                         /* Indication du serveur       */ + +    result = unpack_uleb128(&hint, in_pbuf); + +    switch (hint) +    { +        case LSH_READY: +            g_signal_emit_by_name(client, "ready"); +            break; + +        case LSH_ON_WAIT_LIST: +            log_simple_message(LMT_INFO, _("Waiting for content from server...")); +            break; + +        case LSH_NEED_CONTENT: +        case LSH_NEED_FORMAT: +        case LSH_NEED_ARCH: +            g_signal_emit_by_name(client, "server-status-changed", hint); +            break; + +        default: +            log_variadic_message(LMT_ERROR, +                                 _("Unknown loaded hint received (%x); unsupported newer protocol?"), +                                 hint); +            result = false; +            break; + +    } + +    return result; + +} diff --git a/src/analysis/db/analyst.h b/src/analysis/db/analyst.h index 9f7b32b..459034e 100644 --- a/src/analysis/db/analyst.h +++ b/src/analysis/db/analyst.h @@ -38,6 +38,20 @@ + +/* ------------------------------- GLUES POUR LA GLIB ------------------------------- */ + + +#define G_TYPE_LOADING_STATUS_HINT g_loading_status_hint_type() + + +/* Définit un type GLib pour l'énumération "LoadingStatusHint". */ +GType g_loading_status_hint_type(void); + + + + +  #define G_TYPE_ANALYST_CLIENT            g_analyst_client_get_type()  #define G_ANALYST_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ANALYST_CLIENT, GAnalystClient))  #define G_IS_ANALYST_CLIENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ANALYST_CLIENT)) diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index c5d3af7..b1e47bc 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -101,9 +101,13 @@ struct _GCdbArchive      char *filename;                         /* Chemin d'accès à l'archive  */      char *tmpdir;                           /* Répertoire de travail       */ -    char *cnt_file;                         /* Fichier de contenu binaire  */      char *xml_desc;                         /* Fichier de description      */ +    char *cnt_file;                         /* Fichier de contenu binaire  */ + +    GMutex loading_access;                  /* Verrou pour l'accès         */ + +      GList *collections;                     /* Ensemble de modifications   */      GDbSnapshot *snapshot;                  /* Instantanés de bases SQL    */ @@ -189,8 +193,8 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *, packed_buffer_t *)  /* ------------------------- PRISES EN COMPTE DES COMMANDES ------------------------- */ -/* Prépare la réponse à envoyer à un client connecté. */ -static bool setup_server_answer(DBCommand, DBError, packed_buffer_t *); +/* Prépare une courte réponse à envoyer à un client connecté. */ +static bool craft_server_short_answer(DBCommand, uleb128_t, packed_buffer_t *);  /* Enregistre le contenu binaire lié à une analyse. */  static bool g_cdb_archive_set_content(GCdbArchive *, packed_buffer_t *, packed_buffer_t *); @@ -218,7 +222,7 @@ static cdb_client *create_cdb_client(SSL *fd, const char *peer_name, const char  {      cdb_client *result;                     /* Fiche d'entité à retourner  */ -    result = malloc(sizeof(cdb_client *)); +    result = malloc(sizeof(cdb_client));      result->tls_fd = fd; @@ -358,9 +362,11 @@ static void g_cdb_archive_init(GCdbArchive *archive)      archive->filename = NULL;      archive->tmpdir = NULL; -    archive->cnt_file = NULL;      archive->xml_desc = NULL; +    archive->cnt_file = NULL; +    g_mutex_init(&archive->loading_access); +      archive->collections = create_collections_list();      archive->snapshot = NULL; @@ -387,9 +393,11 @@ static void g_cdb_archive_dispose(GCdbArchive *archive)  {      g_server_backend_stop(G_SERVER_BACKEND(archive)); +    g_mutex_clear(&archive->clients_access); +      g_clear_object(&archive->snapshot); -    g_mutex_clear(&archive->clients_access); +    g_mutex_clear(&archive->loading_access);      G_OBJECT_CLASS(g_cdb_archive_parent_class)->dispose(G_OBJECT(archive)); @@ -1459,38 +1467,100 @@ static void *g_cdb_archive_process(GCdbArchive *archive)  *                                                                             *  ******************************************************************************/ +static LoadingStatusHint g_cdb_archive_compute_loading_hint(GCdbArchive *archive) +{ +    LoadingStatusHint result;               /* Statut à retourner          */ + + +    // Try +    //    g_mutex_lock(&archive->loading_access); + + + +    // cnt_file + +    if (archive->cnt_file == NULL) +        result = LSH_NEED_CONTENT; + +    else +        result = LSH_NEED_FORMAT; + + + + + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : archive   = support pour le suivi d'une connexion.           * +*                fd        = canal de communication réseau ouvert.            * +*                peer_name = désignation de la connexion.                     * +*                user      = désignation de l'utilisateur de la connexion.    * +*                                                                             * +*  Description : Prend en compte une connexion nouvelle d'un utilisateur.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +  static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char *peer_name, const char *user)  {      cdb_client *client;                     /* Nouvelle fiche d'entité     */ +    packed_buffer_t out_pbuf;               /* Tampon d'émission           */ +    LoadingStatusHint hint;                 /* Statut de chargement        */ +    bool status;                            /* Bilan de lecture initiale   */ + +    client = create_cdb_client(fd, peer_name, user);      /** -     * La situation est un peu compliquée lors de l'accueil d'un nouveau client : -     * -     *    - soit on envoie tous les éléments à prendre en compte, mais on doit -     *      bloquer la base de données jusqu'à l'intégration pleine et entière -     *      du client, afin que ce dernier ne loupe pas l'envoi d'un nouvel -     *      élément entre temps. +     * Le verrou encadrant les évolutions des contenus initiaux doit englober +     * l'extension de la liste des clients.       * -     *    - soit on intègre le client et celui ci demande des mises à jour -     *      collection par collection ; c'est également à lui que revient le rejet -     *      des éléments envoyés en solitaires avant la réception de la base -     *      complète. +     * En effet, une évolution partielle peut intervenir dans la fonction +     * g_cdb_archive_process(), à un moment au seul le verrou dans les +     * évolutions sera posé (g_cdb_archive_set_content() par exemple).       * -     * On fait le choix du second scenario ici, du fait de la difficulté -     * de maîtriser facilement la reconstitution d'une liste de clients dans -     * g_cdb_archive_process() depuis un autre flot d'exécution. +     * Or g_cdb_archive_compute_loading_hint() doit fournir ici un état qui ne +     *  varie pas entre le calcul et l'envoi. Donc verrous sur les clients et +     * l'état de l'archive doivent englover l'ensemble des traitements ci-après.       */ -    client = create_cdb_client(fd, peer_name, user); +    g_mutex_lock(&archive->loading_access);      g_mutex_lock(&archive->clients_access); -    archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *)); +    hint = g_cdb_archive_compute_loading_hint(archive); + +    if (hint != LSH_READY) +        hint = (archive->count == 0 ? hint : LSH_ON_WAIT_LIST); + +    init_packed_buffer(&out_pbuf); + +    status = craft_server_short_answer(DBC_LOADING_STATUS, hint, &out_pbuf); + +    if (status) +        status = ssl_send_packed_buffer(&out_pbuf, fd); + +    exit_packed_buffer(&out_pbuf); + +    if (status) +    { +        archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *)); + +        archive->clients[archive->count - 1] = client; -    archive->clients[archive->count - 1] = client; +    }      g_mutex_unlock(&archive->clients_access); +    g_mutex_unlock(&archive->loading_access); +  } @@ -1694,10 +1764,10 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff  /******************************************************************************  *                                                                             *  *  Paramètres  : cmd      = commande à l'origine d'un traitement.             * -*                error    = bilan de traitement à communiquer.                * +*                value    = valeur à communiquer.                             *  *                out_pbuf = paquet à consituer pour un retour au client. [OUT]*  *                                                                             * -*  Description : Prépare la réponse à envoyer à un client connecté.           * +*  Description : Prépare une courte réponse à envoyer à un client connecté.   *  *                                                                             *  *  Retour      : Indication pour le maintien de la communication.             *  *                                                                             * @@ -1705,7 +1775,7 @@ static bool g_cdb_archive_send_snapshot_change(GCdbArchive *archive, packed_buff  *                                                                             *  ******************************************************************************/ -static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *out_pbuf) +static bool craft_server_short_answer(DBCommand cmd, uleb128_t value, packed_buffer_t *out_pbuf)  {      bool result;                            /* Bilan à retourner           */ @@ -1714,7 +1784,7 @@ static bool setup_server_answer(DBCommand cmd, DBError error, packed_buffer_t *o      result = extend_packed_buffer(out_pbuf, (uint32_t []) { cmd }, sizeof(uint32_t), true);      if (result) -        result = extend_packed_buffer(out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true); +        result = pack_uleb128((uleb128_t []){ value }, out_pbuf);      return result; @@ -1748,6 +1818,7 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_      const gchar *hash;                      /* Empreinte de ce contenu     */      int fd;                                 /* Flux ouvert en écriture     */      bool status;                            /* Bilan d'une écriture        */ +    LoadingStatusHint hint;                 /* Statut de chargement        */      result = true;      error = DBE_NONE; @@ -1848,7 +1919,15 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_      /* Formulation de la réponse */ -    result = setup_server_answer(DBC_SET_CONTENT, error, out_pbuf); +    result = craft_server_short_answer(DBC_SET_CONTENT, error, out_pbuf); + +    if (result && error == DBE_NONE) +    { +        hint = g_cdb_archive_compute_loading_hint(archive); + +        result = craft_server_short_answer(DBC_LOADING_STATUS, hint, out_pbuf); + +    }   free_and_exit: diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 17263c8..7707058 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -76,14 +76,21 @@ typedef enum _ServerPrivLevels +/** + * Précisions pour la commande DBC_LOADING_STATUS. + */ + +  /* Eléments de base nécessaires */ -typedef enum _RequiredBasics +typedef enum _LoadingStatusHint  { -    RBS_NONE    = 0x0,                      /* (Plus) rien n'est requis    */ -    RBS_CONTENT = 0x1,                      /* Contenu binaire à analyser  */ -    RBS_LOADED  = 0x2,                      /* Contenu binaire analysé     */ +    LSH_READY        = 0,                   /* (Plus) rien n'est requis    */ +    LSH_ON_WAIT_LIST = 1,                   /* Concurrence des connexions  */ +    LSH_NEED_CONTENT = 2,                   /* Suppléments nécessaires     */ +    LSH_NEED_FORMAT  = 3,                   /* Suppléments nécessaires     */ +    LSH_NEED_ARCH    = 4,                   /* Suppléments nécessaires     */ -} RequiredBasics; +} LoadingStatusHint; @@ -135,6 +142,8 @@ typedef enum _DBAction   */  typedef enum _DBCommand  { +    /* ------------------------- Commandes à portée générale ------------------------- */ +      /**       * Le client envoie un tout premier paquet de la forme suivante :       * @@ -176,6 +185,18 @@ typedef enum _DBCommand      /* ------------------------ Commandes pour analyste ------------------------ */      /** +     * Gestion de la commande 'DBC_LOADING_STATUS'. +     * +     * Le serveur envoie un statut de prise en charge au début d'une connexion : +     * +     *    [ Indication du serveur : DBC_LOADING_STATUS] +     *    [ Statut courant ; cf. LoadingStatusHint    ] +     * +     */ + +    DBC_LOADING_STATUS,                     /* Indications initiales       */ + +    /**       * Gestion de la commande 'DBC_SET_CONTENT'.       *       * Le client connecté envoie un paquet de la forme suivante : diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c index 5c6fd18..79d5df1 100644 --- a/src/analysis/db/server.c +++ b/src/analysis/db/server.c @@ -1088,6 +1088,8 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu      /* Fin de réception des données envoyées */ +    setup_empty_rle_string(&hash); +      status = unpack_rle_string(&hash, in_pbuf);      if (!status)      { @@ -1101,6 +1103,8 @@ static GServerBackend *g_hub_server_handle_analyst(GHubServer *server, packed_bu          goto wrong_receiving_0;      } +    setup_empty_rle_string(&class); +      status = unpack_rle_string(&class, in_pbuf);      if (!status)      {  | 
