summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2024-02-26 01:57:48 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2024-02-26 01:57:48 +0100
commitf2119085a18cea2cb9aa5538b12b1c0ae9d0cb4c (patch)
tree3edf1af98852cd8648aa7102302ff67dc0a82fb6
parent3761097c25ff5c4a8dd660d77f83b98d62d0bda3 (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.c17
-rw-r--r--src/service/messenger/messenger_api_room.c162
-rw-r--r--src/service/messenger/messenger_api_room.h42
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.
*