libgnunetchat

library for GNUnet Messenger
Log | Files | Refs | README | LICENSE

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:
Minclude/gnunet/gnunet_chat_lib.h | 21+++++++++++++++++++++
Msrc/gnunet_chat_context.c | 31+++++++++++++++++++++++++++++--
Msrc/gnunet_chat_context.h | 14+++++++++++++-
Msrc/gnunet_chat_context_intern.c | 11+++++++++--
Msrc/gnunet_chat_handle.c | 11+++++++++--
Msrc/gnunet_chat_handle.h | 3++-
Msrc/gnunet_chat_handle_intern.c | 31+++++++++++++++++++++++++++++++
Msrc/gnunet_chat_invitation.c | 28+++++++++++++++++++++++++++-
Msrc/gnunet_chat_invitation.h | 11+++++++++++
Asrc/gnunet_chat_invitation_intern.c | 36++++++++++++++++++++++++++++++++++++
Msrc/gnunet_chat_lib.c | 25+++++++++++++++++++++++++
Msrc/gnunet_chat_message.c | 2++
Msrc/gnunet_chat_message.h | 2++
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; }; /**