diff options
author | TheJackiMonster <thejackimonster@gmail.com> | 2024-02-26 01:57:48 +0100 |
---|---|---|
committer | TheJackiMonster <thejackimonster@gmail.com> | 2024-02-26 01:57:48 +0100 |
commit | f2119085a18cea2cb9aa5538b12b1c0ae9d0cb4c (patch) | |
tree | 3edf1af98852cd8648aa7102302ff67dc0a82fb6 | |
parent | 3761097c25ff5c4a8dd660d77f83b98d62d0bda3 (diff) |
MESSENGER: Delay message handling in client API when sender is not a valid contact yetdev/thejackimonster/messenger
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r-- | src/service/messenger/messenger_api.c | 17 | ||||
-rw-r--r-- | src/service/messenger/messenger_api_room.c | 162 | ||||
-rw-r--r-- | src/service/messenger/messenger_api_room.h | 42 |
3 files changed, 215 insertions, 6 deletions
diff --git a/src/service/messenger/messenger_api.c b/src/service/messenger/messenger_api.c index 8afb9e42e..fa3896f4e 100644 --- a/src/service/messenger/messenger_api.c +++ b/src/service/messenger/messenger_api.c @@ -304,8 +304,23 @@ handle_recv_message (void *cls, struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw ( store, context, sender); + + if ((! contact) && (GNUNET_YES != is_peer_message (&message)) && + (GNUNET_MESSENGER_KIND_JOIN != message.header.kind)) + { + delay_room_message (room, &message, sender, context, hash, flags); + goto skip_message; + } - handle_room_message (room, contact, &message, hash, flags); + if (GNUNET_YES != handle_room_message (room, contact, &message, + hash, flags)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Handling of message failed: %s (%s)\n", + GNUNET_MESSENGER_name_of_kind (message.header.kind), + GNUNET_h2s (hash)); + + goto skip_message; + } if (flags & GNUNET_MESSENGER_FLAG_RECENT) update_room_last_message (room, hash); diff --git a/src/service/messenger/messenger_api_room.c b/src/service/messenger/messenger_api_room.c index 715934f1c..3b61e739e 100644 --- a/src/service/messenger/messenger_api_room.c +++ b/src/service/messenger/messenger_api_room.c @@ -27,6 +27,8 @@ #include "gnunet_common.h" #include "gnunet_messenger_service.h" +#include "gnunet_scheduler_lib.h" +#include "messenger_api_contact.h" #include "messenger_api_contact_store.h" #include "messenger_api_handle.h" #include "messenger_api_message.h" @@ -58,6 +60,11 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); room->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); + room->recv_head = NULL; + room->recv_tail = NULL; + + room->recv_task = NULL; + init_queue_messages (&(room->queue)); return room; @@ -95,6 +102,22 @@ destroy_room (struct GNUNET_MESSENGER_Room *room) GNUNET_assert (room); clear_queue_messages (&(room->queue)); + + if (room->recv_task) + GNUNET_SCHEDULER_cancel (room->recv_task); + + struct GNUNET_MESSENGER_RoomRecvList *recv; + while (room->recv_head) + { + recv = room->recv_head; + + if (recv->message) + destroy_message (recv->message); + + GNUNET_CONTAINER_DLL_remove (room->recv_head, room->recv_tail, recv); + GNUNET_free (recv); + } + clear_list_tunnels (&(room->entries)); if (room->messages) @@ -147,6 +170,10 @@ get_room_sender_id (const struct GNUNET_MESSENGER_Room *room) } +static void +check_room_for_delayed_messages (struct GNUNET_MESSENGER_Room *room); + + void set_room_sender_id (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id) @@ -169,6 +196,7 @@ set_room_sender_id (struct GNUNET_MESSENGER_Room *room, room->sender_id = GNUNET_new (struct GNUNET_ShortHashCode); GNUNET_memcpy (room->sender_id, id, sizeof(struct GNUNET_ShortHashCode)); + check_room_for_delayed_messages (room); } @@ -287,6 +315,8 @@ handle_join_message (struct GNUNET_MESSENGER_Room *room, entry->sender, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))) increase_contact_rc (entry->sender); + + check_room_for_delayed_messages (room); } @@ -629,7 +659,7 @@ handle_message (struct GNUNET_MESSENGER_Room *room, } -void +enum GNUNET_GenericReturnValue handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, @@ -647,7 +677,7 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room, entry = GNUNET_new (struct GNUNET_MESSENGER_RoomMessageEntry); if (! entry) - return; + return GNUNET_NO; entry->sender = NULL; entry->recipient = NULL; @@ -661,7 +691,7 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { GNUNET_free (entry); - return; + return GNUNET_NO; } update_entry: @@ -679,8 +709,132 @@ update_entry: entry->message = copy_message (message); entry->completed = GNUNET_YES; - handle_message (room, hash, entry); + + if ((GNUNET_YES != is_peer_message (message)) && (! (entry->sender)) && + (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, hash, entry))) + { + destroy_message (entry->message); + GNUNET_free (entry); + return GNUNET_SYSERR; + } + + return GNUNET_YES; +} + + +static void +handle_room_delayed_messages (void *cls) +{ + struct GNUNET_MESSENGER_Room *room = cls; + + GNUNET_assert (room); + + room->recv_task = NULL; + + struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store ( + room->handle); + + const struct GNUNET_MESSENGER_RoomRecvList *tail = room->recv_tail; + + struct GNUNET_MESSENGER_RoomRecvList *recv = room->recv_head; + while (recv) + { + struct GNUNET_MESSENGER_RoomRecvList *next = recv->next; + struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw ( + store, &(recv->context), &(recv->sender)); + + if (! contact) + goto skip_received; + + if (GNUNET_YES != handle_room_message (room, contact, recv->message, + &(recv->hash), recv->flags)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delayed handling of message failed: %s (%s)\n", + GNUNET_MESSENGER_name_of_kind (recv->message->header.kind), + GNUNET_h2s (&(recv->hash))); + + goto drop_received; + } + + if (recv->flags & GNUNET_MESSENGER_FLAG_RECENT) + update_room_last_message (room, &(recv->hash)); + + callback_room_message (room, &(recv->hash)); + + drop_received: + if (recv->message) + destroy_message (recv->message); + + GNUNET_CONTAINER_DLL_remove (room->recv_head, room->recv_tail, recv); + GNUNET_free (recv); + + skip_received: + if (recv == tail) + break; + + recv = next; + } +} + + +static void +check_room_for_delayed_messages (struct GNUNET_MESSENGER_Room *room) +{ + GNUNET_assert (room); + + const struct GNUNET_ShortHashCode *sender_id = get_room_sender_id(room); + + if ((! (room->recv_head)) || (room->recv_task) || (! sender_id)) + return; + + struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store ( + room->handle); + + struct GNUNET_HashCode context; + get_context_from_member (&(room->key), sender_id, &context); + + struct GNUNET_MESSENGER_Contact *contact; + contact = get_store_contact (store, &context, get_handle_pubkey(room->handle)); + + if (GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value (room->members, sender_id, + contact)) + return; + + room->recv_task = GNUNET_SCHEDULER_add_with_priority(GNUNET_SCHEDULER_PRIORITY_IDLE, + handle_room_delayed_messages, + room); +} + + +void +delay_room_message (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_MESSENGER_Message *message, + const struct GNUNET_HashCode *sender, + const struct GNUNET_HashCode *context, + const struct GNUNET_HashCode *hash, + enum GNUNET_MESSENGER_MessageFlags flags) +{ + GNUNET_assert ((room) && (message) && (sender) && (context) && (hash)); + + struct GNUNET_MESSENGER_RoomRecvList *recv = GNUNET_new (struct GNUNET_MESSENGER_RoomRecvList); + + if (! recv) + return; + + recv->message = copy_message (message); + + GNUNET_memcpy (&(recv->sender), sender, sizeof (*sender)); + GNUNET_memcpy (&(recv->context), context, sizeof (*context)); + GNUNET_memcpy (&(recv->hash), hash, sizeof (*hash)); + + recv->flags = flags; + recv->prev = NULL; + recv->next = NULL; + + GNUNET_CONTAINER_DLL_insert_tail (room->recv_head, room->recv_tail, recv); + + check_room_for_delayed_messages (room); } diff --git a/src/service/messenger/messenger_api_room.h b/src/service/messenger/messenger_api_room.h index 4a7f6d6a2..420367b7c 100644 --- a/src/service/messenger/messenger_api_room.h +++ b/src/service/messenger/messenger_api_room.h @@ -46,6 +46,19 @@ struct GNUNET_MESSENGER_RoomMessageEntry enum GNUNET_GenericReturnValue completed; }; +struct GNUNET_MESSENGER_RoomRecvList +{ + struct GNUNET_MESSENGER_Message *message; + + struct GNUNET_HashCode sender; + struct GNUNET_HashCode context; + struct GNUNET_HashCode hash; + enum GNUNET_MESSENGER_MessageFlags flags; + + struct GNUNET_MESSENGER_RoomRecvList *prev; + struct GNUNET_MESSENGER_RoomRecvList *next; +}; + struct GNUNET_MESSENGER_Room { struct GNUNET_MESSENGER_Handle *handle; @@ -65,6 +78,11 @@ struct GNUNET_MESSENGER_Room struct GNUNET_CONTAINER_MultiShortmap *members; struct GNUNET_CONTAINER_MultiHashMap *links; + struct GNUNET_MESSENGER_RoomRecvList *recv_head; + struct GNUNET_MESSENGER_RoomRecvList *recv_tail; + + struct GNUNET_SCHEDULER_Task *recv_task; + struct GNUNET_MESSENGER_QueueMessages queue; }; @@ -180,8 +198,10 @@ callback_room_message (struct GNUNET_MESSENGER_Room *room, * @param[in] message Message * @param[in] hash Hash of message * @param[in] flags Flags of message + * @return #GNUNET_YES if the handling was successfull, otherwise #GNUNET_NO + * or #GNUNET_SYSERR on failure */ -void +enum GNUNET_GenericReturnValue handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, @@ -189,6 +209,26 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room, enum GNUNET_MESSENGER_MessageFlags flags); /** + * Delays handling of a received message for a <i>room</i> in the client API. For that all received + * information from the service like the <i>message</i> and hashes regarding <i>sender</i>, <i>context</i> + * and message <i>hash</i> as well as the message <i>flags</i> will be stored. + * + * @param[in,out] room Room + * @param[in] message Message + * @param[in] sender Hash of sender + * @param[in] context Hash of context + * @param[in] hash Hash of message + * @param[in] flags Flags of message + */ +void +delay_room_message (struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_MESSENGER_Message *message, + const struct GNUNET_HashCode *sender, + const struct GNUNET_HashCode *context, + const struct GNUNET_HashCode *hash, + enum GNUNET_MESSENGER_MessageFlags flags); + +/** * Updates the last message <i>hash</i> of a <i>room</i> for the client API so that new messages can * point to the latest message hash while sending. * |