commit 6894bec728babd86310b0a2a7a01f3ea906fd57c
parent ba41943e84b221a6c31edb16576f0086690ab7b9
Author: Jacki <jacki@thejackimonster.de>
Date: Fri, 4 Jul 2025 15:56:11 +0200
Update invitations on joining/leaving related chat rooms
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
13 files changed, 217 insertions(+), 9 deletions(-)
diff --git a/include/gnunet/gnunet_chat_lib.h b/include/gnunet/gnunet_chat_lib.h
@@ -1569,6 +1569,27 @@ const char*
GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message);
/**
+ * Sets a custom <i>user pointer</i> to a given <i>message</i> so it can
+ * be accessed in message related callbacks.
+ *
+ * @param[in,out] message Message
+ * @param[in] user_pointer Custom user pointer
+ */
+void
+GNUNET_CHAT_message_set_user_pointer (struct GNUNET_CHAT_Message *message,
+ void *user_pointer);
+
+/**
+ * Returns the custom user pointer of a given <i>message</i> or NULL if it
+ * was not set any.
+ *
+ * @param[in] message Message
+ * @return Custom user pointer
+ */
+void*
+GNUNET_CHAT_message_get_user_pointer (const struct GNUNET_CHAT_Message *message);
+
+/**
* Returns the account of a given <i>message</i> which is either
* its sender or target of the message depending on the kind of
* the message, otherwise it returns NULL.
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
@@ -160,7 +160,7 @@ context_destroy (struct GNUNET_CHAT_Context *context)
);
GNUNET_CONTAINER_multihashmap_iterate(
- context->invites, it_destroy_context_invites, NULL
+ context->invites, it_destroy_context_invites, context
);
GNUNET_CONTAINER_multishortmap_iterate(
@@ -212,6 +212,28 @@ context_request_message (struct GNUNET_CHAT_Context* context,
}
void
+context_update_message (struct GNUNET_CHAT_Context* context,
+ const struct GNUNET_HashCode *hash)
+{
+ GNUNET_assert((context) && (hash));
+
+ struct GNUNET_CHAT_Message *message = GNUNET_CONTAINER_multihashmap_get(
+ context->messages, hash);
+
+ if (!message)
+ return;
+
+ message->flags |= GNUNET_MESSENGER_FLAG_UPDATE;
+
+ struct GNUNET_CHAT_Handle *handle = context->handle;
+
+ if (!(handle->msg_cb))
+ return;
+
+ handle->msg_cb(handle->msg_cls, context, message);
+}
+
+void
context_update_room (struct GNUNET_CHAT_Context *context,
struct GNUNET_MESSENGER_Room *room,
enum GNUNET_GenericReturnValue record)
@@ -238,7 +260,7 @@ context_update_room (struct GNUNET_CHAT_Context *context,
);
GNUNET_CONTAINER_multihashmap_iterate(
- context->invites, it_destroy_context_invites, NULL
+ context->invites, it_destroy_context_invites, context
);
GNUNET_CONTAINER_multishortmap_iterate(
@@ -373,6 +395,8 @@ context_delete_message (struct GNUNET_CHAT_Context *context,
if (GNUNET_YES != message_has_msg(message))
return;
+ struct GNUNET_CHAT_Handle *handle = context->handle;
+
switch (message->msg->header.kind)
{
case GNUNET_MESSENGER_KIND_INVITE:
@@ -384,6 +408,9 @@ context_delete_message (struct GNUNET_CHAT_Context *context,
if (! invite)
break;
+ GNUNET_CONTAINER_multihashmap_remove(
+ handle->invitations, &(invite->key.hash), invite);
+
if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(
context->invites, &(message->hash), invite))
invitation_destroy(invite);
diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2025 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
@@ -40,6 +40,7 @@ struct GNUNET_CHAT_Context
{
struct GNUNET_CHAT_Handle *handle;
+ union GNUNET_MESSENGER_RoomKey key;
enum GNUNET_CHAT_ContextType type;
uint32_t flags;
char *nick;
@@ -111,6 +112,17 @@ context_request_message (struct GNUNET_CHAT_Context* context,
const struct GNUNET_HashCode *hash);
/**
+ * Updates a message with a given <i>hash</i> inside a
+ * given chat <i>context</i>.
+ *
+ * @param[in,out] context Chat context
+ * @param[in] hash Message hash
+ */
+void
+context_update_message (struct GNUNET_CHAT_Context* context,
+ const struct GNUNET_HashCode *hash);
+
+/**
* Updates the connected messenger <i>room</i> of a
* selected chat <i>context</i>.
*
diff --git a/src/gnunet_chat_context_intern.c b/src/gnunet_chat_context_intern.c
@@ -71,13 +71,20 @@ it_destroy_context_taggings (GNUNET_UNUSED void *cls,
}
enum GNUNET_GenericReturnValue
-it_destroy_context_invites (GNUNET_UNUSED void *cls,
+it_destroy_context_invites (void *cls,
GNUNET_UNUSED const struct GNUNET_HashCode *key,
void *value)
{
- GNUNET_assert(value);
+ GNUNET_assert((cls) && (value));
+ struct GNUNET_CHAT_Context *context = cls;
struct GNUNET_CHAT_Invitation *invitation = value;
+
+ struct GNUNET_CHAT_Handle *handle = context->handle;
+
+ GNUNET_CONTAINER_multihashmap_remove(
+ handle->invitations, &(invitation->key.hash), invitation);
+
invitation_destroy(invitation);
return GNUNET_YES;
}
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
@@ -32,6 +32,7 @@
#include <gnunet/gnunet_messenger_service.h>
#include <gnunet/gnunet_reclaim_service.h>
#include <gnunet/gnunet_scheduler_lib.h>
+#include <gnunet/gnunet_util_lib.h>
static const unsigned int initial_map_size_of_handle = 8;
static const unsigned int minimum_amount_of_other_members_in_group = 2;
@@ -118,6 +119,7 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
handle->contexts = NULL;
handle->contacts = NULL;
handle->groups = NULL;
+ handle->invitations = NULL;
handle->arm = GNUNET_ARM_connect(
handle->cfg,
@@ -334,9 +336,10 @@ handle_connect (struct GNUNET_CHAT_Handle *handle,
GNUNET_assert(
(handle) && (account) &&
(!(handle->current)) &&
- (!(handle->groups)) &&
- (!(handle->contacts)) &&
(!(handle->contexts)) &&
+ (!(handle->contacts)) &&
+ (!(handle->groups)) &&
+ (!(handle->invitations)) &&
(handle->files)
);
@@ -352,6 +355,8 @@ handle_connect (struct GNUNET_CHAT_Handle *handle,
initial_map_size_of_handle, GNUNET_NO);
handle->groups = GNUNET_CONTAINER_multihashmap_create(
initial_map_size_of_handle, GNUNET_NO);
+ handle->invitations = GNUNET_CONTAINER_multihashmap_create(
+ initial_map_size_of_handle, GNUNET_NO);
handle->gns = GNUNET_GNS_connect(handle->cfg);
@@ -487,6 +492,7 @@ handle_disconnect (struct GNUNET_CHAT_Handle *handle)
handle->own_contact = NULL;
+ GNUNET_CONTAINER_multihashmap_destroy(handle->invitations);
GNUNET_CONTAINER_multihashmap_destroy(handle->groups);
GNUNET_CONTAINER_multishortmap_destroy(handle->contacts);
GNUNET_CONTAINER_multihashmap_destroy(handle->contexts);
@@ -495,6 +501,7 @@ handle_disconnect (struct GNUNET_CHAT_Handle *handle)
handle->contexts = NULL;
handle->contacts = NULL;
handle->groups = NULL;
+ handle->invitations = NULL;
if (handle->connection)
GNUNET_SCHEDULER_cancel(handle->connection);
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
@@ -130,6 +130,7 @@ struct GNUNET_CHAT_Handle
struct GNUNET_CONTAINER_MultiHashMap *contexts;
struct GNUNET_CONTAINER_MultiShortmap *contacts;
struct GNUNET_CONTAINER_MultiHashMap *groups;
+ struct GNUNET_CONTAINER_MultiHashMap *invitations;
struct GNUNET_ARM_Handle *arm;
struct GNUNET_FS_Handle *fs;
@@ -287,7 +288,7 @@ handle_create_file_path (const struct GNUNET_CHAT_Handle *handle,
* using the same identifier as currently in use, replacing
* the old identity.
*
- * @param[in] handle Chat handle
+ * @param[in,out] handle Chat handle
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
enum GNUNET_GenericReturnValue
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
@@ -719,6 +719,19 @@ on_handle_internal_message_callback(void *cls)
handle->msg_cb(handle->msg_cls, context, internal->msg);
}
+static enum GNUNET_GenericReturnValue
+it_invitation_update (GNUNET_UNUSED void *cls,
+ GNUNET_UNUSED const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_CHAT_Invitation *invitation = (struct GNUNET_CHAT_Invitation*) value;
+
+ if (invitation)
+ invitation_update(invitation);
+
+ return GNUNET_YES;
+}
+
void
on_handle_message_callback(void *cls)
{
@@ -796,6 +809,10 @@ on_handle_message_callback(void *cls)
context->invites, &(message->hash), invitation,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
invitation_destroy(invitation);
+ else
+ GNUNET_CONTAINER_multihashmap_put(
+ handle->invitations, &(invitation->key.hash), invitation,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
break;
}
case GNUNET_MESSENGER_KIND_FILE:
@@ -880,12 +897,26 @@ skip_msg_handing:
contact_update_join(contact, context,
&(message->hash), message->flags);
+ GNUNET_CONTAINER_multihashmap_get_multiple(
+ handle->invitations,
+ GNUNET_MESSENGER_room_get_key(context->room),
+ it_invitation_update, handle);
+
if ((GNUNET_MESSENGER_FLAG_SENT & message->flags) &&
(GNUNET_MESSENGER_FLAG_RECENT & message->flags))
handle_send_room_name(handle, context->room);
break;
}
+ case GNUNET_MESSENGER_KIND_LEAVE:
+ {
+ GNUNET_CONTAINER_multihashmap_get_multiple(
+ handle->invitations,
+ GNUNET_MESSENGER_room_get_key(context->room),
+ it_invitation_update, handle);
+
+ break;
+ }
case GNUNET_MESSENGER_KIND_KEY:
{
contact_update_key(contact);
diff --git a/src/gnunet_chat_invitation.c b/src/gnunet_chat_invitation.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2025 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
@@ -23,7 +23,12 @@
*/
#include "gnunet_chat_invitation.h"
+
+#include "gnunet_chat_context.h"
#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_scheduler_lib.h>
+
+#include "gnunet_chat_invitation_intern.c"
struct GNUNET_CHAT_Invitation*
invitation_create_from_message (struct GNUNET_CHAT_Context *context,
@@ -35,6 +40,7 @@ invitation_create_from_message (struct GNUNET_CHAT_Context *context,
struct GNUNET_CHAT_Invitation *invitation = GNUNET_new(struct GNUNET_CHAT_Invitation);
invitation->context = context;
+ invitation->task = NULL;
GNUNET_memcpy(&(invitation->hash), hash, sizeof(invitation->hash));
@@ -44,12 +50,32 @@ invitation_create_from_message (struct GNUNET_CHAT_Context *context,
return invitation;
}
+
void
invitation_destroy (struct GNUNET_CHAT_Invitation *invitation)
{
GNUNET_assert(invitation);
+ if (invitation->task)
+ GNUNET_SCHEDULER_cancel(invitation->task);
+
GNUNET_PEER_decrement_rcs(&(invitation->door), 1);
GNUNET_free(invitation);
}
+
+
+void
+invitation_update (struct GNUNET_CHAT_Invitation *invitation)
+{
+ GNUNET_assert(invitation);
+
+ if (invitation->task)
+ return;
+
+ invitation->task = GNUNET_SCHEDULER_add_with_priority(
+ GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
+ cb_invitation_update,
+ invitation
+ );
+}
diff --git a/src/gnunet_chat_invitation.h b/src/gnunet_chat_invitation.h
@@ -26,6 +26,7 @@
#define GNUNET_CHAT_INVITATION_H_
#include <gnunet/gnunet_messenger_service.h>
+#include <gnunet/gnunet_scheduler_lib.h>
#include <gnunet/gnunet_util_lib.h>
struct GNUNET_CHAT_Context;
@@ -33,6 +34,7 @@ struct GNUNET_CHAT_Context;
struct GNUNET_CHAT_Invitation
{
struct GNUNET_CHAT_Context *context;
+ struct GNUNET_SCHEDULER_Task *task;
struct GNUNET_HashCode hash;
@@ -61,4 +63,13 @@ invitation_create_from_message (struct GNUNET_CHAT_Context *context,
void
invitation_destroy (struct GNUNET_CHAT_Invitation *invitation);
+/**
+ * Updates a chat <i>invitation</i> for applications to
+ * notice any status changes.
+ *
+ * @param[in,out] invitation Chat invitation
+ */
+void
+invitation_update (struct GNUNET_CHAT_Invitation *invitation);
+
#endif /* GNUNET_CHAT_INVITATION_H_ */
diff --git a/src/gnunet_chat_invitation_intern.c b/src/gnunet_chat_invitation_intern.c
@@ -0,0 +1,36 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2025 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
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file gnunet_chat_invitation_intern.c
+ */
+
+#include "gnunet_chat_context.h"
+#include "gnunet_chat_invitation.h"
+
+void
+cb_invitation_update (void *cls)
+{
+ struct GNUNET_CHAT_Invitation *invitation = cls;
+
+ invitation->task = NULL;
+
+ context_update_message (invitation->context, &(invitation->hash));
+}
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
@@ -2347,6 +2347,31 @@ GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message)
}
+void
+GNUNET_CHAT_message_set_user_pointer (struct GNUNET_CHAT_Message *message,
+ void *user_pointer)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if (!message)
+ return;
+
+ message->user_pointer = user_pointer;
+}
+
+
+void*
+GNUNET_CHAT_message_get_user_pointer (const struct GNUNET_CHAT_Message *message)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if (!message)
+ return NULL;
+
+ return message->user_pointer;
+}
+
+
struct GNUNET_CHAT_Account*
GNUNET_CHAT_message_get_account (const struct GNUNET_CHAT_Message *message)
{
diff --git a/src/gnunet_chat_message.c b/src/gnunet_chat_message.c
@@ -46,6 +46,7 @@ message_create_from_msg (struct GNUNET_CHAT_Context *context,
message->flag = GNUNET_CHAT_FLAG_NONE;
message->msg = msg;
+ message->user_pointer = NULL;
return message;
}
@@ -67,6 +68,7 @@ message_create_internally (struct GNUNET_CHAT_Account *account,
message->flag = flag;
message->warning = warning;
+ message->user_pointer = NULL;
return message;
}
diff --git a/src/gnunet_chat_message.h b/src/gnunet_chat_message.h
@@ -71,6 +71,8 @@ struct GNUNET_CHAT_Message
struct GNUNET_HashCode hash;
enum GNUNET_MESSENGER_MessageFlags flags;
enum GNUNET_CHAT_MessageFlag flag;
+
+ void *user_pointer;
};
/**