From e19d4dedf548d6b16f95a97f6b67fd2a09a18643 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Sun, 25 Jul 2021 17:09:02 +0200 Subject: Implemented read receipts and deletion Signed-off-by: TheJackiMonster --- include/gnunet_chat_lib.h | 7 +- src/gnunet_chat_context.c | 8 ++- src/gnunet_chat_context.h | 1 + src/gnunet_chat_context_intern.c | 10 +++ src/gnunet_chat_handle_intern.c | 41 ++++++++++++ src/gnunet_chat_lib.c | 30 ++++++--- src/gnunet_chat_lib_intern.c | 45 +++++++++++++ src/gnunet_chat_message.c | 9 --- src/gnunet_chat_message.h | 3 - src/gnunet_chat_message_intern.c | 135 --------------------------------------- 10 files changed, 128 insertions(+), 161 deletions(-) delete mode 100644 src/gnunet_chat_message_intern.c diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h index 9734644..881938c 100644 --- a/include/gnunet_chat_lib.h +++ b/include/gnunet_chat_lib.h @@ -31,6 +31,7 @@ #include #include +#include #include /** @@ -184,8 +185,8 @@ typedef int * @return */ typedef int -(*GNUNET_CHAT_MessageReadReceiptCallback) (void *cls, struct GNUNET_CHAT_Message *message, - struct GNUNET_CHAT_Contact *contact, +(*GNUNET_CHAT_MessageReadReceiptCallback) (void *cls, const struct GNUNET_CHAT_Message *message, + const struct GNUNET_CHAT_Contact *contact, int read_receipt); /** @@ -373,7 +374,7 @@ GNUNET_CHAT_contact_set_user_pointer (struct GNUNET_CHAT_Contact *contact, * @return */ void* -GNUNET_CHAT_contact_get_user_pointer (struct GNUNET_CHAT_Contact *contact); +GNUNET_CHAT_contact_get_user_pointer (const struct GNUNET_CHAT_Contact *contact); /** * TODO diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c index 1124fd2..caca1f0 100644 --- a/src/gnunet_chat_context.c +++ b/src/gnunet_chat_context.c @@ -39,6 +39,7 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle, context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN; context->nick = NULL; + context->timestamps = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO); context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); context->invites = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); @@ -53,14 +54,19 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle, void context_destroy (struct GNUNET_CHAT_Context* context) { + GNUNET_CONTAINER_multishortmap_iterate( + context->timestamps, it_destroy_context_timestamps, NULL + ); + GNUNET_CONTAINER_multihashmap_iterate( context->messages, it_destroy_context_messages, NULL ); GNUNET_CONTAINER_multihashmap_iterate( - context->messages, it_destroy_context_invites, NULL + context->invites, it_destroy_context_invites, NULL ); + GNUNET_CONTAINER_multishortmap_destroy(context->timestamps); GNUNET_CONTAINER_multihashmap_destroy(context->messages); GNUNET_CONTAINER_multihashmap_destroy(context->invites); GNUNET_CONTAINER_multihashmap_destroy(context->files); diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h index 81e03c3..cb4528a 100644 --- a/src/gnunet_chat_context.h +++ b/src/gnunet_chat_context.h @@ -48,6 +48,7 @@ struct GNUNET_CHAT_Context enum GNUNET_CHAT_ContextType type; char *nick; + struct GNUNET_CONTAINER_MultiShortmap *timestamps; struct GNUNET_CONTAINER_MultiHashMap *messages; struct GNUNET_CONTAINER_MultiHashMap *invites; struct GNUNET_CONTAINER_MultiHashMap *files; diff --git a/src/gnunet_chat_context_intern.c b/src/gnunet_chat_context_intern.c index af35e60..1ae146e 100644 --- a/src/gnunet_chat_context_intern.c +++ b/src/gnunet_chat_context_intern.c @@ -27,6 +27,16 @@ #define GNUNET_UNUSED __attribute__ ((unused)) +int +it_destroy_context_timestamps (GNUNET_UNUSED void *cls, + GNUNET_UNUSED const struct GNUNET_ShortHashCode *key, + void *value) +{ + struct GNUNET_TIME_Absolute *time = value; + GNUNET_free(time); + return GNUNET_YES; +} + int it_destroy_context_messages (GNUNET_UNUSED void *cls, GNUNET_UNUSED const struct GNUNET_HashCode *key, diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c index ede1eb7..bcf0508 100644 --- a/src/gnunet_chat_handle_intern.c +++ b/src/gnunet_chat_handle_intern.c @@ -279,6 +279,37 @@ on_handle_message (void *cls, if (!context) return; + const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh( + msg->header.timestamp + ); + + struct GNUNET_ShortHashCode shorthash; + util_shorthash_from_member(sender, &shorthash); + + struct GNUNET_TIME_Absolute *time = GNUNET_CONTAINER_multishortmap_get( + context->timestamps, &shorthash + ); + + if (time) + { + time = GNUNET_new(struct GNUNET_TIME_Absolute); + *time = timestamp; + + if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put( + context->timestamps, &shorthash, time, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) + GNUNET_free(time); + } + else + { + struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference( + timestamp, *time + ); + + if (GNUNET_TIME_relative_get_zero_().rel_value_us == delta.rel_value_us) + *time = timestamp; + } + struct GNUNET_CHAT_Message *message = GNUNET_CONTAINER_multihashmap_get( context->messages, hash ); @@ -319,6 +350,16 @@ on_handle_message (void *cls, file_destroy(file); break; } + case GNUNET_MESSENGER_KIND_DELETE: + { + struct GNUNET_CHAT_Message *target = GNUNET_CONTAINER_multihashmap_get( + context->messages, &(msg->body.deletion.hash) + ); + + if (target) + target->msg = NULL; + break; + } default: break; } diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c index 8be813b..a835e48 100644 --- a/src/gnunet_chat_lib.c +++ b/src/gnunet_chat_lib.c @@ -306,7 +306,7 @@ GNUNET_CHAT_contact_set_user_pointer (struct GNUNET_CHAT_Contact *contact, void* -GNUNET_CHAT_contact_get_user_pointer (struct GNUNET_CHAT_Contact *contact) +GNUNET_CHAT_contact_get_user_pointer (const struct GNUNET_CHAT_Contact *contact) { if (!contact) return NULL; @@ -611,7 +611,7 @@ GNUNET_CHAT_context_iterate_messages (struct GNUNET_CHAT_Context *context, enum GNUNET_CHAT_MessageKind GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message) { - if (!message) + if ((!message) || (!(message->msg))) return GNUNET_CHAT_KIND_UNKNOWN; switch (message->msg->header.kind) @@ -641,7 +641,7 @@ GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message) struct GNUNET_TIME_Absolute GNUNET_CHAT_message_get_timestamp (const struct GNUNET_CHAT_Message *message) { - if (!message) + if ((!message) || (!(message->msg))) return GNUNET_TIME_absolute_get_zero_(); return GNUNET_TIME_absolute_ntoh(message->msg->header.timestamp); @@ -701,19 +701,29 @@ GNUNET_CHAT_message_get_read_receipt (const struct GNUNET_CHAT_Message *message, GNUNET_CHAT_MessageReadReceiptCallback callback, void *cls) { - if (!message) + if ((!message) || (!(message->msg))) return GNUNET_SYSERR; - // TODO: request read receipt? / check if newer message was received of sender? + struct GNUNET_CHAT_Context *context = message->context; - return GNUNET_SYSERR; + if (!context) + return GNUNET_SYSERR; + + struct GNUNET_CHAT_MessageIterateReadReceipts it; + it.message = message; + it.cb = callback; + it.cls = cls; + + return GNUNET_MESSENGER_iterate_members( + context->room, it_message_iterate_read_receipts, &it + ); } const char* GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message) { - if (!message) + if ((!message) || (!(message->msg))) return NULL; if (GNUNET_MESSENGER_KIND_TEXT != message->msg->header.kind) @@ -726,7 +736,7 @@ GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message) struct GNUNET_CHAT_File* GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message) { - if (!message) + if ((!message) || (!(message->msg))) return NULL; if (GNUNET_MESSENGER_KIND_FILE != message->msg->header.kind) @@ -742,7 +752,7 @@ GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message) struct GNUNET_CHAT_Invitation* GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message) { - if (!message) + if ((!message) || (!(message->msg))) return NULL; if (GNUNET_MESSENGER_KIND_INVITE != message->msg->header.kind) @@ -759,7 +769,7 @@ int GNUNET_CHAT_message_delete (const struct GNUNET_CHAT_Message *message, struct GNUNET_TIME_Relative delay) { - if (!message) + if ((!message) || (!(message->msg))) return GNUNET_SYSERR; struct GNUNET_MESSENGER_Message msg; diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c index 8ccfce5..584ebab 100644 --- a/src/gnunet_chat_lib_intern.c +++ b/src/gnunet_chat_lib_intern.c @@ -117,8 +117,53 @@ it_context_iterate_messages (void *cls, return it->cb(it->cls, it->context, message); } +struct GNUNET_CHAT_MessageIterateReadReceipts +{ + const struct GNUNET_CHAT_Message *message; + GNUNET_CHAT_MessageReadReceiptCallback cb; + void *cls; +}; + +int +it_message_iterate_read_receipts (void *cls, + GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room, + const struct GNUNET_MESSENGER_Contact *member) +{ + struct GNUNET_CHAT_MessageIterateReadReceipts *it = cls; + struct GNUNET_CHAT_Handle *handle = it->message->context->handle; + + if (!handle) + return GNUNET_NO; + + struct GNUNET_ShortHashCode shorthash; + util_shorthash_from_member(member, &shorthash); + struct GNUNET_CHAT_Contact *contact = GNUNET_CONTAINER_multishortmap_get( + handle->contacts, &shorthash + ); + + if (!contact) + return GNUNET_YES; + + struct GNUNET_TIME_Absolute *timestamp = GNUNET_CONTAINER_multishortmap_get( + it->message->context->timestamps, &shorthash + ); + if (!timestamp) + return GNUNET_YES; + struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference( + *timestamp, GNUNET_CHAT_message_get_timestamp(it->message) + ); + int read_receipt; + if (GNUNET_TIME_relative_get_zero_().rel_value_us == delta.rel_value_us) + read_receipt = GNUNET_YES; + else + read_receipt = GNUNET_NO; + if (it->cb) + it->cb(it->cls, it->message, contact, read_receipt); + + return GNUNET_YES; +} diff --git a/src/gnunet_chat_message.c b/src/gnunet_chat_message.c index 7e47291..b88edac 100644 --- a/src/gnunet_chat_message.c +++ b/src/gnunet_chat_message.c @@ -24,8 +24,6 @@ #include "gnunet_chat_message.h" -#include "gnunet_chat_message_intern.c" - struct GNUNET_CHAT_Message* message_create_from_msg (struct GNUNET_CHAT_Context *context, const struct GNUNET_HashCode *hash, @@ -39,20 +37,13 @@ message_create_from_msg (struct GNUNET_CHAT_Context *context, GNUNET_memcpy(&(message->hash), hash, sizeof(message->hash)); message->flags = flags; - message->head = NULL; - message->tail = NULL; - message->msg = msg; - link_message_parent(message); - return message; } void message_destroy (struct GNUNET_CHAT_Message* message) { - unlink_message_parent(message); - clear_message_children(message); GNUNET_free(message); } diff --git a/src/gnunet_chat_message.h b/src/gnunet_chat_message.h index ea5b355..4e2e504 100644 --- a/src/gnunet_chat_message.h +++ b/src/gnunet_chat_message.h @@ -48,9 +48,6 @@ struct GNUNET_CHAT_Message struct GNUNET_HashCode hash; enum GNUNET_MESSENGER_MessageFlags flags; - struct GNUNET_CHAT_MessageList *head; - struct GNUNET_CHAT_MessageList *tail; - const struct GNUNET_MESSENGER_Message *msg; }; diff --git a/src/gnunet_chat_message_intern.c b/src/gnunet_chat_message_intern.c deleted file mode 100644 index 97f3c18..0000000 --- a/src/gnunet_chat_message_intern.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2021 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 . - - SPDX-License-Identifier: AGPL3.0-or-later - */ -/* - * @author Tobias Frisch - * @file gnunet_chat_message_intern.c - */ - -#include - -#include "gnunet_chat_context.h" - -void -link_message_parent (struct GNUNET_CHAT_Message *message) -{ - struct GNUNET_CHAT_Context *context = message->context; - - struct GNUNET_CHAT_Message *prev = GNUNET_CONTAINER_multihashmap_get( - context->messages, &(message->msg->header.previous) - ); - - if (prev) - { - struct GNUNET_CHAT_MessageList *list = GNUNET_new( - struct GNUNET_CHAT_MessageList - ); - - list->message = message; - - GNUNET_CONTAINER_DLL_insert(prev->head, prev->tail, list); - } - - if (GNUNET_MESSENGER_KIND_MERGE != message->msg->header.kind) - return; - - prev = GNUNET_CONTAINER_multihashmap_get( - context->messages, &(message->msg->body.merge.previous) - ); - - if (prev) - { - struct GNUNET_CHAT_MessageList *list = GNUNET_new( - struct GNUNET_CHAT_MessageList - ); - - list->message = message; - - GNUNET_CONTAINER_DLL_insert(prev->head, prev->tail, list); - } -} - -void -unlink_message_parent (struct GNUNET_CHAT_Message *message) -{ - struct GNUNET_CHAT_Context *context = message->context; - - struct GNUNET_CHAT_Message *prev = GNUNET_CONTAINER_multihashmap_get( - context->messages, &(message->msg->header.previous) - ); - - if (prev) - { - struct GNUNET_CHAT_MessageList *list = prev->head; - - while (list) - { - if (list->message == message) - break; - - list = list->next; - } - - if (list) - { - GNUNET_CONTAINER_DLL_remove(prev->head, prev->tail, list); - GNUNET_free(list); - } - } - - if (GNUNET_MESSENGER_KIND_MERGE != message->msg->header.kind) - return; - - prev = GNUNET_CONTAINER_multihashmap_get( - context->messages, &(message->msg->body.merge.previous) - ); - - if (prev) - { - struct GNUNET_CHAT_MessageList *list = prev->head; - - while (list) - { - if (list->message == message) - break; - - list = list->next; - } - - if (list) - { - GNUNET_CONTAINER_DLL_remove(prev->head, prev->tail, list); - GNUNET_free(list); - } - } -} - -void -clear_message_children (struct GNUNET_CHAT_Message *message) -{ - struct GNUNET_CHAT_MessageList *list = message->tail; - - while (list) - { - GNUNET_CONTAINER_DLL_remove(message->head, message->tail, list); - GNUNET_free(list); - - list = message->tail; - } -} -- cgit v1.2.3