aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2024-02-01 20:40:40 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2024-02-01 20:40:40 +0100
commit25e42d202a4f9b356a5e8775cd7ef2c741b3d187 (patch)
tree70bb3e415ac216b26604744250db49c783b01fda /src
parent31a66fa661710e8d842e5742618664e067910c49 (diff)
downloadgnunet-25e42d202a4f9b356a5e8775cd7ef2c741b3d187.tar.gz
gnunet-25e42d202a4f9b356a5e8775cd7ef2c741b3d187.zip
MESSENGER: Implement client side deletion and update callback for messages
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_messenger_service.h10
-rw-r--r--src/service/messenger/messenger_api.c102
-rw-r--r--src/service/messenger/messenger_api_contact_store.c5
-rw-r--r--src/service/messenger/messenger_api_message.c24
-rw-r--r--src/service/messenger/messenger_api_message.h12
-rw-r--r--src/service/messenger/messenger_api_room.c437
-rw-r--r--src/service/messenger/messenger_api_room.h28
7 files changed, 398 insertions, 220 deletions
diff --git a/src/include/gnunet_messenger_service.h b/src/include/gnunet_messenger_service.h
index 8e1cd666d..8c009a0e6 100644
--- a/src/include/gnunet_messenger_service.h
+++ b/src/include/gnunet_messenger_service.h
@@ -669,6 +669,16 @@ enum GNUNET_MESSENGER_MessageFlags
669 * The recent flag. The flag indicates that the message was recently handled by the service. 669 * The recent flag. The flag indicates that the message was recently handled by the service.
670 */ 670 */
671 GNUNET_MESSENGER_FLAG_RECENT = 8, 671 GNUNET_MESSENGER_FLAG_RECENT = 8,
672
673 /**
674 * The update flag. The flag indicates that the message was updated by the client.
675 */
676 GNUNET_MESSENGER_FLAG_UPDATE = 16,
677
678 /**
679 * The delete flag. The flag indicates that the message was deleted by the service.
680 */
681 GNUNET_MESSENGER_FLAG_DELETE = 32,
672}; 682};
673 683
674/** 684/**
diff --git a/src/service/messenger/messenger_api.c b/src/service/messenger/messenger_api.c
index 7623e21c5..dc2e6045a 100644
--- a/src/service/messenger/messenger_api.c
+++ b/src/service/messenger/messenger_api.c
@@ -24,7 +24,6 @@
24 */ 24 */
25 25
26#include "gnunet_common.h" 26#include "gnunet_common.h"
27#include "gnunet_core_service.h"
28#include "gnunet_messenger_service.h" 27#include "gnunet_messenger_service.h"
29 28
30#include "gnunet-service-messenger.h" 29#include "gnunet-service-messenger.h"
@@ -109,7 +108,7 @@ handle_room_open (void *cls,
109 if (! room) 108 if (! room)
110 return; 109 return;
111 110
112 GNUNET_memcpy (&(room->last_message), prev, sizeof(room->last_message)); 111 update_room_last_message (room, prev);
113 112
114 dequeue_messages_from_room (room); 113 dequeue_messages_from_room (room);
115} 114}
@@ -134,7 +133,7 @@ handle_room_entry (void *cls,
134 if (! room) 133 if (! room)
135 return; 134 return;
136 135
137 GNUNET_memcpy (&(room->last_message), prev, sizeof(room->last_message)); 136 update_room_last_message (room, prev);
138 137
139 dequeue_messages_from_room (room); 138 dequeue_messages_from_room (room);
140} 139}
@@ -152,7 +151,7 @@ handle_room_close (void *cls,
152 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); 151 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
153 152
154 if (room) 153 if (room)
155 GNUNET_memcpy (&(room->last_message), prev, sizeof(room->last_message)); 154 update_room_last_message (room, prev);
156 155
157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key)); 156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
158 157
@@ -174,7 +173,7 @@ handle_room_sync (void *cls,
174 if (! room) 173 if (! room)
175 return; 174 return;
176 175
177 GNUNET_memcpy (&(room->last_message), prev, sizeof(room->last_message)); 176 update_room_last_message (room, prev);
178 177
179 room->wait_for_sync = GNUNET_NO; 178 room->wait_for_sync = GNUNET_NO;
180 179
@@ -225,12 +224,6 @@ handle_member_id (void *cls,
225} 224}
226 225
227 226
228static void
229delete_message_in_room (struct GNUNET_MESSENGER_Room *room,
230 const struct GNUNET_HashCode *hash,
231 const struct GNUNET_TIME_Relative delay);
232
233
234static enum GNUNET_GenericReturnValue 227static enum GNUNET_GenericReturnValue
235check_recv_message (void *cls, 228check_recv_message (void *cls,
236 const struct GNUNET_MESSENGER_RecvMessage *msg) 229 const struct GNUNET_MESSENGER_RecvMessage *msg)
@@ -281,8 +274,7 @@ handle_recv_message (void *cls,
281 const struct GNUNET_HashCode *hash = &(msg->hash); 274 const struct GNUNET_HashCode *hash = &(msg->hash);
282 275
283 enum GNUNET_MESSENGER_MessageFlags flags = ( 276 enum GNUNET_MESSENGER_MessageFlags flags = (
284 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags) 277 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags));
285 );
286 278
287 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); 279 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
288 const char *buffer = ((const char*) msg) + sizeof(*msg); 280 const char *buffer = ((const char*) msg) + sizeof(*msg);
@@ -290,28 +282,8 @@ handle_recv_message (void *cls,
290 struct GNUNET_MESSENGER_Message message; 282 struct GNUNET_MESSENGER_Message message;
291 decode_message (&message, length, buffer, GNUNET_YES, NULL); 283 decode_message (&message, length, buffer, GNUNET_YES, NULL);
292 284
293 struct GNUNET_MESSENGER_Message *private_message = NULL;
294 const struct GNUNET_MESSENGER_Message *handle_msg = &message;
295
296 if (GNUNET_MESSENGER_KIND_PRIVATE == message.header.kind)
297 {
298 private_message = copy_message (&message);
299
300 if (GNUNET_YES != decrypt_message (private_message, get_handle_key (
301 handle)))
302 {
303 destroy_message (private_message);
304 private_message = NULL;
305 }
306 }
307
308 if (private_message)
309 flags |= GNUNET_MESSENGER_FLAG_PRIVATE;
310
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", 285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n",
312 GNUNET_MESSENGER_name_of_kind (private_message ? 286 GNUNET_MESSENGER_name_of_kind (message.header.kind));
313 private_message->header.kind :
314 message.header.kind));
315 287
316 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); 288 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
317 289
@@ -332,66 +304,16 @@ handle_recv_message (void *cls,
332 304
333 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw ( 305 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw (
334 store, context, sender); 306 store, context, sender);
335
336 struct GNUNET_MESSENGER_Contact *recipient = NULL;
337
338 if (!private_message)
339 goto skip_recipient;
340
341 const struct GNUNET_CRYPTO_PublicKey *recipient_key;
342
343 if (GNUNET_MESSENGER_KIND_TRANSCRIPT == private_message->header.kind)
344 {
345 struct GNUNET_MESSENGER_Message *transcript;
346 307
347 recipient_key = &(private_message->body.transcript.key); 308 handle_room_message (room, contact, &message, hash, flags);
348 transcript = read_transcript_message(private_message);
349 309
350 if (transcript) 310 if (flags & GNUNET_MESSENGER_FLAG_RECENT)
351 { 311 update_room_last_message (room, hash);
352 destroy_message(private_message);
353 private_message = transcript;
354 }
355 }
356 else
357 recipient_key = get_handle_pubkey(handle);
358 312
359 recipient = get_store_contact(store, context, recipient_key); 313 callback_room_message (room, hash);
360
361skip_recipient:
362 if (private_message)
363 handle_msg = private_message;
364
365 if ((GNUNET_MESSENGER_KIND_DELETE == handle_msg->header.kind) &&
366 (GNUNET_MESSENGER_FLAG_SENT & flags))
367 {
368 struct GNUNET_TIME_Relative delay;
369 struct GNUNET_TIME_Absolute action;
370
371 delay = GNUNET_TIME_relative_ntoh (handle_msg->body.deletion.delay);
372
373 action = GNUNET_TIME_absolute_ntoh (handle_msg->header.timestamp);
374 action = GNUNET_TIME_absolute_add (action, delay);
375
376 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
377
378 link_room_deletion (room, &(handle_msg->body.deletion.hash), delay, delete_message_in_room);
379 }
380
381 contact = handle_room_message (room, contact, recipient, handle_msg, hash, flags);
382
383 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message (
384 room, hash);
385
386 if (handle->msg_callback)
387 handle->msg_callback (handle->msg_cls, room, contact, recipient,
388 stored_message, hash, flags);
389 314
390skip_message: 315skip_message:
391 cleanup_message (&message); 316 cleanup_message (&message);
392
393 if (private_message)
394 destroy_message (private_message);
395} 317}
396 318
397 319
@@ -752,7 +674,7 @@ send_message_to_room (struct GNUNET_MESSENGER_Room *room,
752 hash_message (message, msg_length, msg_buffer, hash); 674 hash_message (message, msg_length, msg_buffer, hash);
753 sign_message (message, msg_length, msg_buffer, hash, key); 675 sign_message (message, msg_length, msg_buffer, hash, key);
754 676
755 GNUNET_memcpy (&(room->last_message), hash, sizeof(room->last_message)); 677 update_room_last_message (room, hash);
756 678
757 GNUNET_MQ_send (room->handle->mq, env); 679 GNUNET_MQ_send (room->handle->mq, env);
758 680
@@ -1243,7 +1165,7 @@ GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
1243} 1165}
1244 1166
1245 1167
1246static void 1168void
1247delete_message_in_room (struct GNUNET_MESSENGER_Room *room, 1169delete_message_in_room (struct GNUNET_MESSENGER_Room *room,
1248 const struct GNUNET_HashCode *hash, 1170 const struct GNUNET_HashCode *hash,
1249 const struct GNUNET_TIME_Relative delay) 1171 const struct GNUNET_TIME_Relative delay)
diff --git a/src/service/messenger/messenger_api_contact_store.c b/src/service/messenger/messenger_api_contact_store.c
index 538e97acc..75069b187 100644
--- a/src/service/messenger/messenger_api_contact_store.c
+++ b/src/service/messenger/messenger_api_contact_store.c
@@ -113,14 +113,13 @@ get_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
113 const struct GNUNET_HashCode *context, 113 const struct GNUNET_HashCode *context,
114 const struct GNUNET_CRYPTO_PublicKey *pubkey) 114 const struct GNUNET_CRYPTO_PublicKey *pubkey)
115{ 115{
116 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey)); 116 GNUNET_assert ((store) && (store->contacts) && (pubkey));
117 117
118 struct GNUNET_HashCode hash; 118 struct GNUNET_HashCode hash;
119 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash); 119 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
120 120
121 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map ( 121 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
122 store, context, &hash 122 store, context, &hash);
123 );
124 123
125 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get ( 124 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (
126 map, &hash); 125 map, &hash);
diff --git a/src/service/messenger/messenger_api_message.c b/src/service/messenger/messenger_api_message.c
index f6d8c31f7..d98938671 100644
--- a/src/service/messenger/messenger_api_message.c
+++ b/src/service/messenger/messenger_api_message.c
@@ -29,6 +29,7 @@
29#include "gnunet_messenger_service.h" 29#include "gnunet_messenger_service.h"
30#include "gnunet_signatures.h" 30#include "gnunet_signatures.h"
31#include <stdint.h> 31#include <stdint.h>
32#include <string.h>
32 33
33struct GNUNET_MESSENGER_MessageSignature 34struct GNUNET_MESSENGER_MessageSignature
34{ 35{
@@ -1123,34 +1124,29 @@ transcribe_message (const struct GNUNET_MESSENGER_Message *message,
1123} 1124}
1124 1125
1125 1126
1126struct GNUNET_MESSENGER_Message* 1127enum GNUNET_GenericReturnValue
1127read_transcript_message (const struct GNUNET_MESSENGER_Message *transcript) 1128read_transcript_message (struct GNUNET_MESSENGER_Message *message)
1128{ 1129{
1129 GNUNET_assert (transcript); 1130 GNUNET_assert (message);
1130 1131
1131 if (GNUNET_MESSENGER_KIND_TRANSCRIPT != transcript->header.kind) 1132 if (GNUNET_MESSENGER_KIND_TRANSCRIPT != message->header.kind)
1132 return NULL; 1133 return GNUNET_NO;
1133 1134
1134 const uint16_t data_length = transcript->body.transcript.length; 1135 const uint16_t data_length = message->body.transcript.length;
1135 1136
1136 struct GNUNET_MESSENGER_ShortMessage shortened; 1137 struct GNUNET_MESSENGER_ShortMessage shortened;
1137 if (GNUNET_YES != decode_short_message (&shortened, 1138 if (GNUNET_YES != decode_short_message (&shortened,
1138 data_length, 1139 data_length,
1139 transcript->body.transcript.data)) 1140 message->body.transcript.data))
1140 { 1141 {
1141 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1142 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1142 "Decoding decrypted message failed!\n"); 1143 "Decoding decrypted message failed!\n");
1143 1144
1144 return NULL; 1145 return GNUNET_NO;
1145 } 1146 }
1146 1147
1147 struct GNUNET_MESSENGER_Message *message = create_message(shortened.kind);
1148
1149 if (!message)
1150 return NULL;
1151
1152 unfold_short_message(&shortened, message); 1148 unfold_short_message(&shortened, message);
1153 return message; 1149 return GNUNET_YES;
1154} 1150}
1155 1151
1156 1152
diff --git a/src/service/messenger/messenger_api_message.h b/src/service/messenger/messenger_api_message.h
index a19eb36ba..f5bc62519 100644
--- a/src/service/messenger/messenger_api_message.h
+++ b/src/service/messenger/messenger_api_message.h
@@ -257,13 +257,15 @@ transcribe_message (const struct GNUNET_MESSENGER_Message *message,
257 const struct GNUNET_CRYPTO_PublicKey *key); 257 const struct GNUNET_CRYPTO_PublicKey *key);
258 258
259/** 259/**
260 * Read the original message from a message <i>transcript</i>. 260 * Read the original message from a transcript <i>message</i> and replaces its body
261 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
262 * operation succeeded, otherwise #GNUNET_NO.
261 * 263 *
262 * @param[in] transcript Message transcript 264 * @param[in,out] transcript Message transcript
263 * @return Original message 265 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
264 */ 266 */
265struct GNUNET_MESSENGER_Message* 267enum GNUNET_GenericReturnValue
266read_transcript_message (const struct GNUNET_MESSENGER_Message *transcript); 268read_transcript_message (struct GNUNET_MESSENGER_Message *message);
267 269
268typedef void (*GNUNET_MESSENGER_SignFunction)( 270typedef void (*GNUNET_MESSENGER_SignFunction)(
269 const void *cls, 271 const void *cls,
diff --git a/src/service/messenger/messenger_api_room.c b/src/service/messenger/messenger_api_room.c
index 364a4e674..6b127fca5 100644
--- a/src/service/messenger/messenger_api_room.c
+++ b/src/service/messenger/messenger_api_room.c
@@ -25,8 +25,12 @@
25 25
26#include "messenger_api_room.h" 26#include "messenger_api_room.h"
27 27
28#include "gnunet_common.h"
29#include "gnunet_messenger_service.h"
30#include "messenger_api_contact_store.h"
28#include "messenger_api_handle.h" 31#include "messenger_api_handle.h"
29#include "messenger_api_message.h" 32#include "messenger_api_message.h"
33#include <string.h>
30 34
31struct GNUNET_MESSENGER_Room* 35struct GNUNET_MESSENGER_Room*
32create_room (struct GNUNET_MESSENGER_Handle *handle, 36create_room (struct GNUNET_MESSENGER_Handle *handle,
@@ -178,8 +182,11 @@ get_room_message (const struct GNUNET_MESSENGER_Room *room,
178 GNUNET_CONTAINER_multihashmap_get ( 182 GNUNET_CONTAINER_multihashmap_get (
179 room->messages, hash 183 room->messages, hash
180 ); 184 );
185
186 if (! entry)
187 return NULL;
181 188
182 return (entry? entry->message : NULL); 189 return entry->message;
183} 190}
184 191
185 192
@@ -213,50 +220,85 @@ get_room_recipient (const struct GNUNET_MESSENGER_Room *room,
213} 220}
214 221
215 222
216static struct GNUNET_MESSENGER_Contact* 223void
224callback_room_message (struct GNUNET_MESSENGER_Room *room,
225 const struct GNUNET_HashCode *hash)
226{
227 GNUNET_assert ((room) && (hash));
228
229 struct GNUNET_MESSENGER_Handle *handle = room->handle;
230
231 if (! handle)
232 return;
233
234 struct GNUNET_MESSENGER_RoomMessageEntry *entry;
235 entry = GNUNET_CONTAINER_multihashmap_get (room->messages, hash);
236
237 if (! entry)
238 return;
239
240 if (handle->msg_callback)
241 handle->msg_callback (handle->msg_cls, room,
242 entry->sender,
243 entry->recipient,
244 entry->message,
245 hash,
246 entry->flags);
247
248 if (entry->flags & GNUNET_MESSENGER_FLAG_UPDATE)
249 entry->flags ^= GNUNET_MESSENGER_FLAG_UPDATE;
250}
251
252
253static void
254handle_message (struct GNUNET_MESSENGER_Room *room,
255 const struct GNUNET_HashCode *hash,
256 struct GNUNET_MESSENGER_RoomMessageEntry *entry);
257
258
259void
217handle_join_message (struct GNUNET_MESSENGER_Room *room, 260handle_join_message (struct GNUNET_MESSENGER_Room *room,
218 struct GNUNET_MESSENGER_Contact *sender, 261 const struct GNUNET_HashCode *hash,
219 const struct GNUNET_MESSENGER_Message *message, 262 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
220 const struct GNUNET_HashCode *hash)
221{ 263{
222 if (! sender) 264 GNUNET_assert ((room) && (hash) && (entry));
265
266 if (! entry->sender)
223 { 267 {
224 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store ( 268 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
225 room->handle); 269 room->handle);
226 struct GNUNET_HashCode context; 270 struct GNUNET_HashCode context;
227 271
228 get_context_from_member (&(room->key), &(message->header.sender_id), 272 get_context_from_member (&(room->key), &(entry->message->header.sender_id),
229 &context); 273 &context);
230 274
231 sender = get_store_contact (store, &context, &(message->body.join.key)); 275 entry->sender = get_store_contact (store, &context, &(entry->message->body.join.key));
232 } 276 }
233 277
234 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value ( 278 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value (
235 room->members, &(message->header.sender_id), sender)) && 279 room->members, &(entry->message->header.sender_id), entry->sender)) &&
236 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, 280 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members,
237 &(message->header. 281 &(entry->message->header.sender_id),
238 sender_id), sender, 282 entry->sender,
239 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))) 283 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
240 increase_contact_rc (sender); 284 increase_contact_rc (entry->sender);
241
242 return sender;
243} 285}
244 286
245 287
246static void 288static void
247handle_leave_message (struct GNUNET_MESSENGER_Room *room, 289handle_leave_message (struct GNUNET_MESSENGER_Room *room,
248 struct GNUNET_MESSENGER_Contact *sender, 290 const struct GNUNET_HashCode *hash,
249 const struct GNUNET_MESSENGER_Message *message, 291 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
250 const struct GNUNET_HashCode *hash)
251{ 292{
252 if ((! sender) || 293 GNUNET_assert ((room) && (hash) && (entry));
294
295 if ((! entry->sender) ||
253 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->members, 296 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->members,
254 &(message->header. 297 &(entry->message->header.sender_id),
255 sender_id), 298 entry->sender)))
256 sender)))
257 return; 299 return;
258 300
259 if (GNUNET_YES == decrease_contact_rc (sender)) 301 if (GNUNET_YES == decrease_contact_rc (entry->sender))
260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
261 "A contact does not share any room with you anymore!\n"); 303 "A contact does not share any room with you anymore!\n");
262} 304}
@@ -264,12 +306,12 @@ handle_leave_message (struct GNUNET_MESSENGER_Room *room,
264 306
265static void 307static void
266handle_name_message (struct GNUNET_MESSENGER_Room *room, 308handle_name_message (struct GNUNET_MESSENGER_Room *room,
267 struct GNUNET_MESSENGER_Contact *sender,
268 const struct GNUNET_MESSENGER_Message *message,
269 const struct GNUNET_HashCode *hash, 309 const struct GNUNET_HashCode *hash,
270 enum GNUNET_MESSENGER_MessageFlags flags) 310 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
271{ 311{
272 if (GNUNET_MESSENGER_FLAG_SENT & flags) 312 GNUNET_assert ((room) && (hash) && (entry));
313
314 if (GNUNET_MESSENGER_FLAG_SENT & entry->flags)
273 { 315 {
274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
275 "Set rule for using handle name in room: %s\n", 317 "Set rule for using handle name in room: %s\n",
@@ -277,176 +319,363 @@ handle_name_message (struct GNUNET_MESSENGER_Room *room,
277 319
278 const char *handle_name = get_handle_name (room->handle); 320 const char *handle_name = get_handle_name (room->handle);
279 321
280 if ((handle_name) && (0 == strcmp (handle_name, message->body.name.name))) 322 if ((handle_name) && (0 == strcmp (handle_name, entry->message->body.name.name)))
281 room->use_handle_name = GNUNET_YES; 323 room->use_handle_name = GNUNET_YES;
282 } 324 }
283 325
284 if (! sender) 326 if (! entry->sender)
285 return; 327 return;
286 328
287 set_contact_name (sender, message->body.name.name); 329 set_contact_name (entry->sender, entry->message->body.name.name);
288} 330}
289 331
290 332
291static void 333static void
292handle_key_message (struct GNUNET_MESSENGER_Room *room, 334handle_key_message (struct GNUNET_MESSENGER_Room *room,
293 struct GNUNET_MESSENGER_Contact *sender, 335 const struct GNUNET_HashCode *hash,
294 const struct GNUNET_MESSENGER_Message *message, 336 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
295 const struct GNUNET_HashCode *hash)
296{ 337{
297 if (! sender) 338 GNUNET_assert ((room) && (hash) && (entry));
339
340 if (! entry->sender)
298 return; 341 return;
299 342
300 struct GNUNET_HashCode context; 343 struct GNUNET_HashCode context;
301 get_context_from_member (&(room->key), &(message->header.sender_id), 344 get_context_from_member (&(room->key), &(entry->message->header.sender_id),
302 &context); 345 &context);
303 346
304 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store ( 347 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
305 room->handle); 348 room->handle);
306 349
307 update_store_contact (store, sender, &context, &context, 350 update_store_contact (store, entry->sender, &context, &context,
308 &(message->body.key.key)); 351 &(entry->message->body.key.key));
309} 352}
310 353
311 354
312static void 355static void
313handle_id_message (struct GNUNET_MESSENGER_Room *room, 356handle_id_message (struct GNUNET_MESSENGER_Room *room,
314 struct GNUNET_MESSENGER_Contact *sender,
315 const struct GNUNET_MESSENGER_Message *message,
316 const struct GNUNET_HashCode *hash, 357 const struct GNUNET_HashCode *hash,
317 enum GNUNET_MESSENGER_MessageFlags flags) 358 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
318{ 359{
319 if (GNUNET_MESSENGER_FLAG_SENT & flags) 360 GNUNET_assert ((room) && (hash) && (entry));
320 set_room_sender_id (room, &(message->body.id.id));
321 361
322 if ((! sender) || 362 if (GNUNET_MESSENGER_FLAG_SENT & entry->flags)
363 set_room_sender_id (room, &(entry->message->body.id.id));
364
365 if ((! entry->sender) ||
323 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->members, 366 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->members,
324 &(message->header. 367 &(entry->message->header.sender_id),
325 sender_id), 368 entry->sender)) ||
326 sender)) ||
327 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (room->members, 369 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (room->members,
328 &(message->body.id.id), 370 &(entry->message->body.id.id),
329 sender, 371 entry->sender,
330 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))) 372 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
331 return; 373 return;
332 374
333 struct GNUNET_HashCode context, next_context; 375 struct GNUNET_HashCode context, next_context;
334 get_context_from_member (&(room->key), &(message->header.sender_id), 376 get_context_from_member (&(room->key), &(entry->message->header.sender_id),
335 &context); 377 &context);
336 get_context_from_member (&(room->key), &(message->body.id.id), &next_context); 378 get_context_from_member (&(room->key), &(entry->message->body.id.id), &next_context);
337 379
338 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store ( 380 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
339 room->handle); 381 room->handle);
340 382
341 update_store_contact (store, sender, &context, &next_context, 383 update_store_contact (store, entry->sender, &context, &next_context,
342 get_contact_key (sender)); 384 get_contact_key (entry->sender));
343} 385}
344 386
345 387
346static void 388static void
347handle_miss_message (struct GNUNET_MESSENGER_Room *room, 389handle_miss_message (struct GNUNET_MESSENGER_Room *room,
348 struct GNUNET_MESSENGER_Contact *sender,
349 const struct GNUNET_MESSENGER_Message *message,
350 const struct GNUNET_HashCode *hash, 390 const struct GNUNET_HashCode *hash,
351 enum GNUNET_MESSENGER_MessageFlags flags) 391 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
352{ 392{
353 if (GNUNET_MESSENGER_FLAG_SENT & flags) 393 GNUNET_assert ((room) && (hash) && (entry));
354 { 394
355 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels ( 395 if (0 == (GNUNET_MESSENGER_FLAG_SENT & entry->flags))
356 &(room->entries), &(message->body.miss.peer), NULL); 396 return;
397
398 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (
399 &(room->entries), &(entry->message->body.miss.peer), NULL);
400
401 if (match)
402 remove_from_list_tunnels (&(room->entries), match);
403}
404
405
406static void
407handle_private_message (struct GNUNET_MESSENGER_Room *room,
408 const struct GNUNET_HashCode *hash,
409 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
410{
411 GNUNET_assert ((room) && (hash) && (entry));
412
413 struct GNUNET_MESSENGER_Message *private_message = copy_message (entry->message);
357 414
358 if (match) 415 if (! private_message)
359 remove_from_list_tunnels (&(room->entries), match); 416 return;
417
418 if (GNUNET_YES != decrypt_message (private_message,
419 get_handle_key (room->handle)))
420 {
421 destroy_message (private_message);
422 private_message = NULL;
360 } 423 }
424
425 if (! private_message)
426 return;
427
428 destroy_message (entry->message);
429
430 entry->recipient = get_handle_contact (room->handle, &(room->key));
431
432 entry->message = private_message;
433 entry->flags |= GNUNET_MESSENGER_FLAG_PRIVATE;
434
435 if ((entry->sender) && (entry->recipient))
436 handle_message (room, hash, entry);
361} 437}
362 438
363 439
440extern void
441delete_message_in_room (struct GNUNET_MESSENGER_Room *room,
442 const struct GNUNET_HashCode *hash,
443 const struct GNUNET_TIME_Relative delay);
444
445
364static void 446static void
365handle_delete_message (struct GNUNET_MESSENGER_Room *room, 447handle_delete_message (struct GNUNET_MESSENGER_Room *room,
366 struct GNUNET_MESSENGER_Contact *sender, 448 const struct GNUNET_HashCode *hash,
367 const struct GNUNET_MESSENGER_Message *message, 449 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
368 const struct GNUNET_HashCode *hash)
369{ 450{
370 struct GNUNET_MESSENGER_RoomMessageEntry *entry = 451 GNUNET_assert ((room) && (hash) && (entry));
371 GNUNET_CONTAINER_multihashmap_get (
372 room->messages, &(message->body.deletion.hash)
373 );
374 452
375 if ((entry) && ((entry->sender == sender) || (get_handle_contact ( 453 const struct GNUNET_HashCode *target_hash = &(entry->message->body.deletion.hash);
376 room->handle, &(room->key)) == 454
377 sender)) && 455 if (get_handle_contact (room->handle, &(room->key)) == entry->sender)
378 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages,
379 &(message->body.
380 deletion.hash),
381 entry)))
382 { 456 {
383 destroy_message (entry->message); 457 struct GNUNET_TIME_Relative delay;
384 GNUNET_free (entry); 458 struct GNUNET_TIME_Absolute action;
459
460 delay = GNUNET_TIME_relative_ntoh (entry->message->body.deletion.delay);
461
462 action = GNUNET_TIME_absolute_ntoh (entry->message->header.timestamp);
463 action = GNUNET_TIME_absolute_add (action, delay);
464
465 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (),
466 action);
467
468 link_room_deletion(room, target_hash, delay, delete_message_in_room);
469 }
470
471 struct GNUNET_MESSENGER_RoomMessageEntry *target =
472 GNUNET_CONTAINER_multihashmap_get (room->messages, target_hash);
473
474 if (! target)
475 return;
476
477 if (((target->sender != entry->sender) &&
478 (get_handle_contact (room->handle, &(room->key)) != entry->sender)))
479 return;
480
481 target->flags |= GNUNET_MESSENGER_FLAG_DELETE;
482 callback_room_message (room, target_hash);
483
484 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages,
485 target_hash,
486 target))
487 {
488 destroy_message (target->message);
489 GNUNET_free (target);
385 } 490 }
386} 491}
387 492
388 493
389struct GNUNET_MESSENGER_Contact* 494static void
390handle_room_message (struct GNUNET_MESSENGER_Room *room, 495handle_transcript_message (struct GNUNET_MESSENGER_Room *room,
391 struct GNUNET_MESSENGER_Contact *sender, 496 const struct GNUNET_HashCode *hash,
392 struct GNUNET_MESSENGER_Contact *recipient, 497 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
393 const struct GNUNET_MESSENGER_Message *message,
394 const struct GNUNET_HashCode *hash,
395 enum GNUNET_MESSENGER_MessageFlags flags)
396{ 498{
397 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, 499 GNUNET_assert ((room) && (hash) && (entry));
398 hash))
399 return sender;
400 500
401 switch (message->header.kind) 501 if (get_handle_contact (room->handle, &(room->key)) != entry->sender)
502 return;
503
504 const struct GNUNET_HashCode *original_hash = &(entry->message->body.transcript.hash);
505 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
506 room->handle);
507
508 struct GNUNET_MESSENGER_RoomMessageEntry *original =
509 GNUNET_CONTAINER_multihashmap_get (room->messages, original_hash);
510 struct GNUNET_MESSENGER_Message *original_message;
511
512 if (original)
513 goto read_transcript;
514
515 original = GNUNET_new (struct GNUNET_MESSENGER_RoomMessageEntry);
516
517 if (! original)
518 return;
519
520 original->sender = NULL;
521 original->recipient = NULL;
522
523 original->message = NULL;
524 original->flags = GNUNET_MESSENGER_FLAG_NONE;
525
526 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages,
527 original_hash,
528 original,
529 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
530 {
531 GNUNET_free (original);
532 return;
533 }
534
535read_transcript:
536 original_message = copy_message (entry->message);
537
538 if (! original_message)
539 return;
540
541 if (GNUNET_YES != read_transcript_message (original_message))
542 {
543 destroy_message (original_message);
544 return;
545 }
546
547 original->recipient = get_store_contact (store,
548 NULL,
549 &(entry->message->body.transcript.key));
550
551 if (original->message)
552 {
553 enum GNUNET_MESSENGER_MessageKind kind = original_message->header.kind;
554 memcpy (&(original_message->header), &(original->message->header),
555 sizeof(struct GNUNET_MESSENGER_MessageHeader));
556 original_message->header.kind = kind;
557
558 destroy_message (original->message);
559 }
560
561 original->message = original_message;
562 original->flags |= GNUNET_MESSENGER_FLAG_PRIVATE;
563
564 link_room_message(room, hash, original_hash);
565 link_room_message(room, original_hash, hash);
566
567 if ((original->sender) && (original->recipient))
568 {
569 original->flags |= GNUNET_MESSENGER_FLAG_UPDATE;
570 handle_message (room, original_hash, original);
571 }
572}
573
574
575static void
576handle_message (struct GNUNET_MESSENGER_Room *room,
577 const struct GNUNET_HashCode *hash,
578 struct GNUNET_MESSENGER_RoomMessageEntry *entry)
579{
580 GNUNET_assert ((room) && (hash) && (entry));
581
582 switch (entry->message->header.kind)
402 { 583 {
403 case GNUNET_MESSENGER_KIND_JOIN: 584 case GNUNET_MESSENGER_KIND_JOIN:
404 sender = handle_join_message (room, sender, message, hash); 585 handle_join_message (room, hash, entry);
405 break; 586 break;
406 case GNUNET_MESSENGER_KIND_LEAVE: 587 case GNUNET_MESSENGER_KIND_LEAVE:
407 handle_leave_message (room, sender, message, hash); 588 handle_leave_message (room, hash, entry);
408 break; 589 break;
409 case GNUNET_MESSENGER_KIND_NAME: 590 case GNUNET_MESSENGER_KIND_NAME:
410 handle_name_message (room, sender, message, hash, flags); 591 handle_name_message (room, hash, entry);
411 break; 592 break;
412 case GNUNET_MESSENGER_KIND_KEY: 593 case GNUNET_MESSENGER_KIND_KEY:
413 handle_key_message (room, sender, message, hash); 594 handle_key_message (room, hash, entry);
414 break; 595 break;
415 case GNUNET_MESSENGER_KIND_ID: 596 case GNUNET_MESSENGER_KIND_ID:
416 handle_id_message (room, sender, message, hash, flags); 597 handle_id_message (room, hash, entry);
417 break; 598 break;
418 case GNUNET_MESSENGER_KIND_MISS: 599 case GNUNET_MESSENGER_KIND_MISS:
419 handle_miss_message (room, sender, message, hash, flags); 600 handle_miss_message (room, hash, entry);
601 break;
602 case GNUNET_MESSENGER_KIND_PRIVATE:
603 handle_private_message (room, hash, entry);
420 break; 604 break;
421 case GNUNET_MESSENGER_KIND_DELETE: 605 case GNUNET_MESSENGER_KIND_DELETE:
422 handle_delete_message (room, sender, message, hash); 606 handle_delete_message (room, hash, entry);
607 break;
608 case GNUNET_MESSENGER_KIND_TRANSCRIPT:
609 handle_transcript_message (room, hash, entry);
423 break; 610 break;
424 default: 611 default:
425 break; 612 break;
426 } 613 }
427 614
428 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new (struct 615 if (entry->flags & GNUNET_MESSENGER_FLAG_UPDATE)
429 GNUNET_MESSENGER_RoomMessageEntry); 616 callback_room_message (room, hash);
617}
618
619
620void
621handle_room_message (struct GNUNET_MESSENGER_Room *room,
622 struct GNUNET_MESSENGER_Contact *sender,
623 const struct GNUNET_MESSENGER_Message *message,
624 const struct GNUNET_HashCode *hash,
625 enum GNUNET_MESSENGER_MessageFlags flags)
626{
627 GNUNET_assert ((room) && (message) && (hash));
628
629 struct GNUNET_MESSENGER_RoomMessageEntry *entry;
630 entry = GNUNET_CONTAINER_multihashmap_get (room->messages, hash);
631
632 if (entry)
633 goto update_entry;
634
635 entry = GNUNET_new (struct GNUNET_MESSENGER_RoomMessageEntry);
430 636
431 if (! entry) 637 if (! entry)
432 return sender; 638 return;
433 639
434 entry->sender = sender; 640 entry->sender = NULL;
435 entry->recipient = recipient; 641 entry->recipient = NULL;
436 entry->message = copy_message (message); 642
643 entry->message = NULL;
644 entry->flags = GNUNET_MESSENGER_FLAG_NONE;
437 645
438 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, 646 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash,
439 entry, 647 entry,
440 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 648 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
441 { 649 {
442 destroy_message (entry->message);
443 GNUNET_free (entry); 650 GNUNET_free (entry);
651 return;
652 }
653
654update_entry:
655 entry->sender = sender;
656 entry->flags = flags;
657
658 if (entry->message)
659 {
660 enum GNUNET_MESSENGER_MessageKind kind = message->header.kind;
661 memcpy (&(entry->message->header), &(message->header),
662 sizeof(struct GNUNET_MESSENGER_MessageHeader));
663 entry->message->header.kind = kind;
444 } 664 }
665 else
666 entry->message = copy_message (message);
667
668 handle_message (room, hash, entry);
669}
445 670
446 if (flags & GNUNET_MESSENGER_FLAG_RECENT)
447 GNUNET_memcpy (&(room->last_message), hash, sizeof(room->last_message));
448 671
449 return sender; 672void
673update_room_last_message (struct GNUNET_MESSENGER_Room *room,
674 const struct GNUNET_HashCode *hash)
675{
676 GNUNET_assert ((room) && (hash));
677
678 GNUNET_memcpy (&(room->last_message), hash, sizeof(room->last_message));
450} 679}
451 680
452 681
diff --git a/src/service/messenger/messenger_api_room.h b/src/service/messenger/messenger_api_room.h
index 79571bc2e..7587fb256 100644
--- a/src/service/messenger/messenger_api_room.h
+++ b/src/service/messenger/messenger_api_room.h
@@ -40,7 +40,9 @@ struct GNUNET_MESSENGER_RoomMessageEntry
40{ 40{
41 struct GNUNET_MESSENGER_Contact *sender; 41 struct GNUNET_MESSENGER_Contact *sender;
42 struct GNUNET_MESSENGER_Contact *recipient; 42 struct GNUNET_MESSENGER_Contact *recipient;
43
43 struct GNUNET_MESSENGER_Message *message; 44 struct GNUNET_MESSENGER_Message *message;
45 enum GNUNET_MESSENGER_MessageFlags flags;
44}; 46};
45 47
46struct GNUNET_MESSENGER_Room 48struct GNUNET_MESSENGER_Room
@@ -153,6 +155,16 @@ get_room_recipient (const struct GNUNET_MESSENGER_Room *room,
153 const struct GNUNET_HashCode *hash); 155 const struct GNUNET_HashCode *hash);
154 156
155/** 157/**
158 * Executes the message callback for a given <i>hash</i> in a <i>room</i>.
159 *
160 * @param[in,out] room Room
161 * @param[in] hash Hash of message
162 */
163void
164callback_room_message (struct GNUNET_MESSENGER_Room *room,
165 const struct GNUNET_HashCode *hash);
166
167/**
156 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update 168 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
157 * members and its information. The function also stores the message in map locally for access afterwards. 169 * members and its information. The function also stores the message in map locally for access afterwards.
158 * 170 *
@@ -161,21 +173,29 @@ get_room_recipient (const struct GNUNET_MESSENGER_Room *room,
161 * 173 *
162 * @param[in,out] room Room 174 * @param[in,out] room Room
163 * @param[in,out] sender Contact of sender 175 * @param[in,out] sender Contact of sender
164 * @param[in,out] recipient Contact of recipient
165 * @param[in] message Message 176 * @param[in] message Message
166 * @param[in] hash Hash of message 177 * @param[in] hash Hash of message
167 * @param[in] flags Flags of message 178 * @param[in] flags Flags of message
168 * @return Contact of sender
169 */ 179 */
170struct GNUNET_MESSENGER_Contact* 180void
171handle_room_message (struct GNUNET_MESSENGER_Room *room, 181handle_room_message (struct GNUNET_MESSENGER_Room *room,
172 struct GNUNET_MESSENGER_Contact *sender, 182 struct GNUNET_MESSENGER_Contact *sender,
173 struct GNUNET_MESSENGER_Contact *recipient,
174 const struct GNUNET_MESSENGER_Message *message, 183 const struct GNUNET_MESSENGER_Message *message,
175 const struct GNUNET_HashCode *hash, 184 const struct GNUNET_HashCode *hash,
176 enum GNUNET_MESSENGER_MessageFlags flags); 185 enum GNUNET_MESSENGER_MessageFlags flags);
177 186
178/** 187/**
188 * Updates the last message <i>hash</i> of a <i>room</i> for the client API so that new messages can
189 * point to the latest message hash while sending.
190 *
191 * @param[in,out] room Room
192 * @param[in] hash Hash of message
193 */
194void
195update_room_last_message (struct GNUNET_MESSENGER_Room *room,
196 const struct GNUNET_HashCode *hash);
197
198/**
179 * Iterates through all members of a given <i>room</i> to forward each of them to a selected 199 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
180 * <i>callback</i> with a custom closure. 200 * <i>callback</i> with a custom closure.
181 * 201 *