summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-11-14 20:58:40 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-11-14 20:58:40 (GMT)
commit73f5d359d6a0cc15ce463aa4b5595bd7112dec45 (patch)
tree466762ac1e85b7292046c4db5e8ccc3da0fc54fd /src/analysis
parent55faf115708f8448c1dbbb1798ac115e8021e45f (diff)
Prevent usage of removed clients.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/db/cdb.c228
1 files changed, 187 insertions, 41 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 08410c4..c5d3af7 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -59,7 +59,7 @@
-/* ------------------------- COEUR DE LA GESTION D'ARCHIVES ------------------------- */
+/* -------------------------- LIEN VERS UN CLIENT CONNECTE -------------------------- */
/* Informations relatives à un client */
@@ -69,11 +69,28 @@ typedef struct _cdb_client
char *peer_name; /* Désignation du correspondant*/
char *user; /* Utilisateur à l'autre bout */
- uint64_t last_time; /* Date de dernier envoi */
+ gint ref_count; /* Décompte d'utilisation */
} cdb_client;
+/* Met en place le suivi d'une connexion de client. */
+static cdb_client *create_cdb_client(SSL *, const char *, const char *);
+
+/* Supprime le suivi d'une connexion de client. */
+static void delete_cdb_client(cdb_client *);
+
+/* Augmente le décompte d'utilisation d'un suivi de connexion. */
+static void ref_cdb_client(cdb_client *);
+
+/* Diminue le décompte d'utilisation d'un suivi de connexion. */
+static void unref_cdb_client(cdb_client *);
+
+
+
+/* ------------------------- COEUR DE LA GESTION D'ARCHIVES ------------------------- */
+
+
/* Description d'une archive d'éléments utilisateur (instance) */
struct _GCdbArchive
{
@@ -92,7 +109,7 @@ struct _GCdbArchive
GDbSnapshot *snapshot; /* Instantanés de bases SQL */
sqlite3 *db; /* Base de données à manipuler */
- cdb_client *clients; /* Connexions en place */
+ cdb_client **clients; /* Connexions en place */
size_t count; /* Quantité de clients */
GMutex clients_access; /* Verrou pour l'accès */
@@ -180,6 +197,107 @@ static bool g_cdb_archive_set_content(GCdbArchive *, packed_buffer_t *, packed_b
+/* -------------------------- LIEN VERS UN CLIENT CONNECTE -------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : fd = canal de communication réseau ouvert. *
+* peer_name = désignation de la connexion. *
+* user = désignation de l'utilisateur de la connexion. *
+* *
+* Description : Met en place le suivi d'une connexion de client. *
+* *
+* Retour : Structure dédiée construite. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static cdb_client *create_cdb_client(SSL *fd, const char *peer_name, const char *user)
+{
+ cdb_client *result; /* Fiche d'entité à retourner */
+
+ result = malloc(sizeof(cdb_client *));
+
+ result->tls_fd = fd;
+
+ result->peer_name = strdup(peer_name);
+ result->user = strdup(user);
+
+ g_atomic_int_set(&result->ref_count, 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = informations de suivi à libérer de la mémoire. *
+* *
+* Description : Supprime le suivi d'une connexion de client. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_cdb_client(cdb_client *client)
+{
+ assert(g_atomic_int_get(&client->ref_count) == 0);
+
+ SSL_free(client->tls_fd);
+
+ free(client->peer_name);
+ free(client->user);
+
+ free(client);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = informations de suivi à libérer de la mémoire. *
+* *
+* Description : Augmente le décompte d'utilisation d'un suivi de connexion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void ref_cdb_client(cdb_client *client)
+{
+ g_atomic_int_inc(&client->ref_count);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = informations de suivi à libérer de la mémoire. *
+* *
+* Description : Diminue le décompte d'utilisation d'un suivi de connexion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void unref_cdb_client(cdb_client *client)
+{
+ if (g_atomic_int_dec_and_test(&client->ref_count))
+ delete_cdb_client(client);
+
+}
+
+
+
/* ---------------------------------------------------------------------------------- */
/* COEUR DE LA GESTION D'ARCHIVES */
/* ---------------------------------------------------------------------------------- */
@@ -246,6 +364,7 @@ static void g_cdb_archive_init(GCdbArchive *archive)
archive->collections = create_collections_list();
archive->snapshot = NULL;
+ archive->db = NULL;
g_mutex_init(&archive->clients_access);
@@ -882,7 +1001,7 @@ static void on_collection_extended(GDbCollection *collec, GDbItem *item, GCdbArc
for (i = 0; i < archive->count && status; i++)
{
- status = ssl_send_packed_buffer(&pbuf, archive->clients[i].tls_fd);
+ status = ssl_send_packed_buffer(&pbuf, archive->clients[i]->tls_fd);
if (!status)
LOG_ERROR(LMT_ERROR, _("Failed to send some DB update"));
@@ -911,6 +1030,8 @@ static void on_collection_extended(GDbCollection *collec, GDbItem *item, GCdbArc
static void *g_cdb_archive_process(GCdbArchive *archive)
{
GServerBackend *base; /* Base de l'instance */
+ cdb_client **clients; /* Clients surveillés */
+ size_t last_count; /* Quantité de ces clients */
struct pollfd *fds; /* Surveillance des flux */
nfds_t nfds; /* Quantité de ces flux */
nfds_t i; /* Boucle de parcours */
@@ -927,20 +1048,38 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
base = G_SERVER_BACKEND(archive);
+ clients = NULL;
+ last_count = 0;
+
fds = NULL;
while (1)
{
+ /* Réinitialisation ? */
+
+ for (i = 0; i < last_count; i++)
+ unref_cdb_client(clients[i]);
+
/* Reconstitution d'une liste à jour */
g_mutex_lock(&archive->clients_access);
- nfds = archive->count + 2;
+ last_count = archive->count;
+
+ clients = realloc(clients, last_count * sizeof(cdb_client));
+
+ for (i = 0; i < last_count; i++)
+ {
+ clients[i] = archive->clients[i];
+ ref_cdb_client(clients[i]);
+ }
+
+ nfds = last_count + 2;
fds = realloc(fds, nfds * sizeof(struct pollfd));
for (i = 0; i < (nfds - 2); i++)
{
- fds[i].fd = SSL_get_fd(archive->clients[i].tls_fd);
+ fds[i].fd = SSL_get_fd(clients[i]->tls_fd);
fds[i].events = POLLIN | POLLPRI;
}
@@ -993,7 +1132,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
{
init_packed_buffer(&in_pbuf);
- status = ssl_recv_packed_buffer(&in_pbuf, archive->clients[i].tls_fd);
+ status = ssl_recv_packed_buffer(&in_pbuf, clients[i]->tls_fd);
if (!status) goto gcap_bad_exchange;
next_command:
@@ -1003,17 +1142,12 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
command = tmp32;
+ init_packed_buffer(&out_pbuf);
+
switch (command)
{
case DBC_SET_CONTENT:
-
status = g_cdb_archive_set_content(archive, &in_pbuf, &out_pbuf);
- if (!status) goto gcap_bad_reply;
-
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
- if (!status) goto gcap_bad_reply;
-
- exit_packed_buffer(&out_pbuf);
break;
@@ -1022,7 +1156,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
error = g_cdb_archive_write(archive);
- init_packed_buffer(&out_pbuf);
+ //init_packed_buffer(&out_pbuf);
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SAVE },
sizeof(uint32_t), true);
@@ -1031,7 +1165,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
status = extend_packed_buffer(&out_pbuf, (uint32_t []) { error }, sizeof(uint32_t), true);
if (!status) goto gcap_bad_reply;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1072,10 +1206,10 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
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].tls_fd);
- if (!status) goto gcap_bad_reply;
+ //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
+ //if (!status) goto gcap_bad_reply;
- exit_packed_buffer(&out_pbuf);
+ //exit_packed_buffer(&out_pbuf);
break;
@@ -1094,7 +1228,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
&in_pbuf, &out_pbuf, archive->db);
if (!status) goto gcap_bad_reply;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
+ status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
if (!status) goto gcap_bad_reply;
exit_packed_buffer(&out_pbuf);
@@ -1106,10 +1240,12 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
if (!g_cdb_archive_send_snapshot_update(archive, &out_pbuf))
goto critical_error;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
- if (!status) goto gcap_bad_reply;
+ status = true;
- exit_packed_buffer(&out_pbuf);
+ //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
+ //if (!status) goto gcap_bad_reply;
+
+ //exit_packed_buffer(&out_pbuf);
break;
@@ -1118,10 +1254,10 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
if (!g_cdb_archive_send_snapshot_change(archive, &out_pbuf))
goto critical_error;
- status = ssl_send_packed_buffer(&out_pbuf, archive->clients[i].tls_fd);
- if (!status) goto gcap_bad_reply;
+ //status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
+ //if (!status) goto gcap_bad_reply;
- exit_packed_buffer(&out_pbuf);
+ //exit_packed_buffer(&out_pbuf);
break;
@@ -1240,6 +1376,17 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
}
+ if (!status)
+ goto gcap_bad_reply;
+
+ if (get_packed_buffer_payload_length(&out_pbuf) > 0)
+ {
+ status = ssl_send_packed_buffer(&out_pbuf, clients[i]->tls_fd);
+ if (!status) goto gcap_bad_reply;
+ }
+
+ exit_packed_buffer(&out_pbuf);
+
if (has_more_data_in_packed_buffer(&in_pbuf))
goto next_command;
@@ -1283,6 +1430,12 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
g_server_backend_stop(G_SERVER_BACKEND(archive));
+ for (i = 0; i < last_count; i++)
+ unref_cdb_client(clients[i]);
+
+ if (clients != NULL)
+ free(clients);
+
if (fds != NULL)
free(fds);
@@ -1328,15 +1481,13 @@ static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char *
* g_cdb_archive_process() depuis un autre flot d'exécution.
*/
- g_mutex_lock(&archive->clients_access);
+ client = create_cdb_client(fd, peer_name, user);
- archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client));
+ g_mutex_lock(&archive->clients_access);
- client = &archive->clients[archive->count - 1];
+ archive->clients = realloc(archive->clients, ++archive->count * sizeof(cdb_client *));
- client->tls_fd = fd;
- client->peer_name = strdup(peer_name);
- client->user = strdup(user);
+ archive->clients[archive->count - 1] = client;
g_mutex_unlock(&archive->clients_access);
@@ -1358,20 +1509,15 @@ static void g_cdb_archive_add_client(GCdbArchive *archive, SSL *fd, const char *
static void _g_cdb_archive_remove_client(GCdbArchive *archive, size_t index)
{
- cdb_client *client; /* Client à traiter */
-
assert(!g_mutex_trylock(&archive->clients_access));
- client = &archive->clients[index];
-
- SSL_free(client->tls_fd);
- free(client->user);
+ unref_cdb_client(archive->clients[index]);
if ((index + 1) < archive->count)
memmove(&archive->clients[index], &archive->clients[index + 1],
- (archive->count - index - 1) * sizeof(cdb_client));
+ (archive->count - index - 1) * sizeof(cdb_client *));
- archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client));
+ archive->clients = realloc(archive->clients, --archive->count * sizeof(cdb_client *));
}
@@ -1422,7 +1568,7 @@ static void g_cdb_archive_send_reply_to_all_clients(GCdbArchive *archive, packed
for (i = 0; i < archive->count; i++)
{
- status = ssl_send_packed_buffer(pbuf, archive->clients[i].tls_fd);
+ status = ssl_send_packed_buffer(pbuf, archive->clients[i]->tls_fd);
if (!status)
{
log_variadic_message(LMT_ERROR, _("Error while replying to client %zu"), i);