aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2021-07-25 17:09:02 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2021-07-25 17:09:02 +0200
commite19d4dedf548d6b16f95a97f6b67fd2a09a18643 (patch)
treea49986fa2a5c0e787e8a84649e4436f742f6affe
parente068078b3ae07d67e9d4b75574075773a88c4a3d (diff)
downloadlibgnunetchat-e19d4dedf548d6b16f95a97f6b67fd2a09a18643.tar.gz
libgnunetchat-e19d4dedf548d6b16f95a97f6b67fd2a09a18643.zip
Implemented read receipts and deletion
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--include/gnunet_chat_lib.h7
-rw-r--r--src/gnunet_chat_context.c8
-rw-r--r--src/gnunet_chat_context.h1
-rw-r--r--src/gnunet_chat_context_intern.c10
-rw-r--r--src/gnunet_chat_handle_intern.c41
-rw-r--r--src/gnunet_chat_lib.c30
-rw-r--r--src/gnunet_chat_lib_intern.c45
-rw-r--r--src/gnunet_chat_message.c9
-rw-r--r--src/gnunet_chat_message.h3
-rw-r--r--src/gnunet_chat_message_intern.c135
10 files changed, 128 insertions, 161 deletions
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 @@
31 31
32#include <gnunet/platform.h> 32#include <gnunet/platform.h>
33#include <gnunet/gnunet_common.h> 33#include <gnunet/gnunet_common.h>
34#include <gnunet/gnunet_time_lib.h>
34#include <gnunet/gnunet_util_lib.h> 35#include <gnunet/gnunet_util_lib.h>
35 36
36/** 37/**
@@ -184,8 +185,8 @@ typedef int
184 * @return 185 * @return
185 */ 186 */
186typedef int 187typedef int
187(*GNUNET_CHAT_MessageReadReceiptCallback) (void *cls, struct GNUNET_CHAT_Message *message, 188(*GNUNET_CHAT_MessageReadReceiptCallback) (void *cls, const struct GNUNET_CHAT_Message *message,
188 struct GNUNET_CHAT_Contact *contact, 189 const struct GNUNET_CHAT_Contact *contact,
189 int read_receipt); 190 int read_receipt);
190 191
191/** 192/**
@@ -373,7 +374,7 @@ GNUNET_CHAT_contact_set_user_pointer (struct GNUNET_CHAT_Contact *contact,
373 * @return 374 * @return
374 */ 375 */
375void* 376void*
376GNUNET_CHAT_contact_get_user_pointer (struct GNUNET_CHAT_Contact *contact); 377GNUNET_CHAT_contact_get_user_pointer (const struct GNUNET_CHAT_Contact *contact);
377 378
378/** 379/**
379 * TODO 380 * 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,
39 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN; 39 context->type = GNUNET_CHAT_CONTEXT_TYPE_UNKNOWN;
40 context->nick = NULL; 40 context->nick = NULL;
41 41
42 context->timestamps = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
42 context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 43 context->messages = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
43 context->invites = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 44 context->invites = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
44 context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); 45 context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
@@ -53,14 +54,19 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle,
53void 54void
54context_destroy (struct GNUNET_CHAT_Context* context) 55context_destroy (struct GNUNET_CHAT_Context* context)
55{ 56{
57 GNUNET_CONTAINER_multishortmap_iterate(
58 context->timestamps, it_destroy_context_timestamps, NULL
59 );
60
56 GNUNET_CONTAINER_multihashmap_iterate( 61 GNUNET_CONTAINER_multihashmap_iterate(
57 context->messages, it_destroy_context_messages, NULL 62 context->messages, it_destroy_context_messages, NULL
58 ); 63 );
59 64
60 GNUNET_CONTAINER_multihashmap_iterate( 65 GNUNET_CONTAINER_multihashmap_iterate(
61 context->messages, it_destroy_context_invites, NULL 66 context->invites, it_destroy_context_invites, NULL
62 ); 67 );
63 68
69 GNUNET_CONTAINER_multishortmap_destroy(context->timestamps);
64 GNUNET_CONTAINER_multihashmap_destroy(context->messages); 70 GNUNET_CONTAINER_multihashmap_destroy(context->messages);
65 GNUNET_CONTAINER_multihashmap_destroy(context->invites); 71 GNUNET_CONTAINER_multihashmap_destroy(context->invites);
66 GNUNET_CONTAINER_multihashmap_destroy(context->files); 72 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
48 enum GNUNET_CHAT_ContextType type; 48 enum GNUNET_CHAT_ContextType type;
49 char *nick; 49 char *nick;
50 50
51 struct GNUNET_CONTAINER_MultiShortmap *timestamps;
51 struct GNUNET_CONTAINER_MultiHashMap *messages; 52 struct GNUNET_CONTAINER_MultiHashMap *messages;
52 struct GNUNET_CONTAINER_MultiHashMap *invites; 53 struct GNUNET_CONTAINER_MultiHashMap *invites;
53 struct GNUNET_CONTAINER_MultiHashMap *files; 54 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
@@ -28,6 +28,16 @@
28#define GNUNET_UNUSED __attribute__ ((unused)) 28#define GNUNET_UNUSED __attribute__ ((unused))
29 29
30int 30int
31it_destroy_context_timestamps (GNUNET_UNUSED void *cls,
32 GNUNET_UNUSED const struct GNUNET_ShortHashCode *key,
33 void *value)
34{
35 struct GNUNET_TIME_Absolute *time = value;
36 GNUNET_free(time);
37 return GNUNET_YES;
38}
39
40int
31it_destroy_context_messages (GNUNET_UNUSED void *cls, 41it_destroy_context_messages (GNUNET_UNUSED void *cls,
32 GNUNET_UNUSED const struct GNUNET_HashCode *key, 42 GNUNET_UNUSED const struct GNUNET_HashCode *key,
33 void *value) 43 void *value)
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,
279 if (!context) 279 if (!context)
280 return; 280 return;
281 281
282 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(
283 msg->header.timestamp
284 );
285
286 struct GNUNET_ShortHashCode shorthash;
287 util_shorthash_from_member(sender, &shorthash);
288
289 struct GNUNET_TIME_Absolute *time = GNUNET_CONTAINER_multishortmap_get(
290 context->timestamps, &shorthash
291 );
292
293 if (time)
294 {
295 time = GNUNET_new(struct GNUNET_TIME_Absolute);
296 *time = timestamp;
297
298 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(
299 context->timestamps, &shorthash, time,
300 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
301 GNUNET_free(time);
302 }
303 else
304 {
305 struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference(
306 timestamp, *time
307 );
308
309 if (GNUNET_TIME_relative_get_zero_().rel_value_us == delta.rel_value_us)
310 *time = timestamp;
311 }
312
282 struct GNUNET_CHAT_Message *message = GNUNET_CONTAINER_multihashmap_get( 313 struct GNUNET_CHAT_Message *message = GNUNET_CONTAINER_multihashmap_get(
283 context->messages, hash 314 context->messages, hash
284 ); 315 );
@@ -319,6 +350,16 @@ on_handle_message (void *cls,
319 file_destroy(file); 350 file_destroy(file);
320 break; 351 break;
321 } 352 }
353 case GNUNET_MESSENGER_KIND_DELETE:
354 {
355 struct GNUNET_CHAT_Message *target = GNUNET_CONTAINER_multihashmap_get(
356 context->messages, &(msg->body.deletion.hash)
357 );
358
359 if (target)
360 target->msg = NULL;
361 break;
362 }
322 default: 363 default:
323 break; 364 break;
324 } 365 }
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,
306 306
307 307
308void* 308void*
309GNUNET_CHAT_contact_get_user_pointer (struct GNUNET_CHAT_Contact *contact) 309GNUNET_CHAT_contact_get_user_pointer (const struct GNUNET_CHAT_Contact *contact)
310{ 310{
311 if (!contact) 311 if (!contact)
312 return NULL; 312 return NULL;
@@ -611,7 +611,7 @@ GNUNET_CHAT_context_iterate_messages (struct GNUNET_CHAT_Context *context,
611enum GNUNET_CHAT_MessageKind 611enum GNUNET_CHAT_MessageKind
612GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message) 612GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message)
613{ 613{
614 if (!message) 614 if ((!message) || (!(message->msg)))
615 return GNUNET_CHAT_KIND_UNKNOWN; 615 return GNUNET_CHAT_KIND_UNKNOWN;
616 616
617 switch (message->msg->header.kind) 617 switch (message->msg->header.kind)
@@ -641,7 +641,7 @@ GNUNET_CHAT_message_get_kind (const struct GNUNET_CHAT_Message *message)
641struct GNUNET_TIME_Absolute 641struct GNUNET_TIME_Absolute
642GNUNET_CHAT_message_get_timestamp (const struct GNUNET_CHAT_Message *message) 642GNUNET_CHAT_message_get_timestamp (const struct GNUNET_CHAT_Message *message)
643{ 643{
644 if (!message) 644 if ((!message) || (!(message->msg)))
645 return GNUNET_TIME_absolute_get_zero_(); 645 return GNUNET_TIME_absolute_get_zero_();
646 646
647 return GNUNET_TIME_absolute_ntoh(message->msg->header.timestamp); 647 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,
701 GNUNET_CHAT_MessageReadReceiptCallback callback, 701 GNUNET_CHAT_MessageReadReceiptCallback callback,
702 void *cls) 702 void *cls)
703{ 703{
704 if (!message) 704 if ((!message) || (!(message->msg)))
705 return GNUNET_SYSERR; 705 return GNUNET_SYSERR;
706 706
707 // TODO: request read receipt? / check if newer message was received of sender? 707 struct GNUNET_CHAT_Context *context = message->context;
708 708
709 return GNUNET_SYSERR; 709 if (!context)
710 return GNUNET_SYSERR;
711
712 struct GNUNET_CHAT_MessageIterateReadReceipts it;
713 it.message = message;
714 it.cb = callback;
715 it.cls = cls;
716
717 return GNUNET_MESSENGER_iterate_members(
718 context->room, it_message_iterate_read_receipts, &it
719 );
710} 720}
711 721
712 722
713const char* 723const char*
714GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message) 724GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message)
715{ 725{
716 if (!message) 726 if ((!message) || (!(message->msg)))
717 return NULL; 727 return NULL;
718 728
719 if (GNUNET_MESSENGER_KIND_TEXT != message->msg->header.kind) 729 if (GNUNET_MESSENGER_KIND_TEXT != message->msg->header.kind)
@@ -726,7 +736,7 @@ GNUNET_CHAT_message_get_text (const struct GNUNET_CHAT_Message *message)
726struct GNUNET_CHAT_File* 736struct GNUNET_CHAT_File*
727GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message) 737GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message)
728{ 738{
729 if (!message) 739 if ((!message) || (!(message->msg)))
730 return NULL; 740 return NULL;
731 741
732 if (GNUNET_MESSENGER_KIND_FILE != message->msg->header.kind) 742 if (GNUNET_MESSENGER_KIND_FILE != message->msg->header.kind)
@@ -742,7 +752,7 @@ GNUNET_CHAT_message_get_file (const struct GNUNET_CHAT_Message *message)
742struct GNUNET_CHAT_Invitation* 752struct GNUNET_CHAT_Invitation*
743GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message) 753GNUNET_CHAT_message_get_invitation (const struct GNUNET_CHAT_Message *message)
744{ 754{
745 if (!message) 755 if ((!message) || (!(message->msg)))
746 return NULL; 756 return NULL;
747 757
748 if (GNUNET_MESSENGER_KIND_INVITE != message->msg->header.kind) 758 if (GNUNET_MESSENGER_KIND_INVITE != message->msg->header.kind)
@@ -759,7 +769,7 @@ int
759GNUNET_CHAT_message_delete (const struct GNUNET_CHAT_Message *message, 769GNUNET_CHAT_message_delete (const struct GNUNET_CHAT_Message *message,
760 struct GNUNET_TIME_Relative delay) 770 struct GNUNET_TIME_Relative delay)
761{ 771{
762 if (!message) 772 if ((!message) || (!(message->msg)))
763 return GNUNET_SYSERR; 773 return GNUNET_SYSERR;
764 774
765 struct GNUNET_MESSENGER_Message msg; 775 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,
117 return it->cb(it->cls, it->context, message); 117 return it->cb(it->cls, it->context, message);
118} 118}
119 119
120struct GNUNET_CHAT_MessageIterateReadReceipts
121{
122 const struct GNUNET_CHAT_Message *message;
123 GNUNET_CHAT_MessageReadReceiptCallback cb;
124 void *cls;
125};
126
127int
128it_message_iterate_read_receipts (void *cls,
129 GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
130 const struct GNUNET_MESSENGER_Contact *member)
131{
132 struct GNUNET_CHAT_MessageIterateReadReceipts *it = cls;
133 struct GNUNET_CHAT_Handle *handle = it->message->context->handle;
134
135 if (!handle)
136 return GNUNET_NO;
137
138 struct GNUNET_ShortHashCode shorthash;
139 util_shorthash_from_member(member, &shorthash);
120 140
141 struct GNUNET_CHAT_Contact *contact = GNUNET_CONTAINER_multishortmap_get(
142 handle->contacts, &shorthash
143 );
144
145 if (!contact)
146 return GNUNET_YES;
147
148 struct GNUNET_TIME_Absolute *timestamp = GNUNET_CONTAINER_multishortmap_get(
149 it->message->context->timestamps, &shorthash
150 );
121 151
152 if (!timestamp)
153 return GNUNET_YES;
122 154
155 struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference(
156 *timestamp, GNUNET_CHAT_message_get_timestamp(it->message)
157 );
123 158
159 int read_receipt;
160 if (GNUNET_TIME_relative_get_zero_().rel_value_us == delta.rel_value_us)
161 read_receipt = GNUNET_YES;
162 else
163 read_receipt = GNUNET_NO;
124 164
165 if (it->cb)
166 it->cb(it->cls, it->message, contact, read_receipt);
167
168 return GNUNET_YES;
169}
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 @@
24 24
25#include "gnunet_chat_message.h" 25#include "gnunet_chat_message.h"
26 26
27#include "gnunet_chat_message_intern.c"
28
29struct GNUNET_CHAT_Message* 27struct GNUNET_CHAT_Message*
30message_create_from_msg (struct GNUNET_CHAT_Context *context, 28message_create_from_msg (struct GNUNET_CHAT_Context *context,
31 const struct GNUNET_HashCode *hash, 29 const struct GNUNET_HashCode *hash,
@@ -39,20 +37,13 @@ message_create_from_msg (struct GNUNET_CHAT_Context *context,
39 GNUNET_memcpy(&(message->hash), hash, sizeof(message->hash)); 37 GNUNET_memcpy(&(message->hash), hash, sizeof(message->hash));
40 message->flags = flags; 38 message->flags = flags;
41 39
42 message->head = NULL;
43 message->tail = NULL;
44
45 message->msg = msg; 40 message->msg = msg;
46 41
47 link_message_parent(message);
48
49 return message; 42 return message;
50} 43}
51 44
52void 45void
53message_destroy (struct GNUNET_CHAT_Message* message) 46message_destroy (struct GNUNET_CHAT_Message* message)
54{ 47{
55 unlink_message_parent(message);
56 clear_message_children(message);
57 GNUNET_free(message); 48 GNUNET_free(message);
58} 49}
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
48 struct GNUNET_HashCode hash; 48 struct GNUNET_HashCode hash;
49 enum GNUNET_MESSENGER_MessageFlags flags; 49 enum GNUNET_MESSENGER_MessageFlags flags;
50 50
51 struct GNUNET_CHAT_MessageList *head;
52 struct GNUNET_CHAT_MessageList *tail;
53
54 const struct GNUNET_MESSENGER_Message *msg; 51 const struct GNUNET_MESSENGER_Message *msg;
55}; 52};
56 53
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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file gnunet_chat_message_intern.c
23 */
24
25#include <gnunet/gnunet_container_lib.h>
26
27#include "gnunet_chat_context.h"
28
29void
30link_message_parent (struct GNUNET_CHAT_Message *message)
31{
32 struct GNUNET_CHAT_Context *context = message->context;
33
34 struct GNUNET_CHAT_Message *prev = GNUNET_CONTAINER_multihashmap_get(
35 context->messages, &(message->msg->header.previous)
36 );
37
38 if (prev)
39 {
40 struct GNUNET_CHAT_MessageList *list = GNUNET_new(
41 struct GNUNET_CHAT_MessageList
42 );
43
44 list->message = message;
45
46 GNUNET_CONTAINER_DLL_insert(prev->head, prev->tail, list);
47 }
48
49 if (GNUNET_MESSENGER_KIND_MERGE != message->msg->header.kind)
50 return;
51
52 prev = GNUNET_CONTAINER_multihashmap_get(
53 context->messages, &(message->msg->body.merge.previous)
54 );
55
56 if (prev)
57 {
58 struct GNUNET_CHAT_MessageList *list = GNUNET_new(
59 struct GNUNET_CHAT_MessageList
60 );
61
62 list->message = message;
63
64 GNUNET_CONTAINER_DLL_insert(prev->head, prev->tail, list);
65 }
66}
67
68void
69unlink_message_parent (struct GNUNET_CHAT_Message *message)
70{
71 struct GNUNET_CHAT_Context *context = message->context;
72
73 struct GNUNET_CHAT_Message *prev = GNUNET_CONTAINER_multihashmap_get(
74 context->messages, &(message->msg->header.previous)
75 );
76
77 if (prev)
78 {
79 struct GNUNET_CHAT_MessageList *list = prev->head;
80
81 while (list)
82 {
83 if (list->message == message)
84 break;
85
86 list = list->next;
87 }
88
89 if (list)
90 {
91 GNUNET_CONTAINER_DLL_remove(prev->head, prev->tail, list);
92 GNUNET_free(list);
93 }
94 }
95
96 if (GNUNET_MESSENGER_KIND_MERGE != message->msg->header.kind)
97 return;
98
99 prev = GNUNET_CONTAINER_multihashmap_get(
100 context->messages, &(message->msg->body.merge.previous)
101 );
102
103 if (prev)
104 {
105 struct GNUNET_CHAT_MessageList *list = prev->head;
106
107 while (list)
108 {
109 if (list->message == message)
110 break;
111
112 list = list->next;
113 }
114
115 if (list)
116 {
117 GNUNET_CONTAINER_DLL_remove(prev->head, prev->tail, list);
118 GNUNET_free(list);
119 }
120 }
121}
122
123void
124clear_message_children (struct GNUNET_CHAT_Message *message)
125{
126 struct GNUNET_CHAT_MessageList *list = message->tail;
127
128 while (list)
129 {
130 GNUNET_CONTAINER_DLL_remove(message->head, message->tail, list);
131 GNUNET_free(list);
132
133 list = message->tail;
134 }
135}