From dd7e1c8d1776c2f6023f080836befb8c4e4fffa5 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Mon, 29 Jan 2024 20:19:38 +0100 Subject: MESSENGER: Implement linked deletion of transcript and private message Signed-off-by: TheJackiMonster --- src/include/gnunet_protocols.h | 16 ++-- src/service/messenger/gnunet-service-messenger.h | 37 +++----- src/service/messenger/messenger_api.c | 89 +++++++++++++------ src/service/messenger/messenger_api_room.c | 106 +++++++++++++++++++++++ src/service/messenger/messenger_api_room.h | 36 ++++++++ 5 files changed, 223 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 17aeff63f..42524d490 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2001--2020 GNUnet e.V. + Copyright (C) 2001--2024 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -3560,17 +3560,9 @@ extern "C" { #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE 1600 -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE 1601 +#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY 1601 -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY 1602 - -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME 1603 - -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME 1604 - -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY 1605 - -#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID 1606 +#define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID 1602 /************************************ Room *************************************/ @@ -3588,6 +3580,8 @@ extern "C" { #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SYNC 1617 +#define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_LINK 1618 + /*********************************************************************************/ /*********************************************************************************/ diff --git a/src/service/messenger/gnunet-service-messenger.h b/src/service/messenger/gnunet-service-messenger.h index c3e762734..4d629d2e1 100644 --- a/src/service/messenger/gnunet-service-messenger.h +++ b/src/service/messenger/gnunet-service-messenger.h @@ -27,6 +27,7 @@ #define GNUNET_SERVICE_MESSENGER_H #include "gnunet_util_lib.h" +#include /** * Message to create a handle for a client @@ -36,14 +37,6 @@ struct GNUNET_MESSENGER_CreateMessage struct GNUNET_MessageHeader header; }; -/** - * Message to update the handle (its public key) for a client - */ -struct GNUNET_MESSENGER_UpdateMessage -{ - struct GNUNET_MessageHeader header; -}; - /** * Message to destroy the handle for a client */ @@ -52,22 +45,6 @@ struct GNUNET_MESSENGER_DestroyMessage struct GNUNET_MessageHeader header; }; -/** - * Message to receive the current name of a handle - */ -struct GNUNET_MESSENGER_NameMessage -{ - struct GNUNET_MessageHeader header; -}; - -/** - * Message to receive the current public key of a handle - */ -struct GNUNET_MESSENGER_KeyMessage -{ - struct GNUNET_MessageHeader header; -}; - /** * General message to confirm interaction with a room */ @@ -127,4 +104,16 @@ struct GNUNET_MESSENGER_RecvMessage uint32_t flags; }; +/** + * Message to link something in a room + */ +struct GNUNET_MESSENGER_LinkMessage +{ + struct GNUNET_MessageHeader header; + + struct GNUNET_HashCode key; + struct GNUNET_HashCode hashes [2]; + uint32_t bidirectional; +}; + #endif //GNUNET_SERVICE_MESSENGER_H diff --git a/src/service/messenger/messenger_api.c b/src/service/messenger/messenger_api.c index e69309573..240a5e018 100644 --- a/src/service/messenger/messenger_api.c +++ b/src/service/messenger/messenger_api.c @@ -225,6 +225,12 @@ handle_member_id (void *cls, } +static void +delete_message_in_room (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay); + + static enum GNUNET_GenericReturnValue check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) @@ -285,6 +291,8 @@ handle_recv_message (void *cls, decode_message (&message, length, buffer, GNUNET_YES, NULL); struct GNUNET_MESSENGER_Message *private_message = NULL; + const struct GNUNET_MESSENGER_Message *handle_msg = &message; + if (GNUNET_MESSENGER_KIND_PRIVATE == message.header.kind) { private_message = copy_message (&message); @@ -351,8 +359,25 @@ handle_recv_message (void *cls, recipient = get_store_contact(store, context, recipient_key); skip_recipient: - contact = handle_room_message (room, contact, recipient, private_message ? - private_message : &message, hash, flags); + if (private_message) + handle_msg = private_message; + + if (GNUNET_MESSENGER_KIND_DELETE == handle_msg->header.kind) + { + struct GNUNET_TIME_Relative delay; + struct GNUNET_TIME_Absolute action; + + delay = GNUNET_TIME_relative_ntoh (handle_msg->body.deletion.delay); + + action = GNUNET_TIME_absolute_ntoh (handle_msg->header.timestamp); + action = GNUNET_TIME_absolute_add (action, delay); + + delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action); + + link_room_deletion (room, &(handle_msg->body.deletion.hash), delay, delete_message_in_room); + } + + contact = handle_room_message (room, contact, recipient, handle_msg, hash, flags); const struct GNUNET_MESSENGER_Message *stored_message = get_room_message ( room, hash); @@ -693,8 +718,8 @@ GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle) static void send_message_to_room (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Message *message, - struct GNUNET_MESSENGER_Message *transcript, - const struct GNUNET_CRYPTO_PrivateKey *key) + const struct GNUNET_CRYPTO_PrivateKey *key, + struct GNUNET_HashCode *hash) { const struct GNUNET_ShortHashCode *sender_id = get_room_sender_id (room); @@ -723,14 +748,10 @@ send_message_to_room (struct GNUNET_MESSENGER_Room *room, char *msg_buffer = ((char*) msg) + sizeof(*msg); encode_message (message, msg_length, msg_buffer, GNUNET_YES); - struct GNUNET_HashCode hash; - hash_message (message, msg_length, msg_buffer, &hash); - sign_message (message, msg_length, msg_buffer, &hash, key); - - if (transcript) - GNUNET_memcpy (&(transcript->body.transcript.hash), &hash, sizeof(hash)); + hash_message (message, msg_length, msg_buffer, hash); + sign_message (message, msg_length, msg_buffer, hash, key); - GNUNET_memcpy (&(room->last_message), &hash, sizeof(room->last_message)); + GNUNET_memcpy (&(room->last_message), hash, sizeof(room->last_message)); GNUNET_MQ_send (room->handle->mq, env); @@ -772,13 +793,14 @@ enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room, static enum GNUNET_GenericReturnValue dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room) { + if (GNUNET_YES != is_room_available (room)) + return room->queue.head ? GNUNET_NO : GNUNET_YES; + struct GNUNET_MESSENGER_Message *message = NULL; struct GNUNET_MESSENGER_Message *transcript = NULL; struct GNUNET_CRYPTO_PublicKey pubkey; struct GNUNET_CRYPTO_PrivateKey key; - - if (GNUNET_YES != is_room_available (room)) - return room->queue.head ? GNUNET_NO : GNUNET_YES; + struct GNUNET_HashCode hash, other; do { if (message) @@ -792,15 +814,21 @@ dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room) continue; } - send_message_to_room (room, message, transcript, &key); + send_message_to_room (room, message, &key, &hash); if (!transcript) continue; - GNUNET_CRYPTO_key_get_public(&key, &pubkey); + GNUNET_memcpy (&(transcript->body.transcript.hash), &hash, sizeof(hash)); + GNUNET_CRYPTO_key_get_public (&key, &pubkey); if (GNUNET_YES == encrypt_message(transcript, &pubkey)) - send_message_to_room (room, transcript, NULL, &key); + { + send_message_to_room (room, transcript, &key, &other); + + link_room_message(room, &hash, &other); + link_room_message(room, &other, &hash); + } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -1210,19 +1238,16 @@ GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, else public_key = NULL; - send_message_to_room_with_key (room, copy_message(message), public_key); + send_message_to_room_with_key (room, copy_message (message), public_key); } -void -GNUNET_MESSENGER_delete_message (struct GNUNET_MESSENGER_Room *room, - const struct GNUNET_HashCode *hash, - const struct GNUNET_TIME_Relative delay) +static void +delete_message_in_room (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay) { - if ((! room) || (! hash)) - return; - - struct GNUNET_MESSENGER_Message *message = create_message_delete(hash, delay); + struct GNUNET_MESSENGER_Message *message = create_message_delete (hash, delay); if (! message) { @@ -1235,6 +1260,18 @@ GNUNET_MESSENGER_delete_message (struct GNUNET_MESSENGER_Room *room, } +void +GNUNET_MESSENGER_delete_message (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay) +{ + if ((! room) || (! hash)) + return; + + delete_message_in_room (room, hash, delay); +} + + const struct GNUNET_MESSENGER_Message* GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) diff --git a/src/service/messenger/messenger_api_room.c b/src/service/messenger/messenger_api_room.c index e7de430ae..c66f0e594 100644 --- a/src/service/messenger/messenger_api_room.c +++ b/src/service/messenger/messenger_api_room.c @@ -25,6 +25,7 @@ #include "messenger_api_room.h" +#include "gnunet_time_lib.h" #include "messenger_api_handle.h" #include "messenger_api_message.h" @@ -52,6 +53,7 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); + room->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); init_queue_messages (&(room->queue)); @@ -73,6 +75,17 @@ iterate_destroy_message (void *cls, } +static enum GNUNET_GenericReturnValue +iterate_destroy_link (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_HashCode *hash = value; + GNUNET_free (hash); + return GNUNET_YES; +} + + void destroy_room (struct GNUNET_MESSENGER_Room *room) { @@ -92,6 +105,14 @@ destroy_room (struct GNUNET_MESSENGER_Room *room) if (room->members) GNUNET_CONTAINER_multishortmap_destroy (room->members); + if (room->links) + { + GNUNET_CONTAINER_multihashmap_iterate (room->links, + iterate_destroy_link, NULL); + + GNUNET_CONTAINER_multihashmap_destroy (room->links); + } + if (room->sender_id) GNUNET_free (room->sender_id); @@ -513,3 +534,88 @@ find_room_member (const struct GNUNET_MESSENGER_Room *room, return find.result; } + + +static enum GNUNET_GenericReturnValue +find_linked_hash (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + const struct GNUNET_HashCode **result = cls; + struct GNUNET_HashCode *hash = value; + + if (0 == GNUNET_CRYPTO_hash_cmp (hash, *result)) + { + *result = NULL; + return GNUNET_NO; + } + + return GNUNET_YES; +} + + +void +link_room_message (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_HashCode *other) +{ + GNUNET_assert ((room) && (hash) && (other)); + + const struct GNUNET_HashCode **result = &other; + GNUNET_CONTAINER_multihashmap_get_multiple (room->links, hash, + find_linked_hash, result); + + if (! *result) + return; + + struct GNUNET_HashCode *value = GNUNET_memdup(other, sizeof(struct GNUNET_HashCode)); + if (! value) + return; + + if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->links, hash, value, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)) + GNUNET_free (value); +} + + +struct GNUNET_MESSENGER_RoomLinkDeletionInfo +{ + struct GNUNET_MESSENGER_Room *room; + struct GNUNET_TIME_Relative delay; + GNUNET_MESSENGER_RoomLinkDeletion deletion; +}; + + +static enum GNUNET_GenericReturnValue +delete_linked_hash (void *cls, + const struct GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_MESSENGER_RoomLinkDeletionInfo *info = cls; + struct GNUNET_HashCode *hash = value; + + if (info->deletion) + info->deletion (info->room, hash, info->delay); + + GNUNET_free (hash); + return GNUNET_YES; +} + + +void +link_room_deletion (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay, + GNUNET_MESSENGER_RoomLinkDeletion deletion) +{ + GNUNET_assert ((room) && (hash)); + + struct GNUNET_MESSENGER_RoomLinkDeletionInfo info; + info.room = room; + info.delay = delay; + info.deletion = deletion; + + GNUNET_CONTAINER_multihashmap_get_multiple (room->links, hash, + delete_linked_hash, &info); + GNUNET_CONTAINER_multihashmap_remove_all (room->links, hash); +} diff --git a/src/service/messenger/messenger_api_room.h b/src/service/messenger/messenger_api_room.h index 855405337..79571bc2e 100644 --- a/src/service/messenger/messenger_api_room.h +++ b/src/service/messenger/messenger_api_room.h @@ -26,6 +26,8 @@ #ifndef GNUNET_MESSENGER_API_ROOM_H #define GNUNET_MESSENGER_API_ROOM_H +#include "gnunet_common.h" +#include "gnunet_time_lib.h" #include "gnunet_util_lib.h" #include "gnunet_messenger_service.h" @@ -58,10 +60,15 @@ struct GNUNET_MESSENGER_Room struct GNUNET_CONTAINER_MultiHashMap *messages; struct GNUNET_CONTAINER_MultiShortmap *members; + struct GNUNET_CONTAINER_MultiHashMap *links; struct GNUNET_MESSENGER_QueueMessages queue; }; +typedef void (*GNUNET_MESSENGER_RoomLinkDeletion) (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay); + /** * Creates and allocates a new room for a handle with a given key for the client API. * @@ -194,4 +201,33 @@ enum GNUNET_GenericReturnValue find_room_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact); +/** + * Links a message identified by its hash inside a given room with another + * message identified by its other hash. Linked messages will be deleted automatically, + * if any linked message to it gets deleted. + * + * @param[in,out] room Room + * @param[in] hash Hash of message + * @param[in] other Hash of other message + */ +void +link_room_message (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_HashCode *other); + +/** + * Delete all remaining links to a certain message identified by its hash inside a given + * room and cause a deletion process to all of the linked messages. + * + * @param[in,out] room Room + * @param[in] hash Hash of message + * @param[in] delay Delay for linked deletion + * @param[in] deletion Function called for each linked deletion + */ +void +link_room_deletion (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_HashCode *hash, + const struct GNUNET_TIME_Relative delay, + GNUNET_MESSENGER_RoomLinkDeletion deletion); + #endif //GNUNET_MESSENGER_API_ROOM_H -- cgit v1.2.3