aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--po/POTFILES.in2
-rw-r--r--src/include/gnunet_messenger_service.h240
-rw-r--r--src/messenger/.gitignore10
-rw-r--r--src/messenger/Makefile.am136
-rw-r--r--src/messenger/gnunet-messenger.c132
-rw-r--r--src/messenger/gnunet-service-messenger.c148
-rw-r--r--src/messenger/gnunet-service-messenger.h20
-rw-r--r--src/messenger/gnunet-service-messenger_basement.c4
-rw-r--r--src/messenger/gnunet-service-messenger_basement.h24
-rw-r--r--src/messenger/gnunet-service-messenger_contact.c96
-rw-r--r--src/messenger/gnunet-service-messenger_contact.h112
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c295
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h152
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c449
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h120
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c16
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.h42
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.c76
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.h42
-rw-r--r--src/messenger/gnunet-service-messenger_member.c379
-rw-r--r--src/messenger/gnunet-service-messenger_member.h170
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c707
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h275
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c250
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.h151
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c108
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.h100
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.c69
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.h58
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c206
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.h128
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c89
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h121
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.c360
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.h92
-rw-r--r--src/messenger/gnunet-service-messenger_operation.c214
-rw-r--r--src/messenger/gnunet-service-messenger_operation.h129
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.c224
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.h131
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1092
-rw-r--r--src/messenger/gnunet-service-messenger_room.h265
-rw-r--r--src/messenger/gnunet-service-messenger_service.c306
-rw-r--r--src/messenger/gnunet-service-messenger_service.h162
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c233
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h104
-rw-r--r--src/messenger/messenger_api.c264
-rw-r--r--src/messenger/messenger_api_contact.c44
-rw-r--r--src/messenger/messenger_api_contact.h45
-rw-r--r--src/messenger/messenger_api_contact_store.c182
-rw-r--r--src/messenger/messenger_api_contact_store.h122
-rw-r--r--src/messenger/messenger_api_ego.h2
-rw-r--r--src/messenger/messenger_api_handle.c99
-rw-r--r--src/messenger/messenger_api_handle.h69
-rw-r--r--src/messenger/messenger_api_list_tunnels.c74
-rw-r--r--src/messenger/messenger_api_list_tunnels.h44
-rw-r--r--src/messenger/messenger_api_message.c423
-rw-r--r--src/messenger/messenger_api_message.h119
-rw-r--r--src/messenger/messenger_api_room.c214
-rw-r--r--src/messenger/messenger_api_room.h54
-rw-r--r--src/messenger/messenger_api_util.c (renamed from src/messenger/gnunet-service-messenger_util.c)30
-rw-r--r--src/messenger/messenger_api_util.h (renamed from src/messenger/gnunet-service-messenger_util.h)27
-rw-r--r--src/messenger/test_messenger.c40
-rw-r--r--src/messenger/test_messenger_adapt.c47
-rw-r--r--src/messenger/test_messenger_anonymous.c34
-rw-r--r--src/messenger/test_messenger_api.conf32
-rw-r--r--src/messenger/test_messenger_async_client.c47
-rw-r--r--src/messenger/test_messenger_async_p2p.c47
-rw-r--r--src/messenger/test_messenger_comm0.c252
-rw-r--r--src/messenger/test_messenger_growth.c47
-rw-r--r--src/messenger/test_messenger_ring.c47
-rw-r--r--src/messenger/test_messenger_server.c47
-rw-r--r--src/messenger/test_messenger_sync_client.c47
-rw-r--r--src/messenger/test_messenger_sync_p2p.c47
-rw-r--r--src/messenger/test_messenger_worst_client.c47
-rw-r--r--src/messenger/test_messenger_worst_p2p.c47
-rw-r--r--src/messenger/testing_messenger_barrier.c170
-rw-r--r--src/messenger/testing_messenger_barrier.h131
-rw-r--r--src/messenger/testing_messenger_setup.c528
-rw-r--r--src/messenger/testing_messenger_setup.h39
79 files changed, 8653 insertions, 3094 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 51ada43b3..b2fa88d73 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -550,5 +550,7 @@ src/vpn/vpn_api.c
550src/zonemaster/gnunet-service-zonemaster-monitor.c 550src/zonemaster/gnunet-service-zonemaster-monitor.c
551src/zonemaster/gnunet-service-zonemaster.c 551src/zonemaster/gnunet-service-zonemaster.c
552src/fs/fs_api.h 552src/fs/fs_api.h
553src/include/gnunet_identity_service.h
554src/include/gnunet_messenger_service.h
553src/testbed/testbed_api.h 555src/testbed/testbed_api.h
554src/testbed/testbed_api_operations.h 556src/testbed/testbed_api_operations.h
diff --git a/src/include/gnunet_messenger_service.h b/src/include/gnunet_messenger_service.h
index 389b6b8fd..99d4cf267 100644
--- a/src/include/gnunet_messenger_service.h
+++ b/src/include/gnunet_messenger_service.h
@@ -48,6 +48,14 @@ extern "C" {
48#include "gnunet_scheduler_lib.h" 48#include "gnunet_scheduler_lib.h"
49#include "gnunet_time_lib.h" 49#include "gnunet_time_lib.h"
50 50
51/**
52 * Version number of GNUnet Messenger API.
53 */
54#define GNUNET_MESSENGER_VERSION 0x00000001
55
56/**
57 * Identifier of GNUnet MESSENGER Service.
58 */
51#define GNUNET_MESSENGER_SERVICE_NAME "messenger" 59#define GNUNET_MESSENGER_SERVICE_NAME "messenger"
52 60
53/** 61/**
@@ -141,11 +149,18 @@ enum GNUNET_MESSENGER_MessageKind
141 GNUNET_MESSENGER_KIND_PRIVATE = 14, 149 GNUNET_MESSENGER_KIND_PRIVATE = 14,
142 150
143 /** 151 /**
152 * The delete kind. The message contains a #GNUNET_MESSENGER_MessageDelete body.
153 */
154 GNUNET_MESSENGER_KIND_DELETE = 15,
155
156 /**
144 * The unknown kind. The message contains an unknown body. 157 * The unknown kind. The message contains an unknown body.
145 */ 158 */
146 GNUNET_MESSENGER_KIND_UNKNOWN = 0 159 GNUNET_MESSENGER_KIND_UNKNOWN = 0
147}; 160};
148 161
162#define GNUNET_MESSENGER_KIND_MAX (GNUNET_MESSENGER_KIND_DELETE)
163
149/** 164/**
150 * Get the name of a message <i>kind</i>. 165 * Get the name of a message <i>kind</i>.
151 * 166 *
@@ -157,6 +172,9 @@ GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind);
157 172
158/** 173/**
159 * The header of a #GNUNET_MESSENGER_Message. 174 * The header of a #GNUNET_MESSENGER_Message.
175 * This allows authentification of the sender, temporal ordering and finding potentially missed messages.
176 *
177 * Message-header-size: 40+ bytes
160 */ 178 */
161struct GNUNET_MESSENGER_MessageHeader 179struct GNUNET_MESSENGER_MessageHeader
162{ 180{
@@ -188,6 +206,9 @@ struct GNUNET_MESSENGER_MessageHeader
188 206
189/** 207/**
190 * An info message body. 208 * An info message body.
209 * This allows ensuring member ids are unique and this first message can be verified.
210 *
211 * Message-body-size: 8+ bytes
191 */ 212 */
192struct GNUNET_MESSENGER_MessageInfo 213struct GNUNET_MESSENGER_MessageInfo
193{ 214{
@@ -197,13 +218,16 @@ struct GNUNET_MESSENGER_MessageInfo
197 struct GNUNET_IDENTITY_PublicKey host_key; 218 struct GNUNET_IDENTITY_PublicKey host_key;
198 219
199 /** 220 /**
200 * The new unique id for the receiver in a room. 221 * The version of GNUnet Messenger API.
201 */ 222 */
202 struct GNUNET_ShortHashCode unique_id; 223 uint32_t messenger_version;
203}; 224};
204 225
205/** 226/**
206 * A join message body. 227 * A join message body.
228 * This allows informing others about joining the room with a given key pair.
229 *
230 * Message-body-size: 4+ bytes
207 */ 231 */
208struct GNUNET_MESSENGER_MessageJoin 232struct GNUNET_MESSENGER_MessageJoin
209{ 233{
@@ -215,6 +239,9 @@ struct GNUNET_MESSENGER_MessageJoin
215 239
216/** 240/**
217 * A leave message body. 241 * A leave message body.
242 * This allows informing others about leaving the room.
243 *
244 * Message-body-size: 0 bytes
218 */ 245 */
219struct GNUNET_MESSENGER_MessageLeave 246struct GNUNET_MESSENGER_MessageLeave
220{ 247{
@@ -222,6 +249,9 @@ struct GNUNET_MESSENGER_MessageLeave
222 249
223/** 250/**
224 * A name message body. 251 * A name message body.
252 * This allows replacing the current name with another one.
253 *
254 * Message-body-size: 0+ bytes
225 */ 255 */
226struct GNUNET_MESSENGER_MessageName 256struct GNUNET_MESSENGER_MessageName
227{ 257{
@@ -233,6 +263,9 @@ struct GNUNET_MESSENGER_MessageName
233 263
234/** 264/**
235 * A key message body. 265 * A key message body.
266 * This allows replacing the current key pair with another one.
267 *
268 * Message-body-size: 4+ bytes
236 */ 269 */
237struct GNUNET_MESSENGER_MessageKey 270struct GNUNET_MESSENGER_MessageKey
238{ 271{
@@ -244,6 +277,9 @@ struct GNUNET_MESSENGER_MessageKey
244 277
245/** 278/**
246 * A peer message body. 279 * A peer message body.
280 * This allows informing others to open a peer as a door to the current room.
281 *
282 * Message-body-size: 32 bytes
247 */ 283 */
248struct GNUNET_MESSENGER_MessagePeer 284struct GNUNET_MESSENGER_MessagePeer
249{ 285{
@@ -255,6 +291,9 @@ struct GNUNET_MESSENGER_MessagePeer
255 291
256/** 292/**
257 * An id message body. 293 * An id message body.
294 * This allows replacing the member id with a newly unique generated one.
295 *
296 * Message-body-size: 8 bytes
258 */ 297 */
259struct GNUNET_MESSENGER_MessageId 298struct GNUNET_MESSENGER_MessageId
260{ 299{
@@ -266,6 +305,9 @@ struct GNUNET_MESSENGER_MessageId
266 305
267/** 306/**
268 * A miss message body. 307 * A miss message body.
308 * This allows informing others about a disconnection of any door.
309 *
310 * Message-body-size: 32 bytes
269 */ 311 */
270struct GNUNET_MESSENGER_MessageMiss 312struct GNUNET_MESSENGER_MessageMiss
271{ 313{
@@ -277,6 +319,9 @@ struct GNUNET_MESSENGER_MessageMiss
277 319
278/** 320/**
279 * A merge message body. 321 * A merge message body.
322 * This allows merging message history branches together.
323 *
324 * Message-body-size: 16 bytes
280 */ 325 */
281struct GNUNET_MESSENGER_MessageMerge 326struct GNUNET_MESSENGER_MessageMerge
282{ 327{
@@ -288,6 +333,9 @@ struct GNUNET_MESSENGER_MessageMerge
288 333
289/** 334/**
290 * A request message body. 335 * A request message body.
336 * This allows requesting the content of a specific message which is currently missing.
337 *
338 * Message-body-size: 16 bytes
291 */ 339 */
292struct GNUNET_MESSENGER_MessageRequest 340struct GNUNET_MESSENGER_MessageRequest
293{ 341{
@@ -299,6 +347,9 @@ struct GNUNET_MESSENGER_MessageRequest
299 347
300/** 348/**
301 * An invite message body. 349 * An invite message body.
350 * This allows sharing information about other rooms in form of an invitation.
351 *
352 * Message-body-size: 48 bytes
302 */ 353 */
303struct GNUNET_MESSENGER_MessageInvite 354struct GNUNET_MESSENGER_MessageInvite
304{ 355{
@@ -315,6 +366,9 @@ struct GNUNET_MESSENGER_MessageInvite
315 366
316/** 367/**
317 * A text message body. 368 * A text message body.
369 * This allows general communication in text form.
370 *
371 * Message-body-size: 0+ bytes
318 */ 372 */
319struct GNUNET_MESSENGER_MessageText 373struct GNUNET_MESSENGER_MessageText
320{ 374{
@@ -326,6 +380,9 @@ struct GNUNET_MESSENGER_MessageText
326 380
327/** 381/**
328 * A file message body. 382 * A file message body.
383 * This allows sending necessary details about an uploaded encrypted file to allow access to it.
384 *
385 * Message-body-size: 335+ bytes
329 */ 386 */
330struct GNUNET_MESSENGER_MessageFile 387struct GNUNET_MESSENGER_MessageFile
331{ 388{
@@ -352,6 +409,9 @@ struct GNUNET_MESSENGER_MessageFile
352 409
353/** 410/**
354 * A private message body. 411 * A private message body.
412 * This allows to encapsulate any message to be encrypted for only one specific member to receive in a room.
413 *
414 * Message-body-size: 32+ bytes
355 */ 415 */
356struct GNUNET_MESSENGER_MessagePrivate 416struct GNUNET_MESSENGER_MessagePrivate
357{ 417{
@@ -372,6 +432,25 @@ struct GNUNET_MESSENGER_MessagePrivate
372}; 432};
373 433
374/** 434/**
435 * A delete message body
436 * This allows deletion of an own previous message with any custom automatic delay.
437 *
438 * Message-body-size: 24 bytes
439 */
440struct GNUNET_MESSENGER_MessageDelete
441{
442 /**
443 * The hash of the message to delete.
444 */
445 struct GNUNET_HashCode hash;
446
447 /**
448 * The delay of the delete operation to get processed.
449 */
450 struct GNUNET_TIME_RelativeNBO delay;
451};
452
453/**
375 * The unified body of a #GNUNET_MESSENGER_Message. 454 * The unified body of a #GNUNET_MESSENGER_Message.
376 */ 455 */
377struct GNUNET_MESSENGER_MessageBody 456struct GNUNET_MESSENGER_MessageBody
@@ -392,6 +471,7 @@ struct GNUNET_MESSENGER_MessageBody
392 struct GNUNET_MESSENGER_MessageText text; 471 struct GNUNET_MESSENGER_MessageText text;
393 struct GNUNET_MESSENGER_MessageFile file; 472 struct GNUNET_MESSENGER_MessageFile file;
394 struct GNUNET_MESSENGER_MessagePrivate private; 473 struct GNUNET_MESSENGER_MessagePrivate private;
474 struct GNUNET_MESSENGER_MessageDelete delete;
395 }; 475 };
396}; 476};
397 477
@@ -412,11 +492,27 @@ struct GNUNET_MESSENGER_Message
412}; 492};
413 493
414/** 494/**
495 * Enum for the different supported flags used by message handling
496 */
497enum GNUNET_MESSENGER_MessageFlags
498{
499 /**
500 * The none flag. The flag indicates that the message is not affected by any special context.
501 */
502 GNUNET_MESSENGER_FLAG_NONE = 0,
503
504 /**
505 * The private flag. The flag indicates that the message was privately encrypted.
506 */
507 GNUNET_MESSENGER_FLAG_PRIVATE = 1,
508};
509
510/**
415 * Method called whenever the EGO of a <i>handle</i> changes or if the first connection fails 511 * Method called whenever the EGO of a <i>handle</i> changes or if the first connection fails
416 * to load a valid EGO and the anonymous key pair will be used instead. 512 * to load a valid EGO and the anonymous key pair will be used instead.
417 * 513 *
418 * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> 514 * @param[in/out] cls Closure from #GNUNET_MESSENGER_connect
419 * @param handle Messenger handle 515 * @param[in/out] handle Messenger handle
420 */ 516 */
421typedef void 517typedef void
422(*GNUNET_MESSENGER_IdentityCallback) (void *cls, struct GNUNET_MESSENGER_Handle *handle); 518(*GNUNET_MESSENGER_IdentityCallback) (void *cls, struct GNUNET_MESSENGER_Handle *handle);
@@ -424,25 +520,45 @@ typedef void
424/** 520/**
425 * Method called whenever a message is sent or received from a <i>room</i>. 521 * Method called whenever a message is sent or received from a <i>room</i>.
426 * 522 *
427 * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> 523 * The flag <i>private_message</i> will be #GNUNET_YES if a message was
428 * @param room Room handle 524 * received privately, otherwise #GNUNET_NO.
429 * @param message Newly received or sent message 525 *
430 * @param hash Hash identifying the message 526 * @param[in/out] cls Closure from #GNUNET_MESSENGER_connect
527 * @param[in] room Room handle
528 * @param[in] sender Sender of message
529 * @param[in] message Newly received or sent message
530 * @param[in] hash Hash identifying the message
531 * @param[in] flags Flags of the message
431 */ 532 */
432typedef void 533typedef void
433(*GNUNET_MESSENGER_MessageCallback) (void *cls, const struct GNUNET_MESSENGER_Room *room, 534(*GNUNET_MESSENGER_MessageCallback) (void *cls, struct GNUNET_MESSENGER_Room *room,
434 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 535 const struct GNUNET_MESSENGER_Contact *sender,
536 const struct GNUNET_MESSENGER_Message *message,
537 const struct GNUNET_HashCode *hash,
538 enum GNUNET_MESSENGER_MessageFlags flags);
539
540/**
541 * Method called for each member in a <i>room</i> during iteration. If the method returns
542 * #GNUNET_YES the iteration continues, otherwise it will quit the iteration.
543 *
544 * @param[in/out] cls Closure from #GNUNET_MESSENGER_iterate_members
545 * @param[in] room Room handle
546 * @param[in] contact Contact handle
547 */
548typedef int
549(*GNUNET_MESSENGER_MemberCallback) (void* cls, struct GNUNET_MESSENGER_Room *room,
550 const struct GNUNET_MESSENGER_Contact *contact);
435 551
436/** 552/**
437 * Set up a handle for the messenger related functions and connects to all necessary services. It will look up the ego 553 * Set up a handle for the messenger related functions and connects to all necessary services. It will look up the ego
438 * key identified by its <i>name</i> and use it for signing all messages from the handle. 554 * key identified by its <i>name</i> and use it for signing all messages from the handle.
439 * 555 *
440 * @param cfg Configuration to use 556 * @param[in] cfg Configuration to use
441 * @param name Name to look up an ego or NULL to stay anonymous 557 * @param[in] name Name to look up an ego or NULL to stay anonymous
442 * @param identity_callback Function called when the EGO of the handle changes 558 * @param[in] identity_callback Function called when the EGO of the handle changes
443 * @param identity_cls Closure for the <i>identity_callback</i> handler 559 * @param[in/out] identity_cls Closure for the <i>identity_callback</i> handler
444 * @param msg_callback Function called when a new message is sent or received 560 * @param[in] msg_callback Function called when a new message is sent or received
445 * @param msg_cls Closure for the <i>msg_callback</i> handler 561 * @param[in/out] msg_cls Closure for the <i>msg_callback</i> handler
446 * @return Messenger handle to use, NULL on error 562 * @return Messenger handle to use, NULL on error
447 */ 563 */
448struct GNUNET_MESSENGER_Handle* 564struct GNUNET_MESSENGER_Handle*
@@ -458,8 +574,8 @@ GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const c
458 * Keep in mind that this will fully delete the old ego key (if any is used) even if any other service wants to use it 574 * Keep in mind that this will fully delete the old ego key (if any is used) even if any other service wants to use it
459 * as default. 575 * as default.
460 * 576 *
461 * @param handle Messenger handle to use 577 * @param[in/out] handle Messenger handle to use
462 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 578 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
463 */ 579 */
464int 580int
465GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle); 581GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle);
@@ -467,7 +583,7 @@ GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle);
467/** 583/**
468 * Disconnect all of the messengers used services and clears up its used memory. 584 * Disconnect all of the messengers used services and clears up its used memory.
469 * 585 *
470 * @param handle Messenger handle to use 586 * @param[in/out] handle Messenger handle to use
471 */ 587 */
472void 588void
473GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle); 589GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle);
@@ -475,7 +591,7 @@ GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle);
475/** 591/**
476 * Get the name (if specified, otherwise NULL) used by the messenger. 592 * Get the name (if specified, otherwise NULL) used by the messenger.
477 * 593 *
478 * @param handle Messenger handle to use 594 * @param[in] handle Messenger handle to use
479 * @return Name used by the messenger or NULL 595 * @return Name used by the messenger or NULL
480 */ 596 */
481const char* 597const char*
@@ -483,21 +599,21 @@ GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle);
483 599
484/** 600/**
485 * Set the name for the messenger. This will rename the currently used ego and move all stored files related to the current 601 * Set the name for the messenger. This will rename the currently used ego and move all stored files related to the current
486 * name to its new directory. If anything fails during this process the function returns GNUNET_NO and the name for 602 * name to its new directory. If anything fails during this process the function returns #GNUNET_NO and the name for
487 * the messenger won't change as specified. 603 * the messenger won't change as specified.
488 * 604 *
489 * @param handle Messenger handle to use 605 * @param[in/out] handle Messenger handle to use
490 * @param name Name for the messenger to change to 606 * @param[in] name Name for the messenger to change to
491 * @return GNUNET_YES on success, GNUNET_NO on failure and GNUNET_SYSERR if <i>handle</i> is NULL 607 * @return #GNUNET_YES on success, #GNUNET_NO on failure and #GNUNET_SYSERR if <i>handle</i> is NULL
492 */ 608 */
493int 609int
494GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); 610GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
495 611
496/** 612/**
497 * Get the public key used by the messenger. 613 * Get the public key used by the messenger or NULL if the anonymous key was used.
498 * 614 *
499 * @param handle Messenger handle to use 615 * @param[in] handle Messenger handle to use
500 * @return Used ego's public key 616 * @return Used ego's public key or NULL
501 */ 617 */
502const struct GNUNET_IDENTITY_PublicKey* 618const struct GNUNET_IDENTITY_PublicKey*
503GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle); 619GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle);
@@ -509,38 +625,38 @@ GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle);
509 * Notice that there can only be one room related to a specific <i>key</i>. So trying to open two rooms with the same 625 * Notice that there can only be one room related to a specific <i>key</i>. So trying to open two rooms with the same
510 * <i>key</i> will result in opening the room once but returning the handle both times because the room stays open. 626 * <i>key</i> will result in opening the room once but returning the handle both times because the room stays open.
511 * 627 *
512 * You can also open a room after entering it through a <b>door</b> using <i>GNUNET_MESSENGER_entry_room(...)</i>. This 628 * You can also open a room after entering it through a <b>door</b> using #GNUNET_MESSENGER_enter_room. This
513 * will notify all entered <b>doors</b> to list you as new <b>door</b>. 629 * will notify all entered <b>doors</b> to list you as new <b>door</b>.
514 * 630 *
515 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) 631 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. )
516 * 632 *
517 * @param handle Messenger handle to use 633 * @param[in/out] handle Messenger handle to use
518 * @param key Hash identifying the port 634 * @param[in] key Hash identifying the port
519 * @return Room handle, NULL on error 635 * @return Room handle, NULL on error
520 */ 636 */
521struct GNUNET_MESSENGER_Room* 637struct GNUNET_MESSENGER_Room*
522GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 638GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
523 639
524/** 640/**
525 * Enter a room to send and receive messages through a <b>door</b> opened using <i>GNUNET_MESSENGER_open_room(...)</i>. 641 * Enter a room to send and receive messages through a <b>door</b> opened using #GNUNET_MESSENGER_open_room.
526 * 642 *
527 * Notice that there can only be one room related to a specific <i>key</i>. So trying to enter two rooms with the same 643 * Notice that there can only be one room related to a specific <i>key</i>. So trying to enter two rooms with the same
528 * <i>key</i> will result in entering the room once but returning the handle both times because the room stays entered. 644 * <i>key</i> will result in entering the room once but returning the handle both times because the room stays entered.
529 * You can however enter a room through multiple <b>doors</b> in parallel which results in connecting both ends. But 645 * You can however enter a room through multiple <b>doors</b> in parallel which results in connecting both ends. But
530 * entering the room through the same <b>door</b> won't have any effect after the first time. 646 * entering the room through the same <b>door</b> won't have any effect after the first time.
531 * 647 *
532 * You can also enter a room through a <b>door</b> after opening it using <i>GNUNET_MESSENGER_open_room(...)</i>. But the 648 * You can also enter a room through a <b>door</b> after opening it using #GNUNET_MESSENGER_open_room. But the
533 * <b>door</b> may not be your own peer identity. 649 * <b>door</b> may not be your own peer identity.
534 * 650 *
535 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) 651 * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. )
536 * 652 *
537 * @param handle Messenger handle to use 653 * @param[in/out] handle Messenger handle to use
538 * @param door Peer identity of an open <b>door</b> 654 * @param[in] door Peer identity of an open <b>door</b>
539 * @param key Hash identifying the port 655 * @param[in] key Hash identifying the port
540 * @return Room handle, NULL on error 656 * @return Room handle, NULL on error
541 */ 657 */
542struct GNUNET_MESSENGER_Room* 658struct GNUNET_MESSENGER_Room*
543GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 659GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
544 const struct GNUNET_HashCode *key); 660 const struct GNUNET_HashCode *key);
545 661
546/** 662/**
@@ -550,37 +666,37 @@ GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struc
550 * ( After a member closes a <b>door</b>, all members entered through that specific <b>door</b> have to use another one 666 * ( After a member closes a <b>door</b>, all members entered through that specific <b>door</b> have to use another one
551 * or open the room on their own. ) 667 * or open the room on their own. )
552 * 668 *
553 * @param room Room handle 669 * @param[in/out] room Room handle
554 */ 670 */
555void 671void
556GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room); 672GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room);
557 673
558/** 674/**
559 * Get the contact of a member in a <i>room</i> identified by their <i>id</i>. 675 * Get the contact of a member in a <i>room</i> which sent a specific message identified with a given <i>hash</i>.
560 * 676 *
561 * Notice that contacts are independent of rooms but will be removed if all rooms containing these contacts get closed. 677 * Notice that contacts are independent of rooms but will be removed if all rooms containing these contacts get closed.
562 * 678 *
563 * @param room Room handle 679 * @param[in] room Room handle
564 * @param id Hash identifying a member 680 * @param[in] hash Hash identifying a message
565 * @return Contact handle, NULL if <i>id</i> is not in use 681 * @return Contact handle, NULL otherwise
566 */ 682 */
567struct GNUNET_MESSENGER_Contact* 683struct GNUNET_MESSENGER_Contact*
568GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id); 684GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
569 685
570/** 686/**
571 * Get the name used by the <i>contact</i>. 687 * Get the name used by the <i>contact</i>.
572 * 688 *
573 * @param contact Contact handle 689 * @param[in] contact Contact handle
574 * @return Name of <i>contact</i> or NULL 690 * @return Name of <i>contact</i> or NULL
575 */ 691 */
576const char* 692const char*
577GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact); 693GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact);
578 694
579/** 695/**
580 * Get the public key used by the <i>contact</i>. 696 * Get the public key used by the <i>contact</i> or NULL if the anonymous key was used.
581 * 697 *
582 * @param contact Contact handle 698 * @param[in] contact Contact handle
583 * @return Public key of the ego used by <i>contact</i> 699 * @return Public key of the ego used by <i>contact</i> or NULL
584 */ 700 */
585const struct GNUNET_IDENTITY_PublicKey* 701const struct GNUNET_IDENTITY_PublicKey*
586GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact); 702GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact);
@@ -593,22 +709,44 @@ GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact
593 * 709 *
594 * Notice that all messages sent and received are also stored and can be propagated to new members entering the room. 710 * Notice that all messages sent and received are also stored and can be propagated to new members entering the room.
595 * 711 *
596 * @param room Room handle 712 * If you provide a specific <i>contact</i> as receiver of the given message, the message will automatically be
597 * @param message New message to send 713 * encrypted and sent as a private message (see #GNUNET_MESSENGER_MessagePrivate). Therefore the selected contact
714 * will be the only member receiving the actual message.
715 *
716 * Sending a message to all members in a given room can be done by providing NULL as contact.
717 *
718 * @param[in/out] room Room handle
719 * @param[in] message New message to send
720 * @param[in] contact Contact or NULL
598 */ 721 */
599void 722void
600GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message); 723GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
724 const struct GNUNET_MESSENGER_Contact* contact);
601 725
602/** 726/**
603 * Get the message in a <i>room</i> identified by its <i>hash</i>. 727 * Get the message in a <i>room</i> identified by its <i>hash</i>.
604 * 728 *
605 * @param room Room handle 729 * @param[in] room Room handle
606 * @param hash Hash identifying a message 730 * @param[in] hash Hash identifying a message
607 * @return Message struct or NULL if no message with that hash is known 731 * @return Message struct or NULL if no message with that hash is known
608 */ 732 */
609const struct GNUNET_MESSENGER_Message* 733const struct GNUNET_MESSENGER_Message*
610GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); 734GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
611 735
736/**
737 * Iterates through all members of a given <i>room</i> and calls a selected <i>callback</i>
738 * for each of them with a provided closure. The callback will receive the contact of each
739 * member. The function returns the amount of members iterated with the given callback.
740 *
741 * @param[in] room Room handle
742 * @param[in] callback Function called for each member
743 * @param[in] cls Closure for the <i>callback</i> handler
744 * @return Amount of members iterated
745 */
746int
747GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
748 void* cls);
749
612#if 0 /* keep Emacsens' auto-indent happy */ 750#if 0 /* keep Emacsens' auto-indent happy */
613{ 751{
614#endif 752#endif
diff --git a/src/messenger/.gitignore b/src/messenger/.gitignore
index 9de3fb304..ed78c5562 100644
--- a/src/messenger/.gitignore
+++ b/src/messenger/.gitignore
@@ -2,3 +2,13 @@ gnunet-service-messenger
2gnunet-messenger 2gnunet-messenger
3test_messenger_api 3test_messenger_api
4test_messenger_anonymous 4test_messenger_anonymous
5test_messenger_sync_client
6test_messenger_async_client
7test_messenger_worst_client
8test_messenger_sync_p2p
9test_messenger_async_p2p
10test_messenger_worst_p2p
11test_messenger_server
12test_messenger_growth
13test_messenger_ring
14test_messenger_adapt
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am
index d9694420b..1ebfbe5ed 100644
--- a/src/messenger/Makefile.am
+++ b/src/messenger/Makefile.am
@@ -31,10 +31,14 @@ lib_LTLIBRARIES = \
31 31
32libgnunetmessenger_common_la_SOURCES = \ 32libgnunetmessenger_common_la_SOURCES = \
33 messenger_api_ego.h \ 33 messenger_api_ego.h \
34 messenger_api_contact.c messenger_api_contact.h \
35 messenger_api_contact_store.c messenger_api_contact_store.h \
34 messenger_api_message.c messenger_api_message.h \ 36 messenger_api_message.c messenger_api_message.h \
35 messenger_api_list_tunnels.c messenger_api_list_tunnels.h 37 messenger_api_list_tunnels.c messenger_api_list_tunnels.h \
38 messenger_api_util.c messenger_api_util.h
36libgnunetmessenger_common_la_LIBADD = \ 39libgnunetmessenger_common_la_LIBADD = \
37 $(top_builddir)/src/util/libgnunetutil.la \ 40 $(top_builddir)/src/util/libgnunetutil.la \
41 $(top_builddir)/src/cadet/libgnunetcadet.la \
38 $(top_builddir)/src/identity/libgnunetidentity.la \ 42 $(top_builddir)/src/identity/libgnunetidentity.la \
39 $(XLIB) \ 43 $(XLIB) \
40 $(LTLIBINTL) 44 $(LTLIBINTL)
@@ -44,7 +48,6 @@ libgnunetmessenger_common_la_LDFLAGS = \
44 48
45libgnunetmessenger_la_SOURCES = \ 49libgnunetmessenger_la_SOURCES = \
46 messenger_api.c \ 50 messenger_api.c \
47 messenger_api_contact.c messenger_api_contact.h \
48 messenger_api_handle.c messenger_api_handle.h \ 51 messenger_api_handle.c messenger_api_handle.h \
49 messenger_api_room.c messenger_api_room.h 52 messenger_api_room.c messenger_api_room.h
50libgnunetmessenger_la_LIBADD = \ 53libgnunetmessenger_la_LIBADD = \
@@ -72,17 +75,21 @@ gnunet_service_messenger_SOURCES = \
72 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \ 75 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \
73 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \ 76 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \
74 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \ 77 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \
78 gnunet-service-messenger_member_session.c gnunet-service-messenger_member_session.h \
79 gnunet-service-messenger_member.c gnunet-service-messenger_member.h \
80 gnunet-service-messenger_member_store.c gnunet-service-messenger_member_store.h \
75 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \ 81 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \
76 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \ 82 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \
77 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \ 83 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \
78 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \ 84 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \
79 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \ 85 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \
86 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \
87 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
80 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \ 88 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \
81 gnunet-service-messenger_contact.c gnunet-service-messenger_contact.h \ 89 gnunet-service-messenger_ego_store.c gnunet-service-messenger_ego_store.h \
82 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \ 90 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \
83 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \ 91 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \
84 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h \ 92 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h
85 gnunet-service-messenger_util.c gnunet-service-messenger_util.h
86gnunet_service_messenger_LDADD = \ 93gnunet_service_messenger_LDADD = \
87 $(top_builddir)/src/util/libgnunetutil.la \ 94 $(top_builddir)/src/util/libgnunetutil.la \
88 $(top_builddir)/src/cadet/libgnunetcadet.la \ 95 $(top_builddir)/src/cadet/libgnunetcadet.la \
@@ -94,7 +101,16 @@ gnunet_service_messenger_LDADD = \
94check_PROGRAMS = \ 101check_PROGRAMS = \
95 test_messenger_api \ 102 test_messenger_api \
96 test_messenger_anonymous \ 103 test_messenger_anonymous \
97 test_messenger_comm0 104 test_messenger_sync_client \
105 test_messenger_async_client \
106 test_messenger_worst_client \
107 test_messenger_sync_p2p \
108 test_messenger_async_p2p \
109 test_messenger_worst_p2p \
110 test_messenger_server \
111 test_messenger_growth \
112 test_messenger_ring \
113 test_messenger_adapt
98 114
99if ENABLE_TEST_RUN 115if ENABLE_TEST_RUN
100AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 116AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
@@ -118,13 +134,113 @@ test_messenger_anonymous_LDADD = \
118 $(top_builddir)/src/testing/libgnunettesting.la \ 134 $(top_builddir)/src/testing/libgnunettesting.la \
119 $(top_builddir)/src/util/libgnunetutil.la 135 $(top_builddir)/src/util/libgnunetutil.la
120 136
121test_messenger_comm0_SOURCES = \ 137test_messenger_sync_client_SOURCES = \
122 test_messenger_comm0.c 138 test_messenger_sync_client.c \
123test_messenger_comm0_LDADD = \ 139 testing_messenger_barrier.c testing_messenger_barrier.h \
140 testing_messenger_setup.c testing_messenger_setup.h
141test_messenger_sync_client_LDADD = \
142 libgnunetmessenger_common.la \
143 libgnunetmessenger.la \
144 $(top_builddir)/src/testbed/libgnunettestbed.la \
145 $(top_builddir)/src/testing/libgnunettesting.la \
146 $(top_builddir)/src/util/libgnunetutil.la
147
148test_messenger_async_client_SOURCES = \
149 test_messenger_async_client.c \
150 testing_messenger_barrier.c testing_messenger_barrier.h \
151 testing_messenger_setup.c testing_messenger_setup.h
152test_messenger_async_client_LDADD = \
153 libgnunetmessenger_common.la \
154 libgnunetmessenger.la \
155 $(top_builddir)/src/testbed/libgnunettestbed.la \
156 $(top_builddir)/src/testing/libgnunettesting.la \
157 $(top_builddir)/src/util/libgnunetutil.la
158
159test_messenger_worst_client_SOURCES = \
160 test_messenger_worst_client.c \
161 testing_messenger_barrier.c testing_messenger_barrier.h \
162 testing_messenger_setup.c testing_messenger_setup.h
163test_messenger_worst_client_LDADD = \
164 libgnunetmessenger_common.la \
165 libgnunetmessenger.la \
166 $(top_builddir)/src/testbed/libgnunettestbed.la \
167 $(top_builddir)/src/testing/libgnunettesting.la \
168 $(top_builddir)/src/util/libgnunetutil.la
169
170test_messenger_sync_p2p_SOURCES = \
171 test_messenger_sync_p2p.c \
172 testing_messenger_barrier.c testing_messenger_barrier.h \
173 testing_messenger_setup.c testing_messenger_setup.h
174test_messenger_sync_p2p_LDADD = \
175 libgnunetmessenger_common.la \
176 libgnunetmessenger.la \
177 $(top_builddir)/src/testbed/libgnunettestbed.la \
178 $(top_builddir)/src/testing/libgnunettesting.la \
179 $(top_builddir)/src/util/libgnunetutil.la
180
181test_messenger_async_p2p_SOURCES = \
182 test_messenger_async_p2p.c \
183 testing_messenger_barrier.c testing_messenger_barrier.h \
184 testing_messenger_setup.c testing_messenger_setup.h
185test_messenger_async_p2p_LDADD = \
186 libgnunetmessenger_common.la \
187 libgnunetmessenger.la \
188 $(top_builddir)/src/testbed/libgnunettestbed.la \
189 $(top_builddir)/src/testing/libgnunettesting.la \
190 $(top_builddir)/src/util/libgnunetutil.la
191
192test_messenger_worst_p2p_SOURCES = \
193 test_messenger_worst_p2p.c \
194 testing_messenger_barrier.c testing_messenger_barrier.h \
195 testing_messenger_setup.c testing_messenger_setup.h
196test_messenger_worst_p2p_LDADD = \
197 libgnunetmessenger_common.la \
198 libgnunetmessenger.la \
199 $(top_builddir)/src/testbed/libgnunettestbed.la \
200 $(top_builddir)/src/testing/libgnunettesting.la \
201 $(top_builddir)/src/util/libgnunetutil.la
202
203test_messenger_server_SOURCES = \
204 test_messenger_server.c \
205 testing_messenger_barrier.c testing_messenger_barrier.h \
206 testing_messenger_setup.c testing_messenger_setup.h
207test_messenger_server_LDADD = \
208 libgnunetmessenger_common.la \
209 libgnunetmessenger.la \
210 $(top_builddir)/src/testbed/libgnunettestbed.la \
211 $(top_builddir)/src/testing/libgnunettesting.la \
212 $(top_builddir)/src/util/libgnunetutil.la
213
214test_messenger_growth_SOURCES = \
215 test_messenger_growth.c \
216 testing_messenger_barrier.c testing_messenger_barrier.h \
217 testing_messenger_setup.c testing_messenger_setup.h
218test_messenger_growth_LDADD = \
219 libgnunetmessenger_common.la \
220 libgnunetmessenger.la \
221 $(top_builddir)/src/testbed/libgnunettestbed.la \
222 $(top_builddir)/src/testing/libgnunettesting.la \
223 $(top_builddir)/src/util/libgnunetutil.la
224
225test_messenger_ring_SOURCES = \
226 test_messenger_ring.c \
227 testing_messenger_barrier.c testing_messenger_barrier.h \
228 testing_messenger_setup.c testing_messenger_setup.h
229test_messenger_ring_LDADD = \
230 libgnunetmessenger_common.la \
231 libgnunetmessenger.la \
232 $(top_builddir)/src/testbed/libgnunettestbed.la \
233 $(top_builddir)/src/testing/libgnunettesting.la \
234 $(top_builddir)/src/util/libgnunetutil.la
235
236test_messenger_adapt_SOURCES = \
237 test_messenger_adapt.c \
238 testing_messenger_barrier.c testing_messenger_barrier.h \
239 testing_messenger_setup.c testing_messenger_setup.h
240test_messenger_adapt_LDADD = \
124 libgnunetmessenger_common.la \ 241 libgnunetmessenger_common.la \
125 libgnunetmessenger.la \ 242 libgnunetmessenger.la \
126 $(top_builddir)/src/testbed/libgnunettestbed.la \ 243 $(top_builddir)/src/testbed/libgnunettestbed.la \
127 $(top_builddir)/src/testbed-logger/libgnunettestbedlogger.la \
128 $(top_builddir)/src/testing/libgnunettesting.la \ 244 $(top_builddir)/src/testing/libgnunettesting.la \
129 $(top_builddir)/src/util/libgnunetutil.la 245 $(top_builddir)/src/util/libgnunetutil.la
130 246
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c
index 579e5c3ad..737bb83c8 100644
--- a/src/messenger/gnunet-messenger.c
+++ b/src/messenger/gnunet-messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -34,29 +34,38 @@ struct GNUNET_MESSENGER_Handle *messenger;
34/** 34/**
35 * Function called whenever a message is received or sent. 35 * Function called whenever a message is received or sent.
36 * 36 *
37 * @param cls Closure 37 * @param[in/out] cls Closure
38 * @param room Room 38 * @param[in] room Room
39 * @param message Message 39 * @param[in] sender Sender of message
40 * @param hash Hash of message 40 * @param[in] message Message
41 * @param[in] hash Hash of message
42 * @param[in] flags Flags of message
41 */ 43 */
42void 44void
43on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 45on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
44 const struct GNUNET_HashCode *hash) 46 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
47 enum GNUNET_MESSENGER_MessageFlags flags)
45{ 48{
46 struct GNUNET_MESSENGER_Contact *sender = GNUNET_MESSENGER_get_member (room, &(message->header.sender_id));
47
48 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender); 49 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
49 50
50 if (!sender_name) 51 if (!sender_name)
51 sender_name = "anonymous"; 52 sender_name = "anonymous";
52 53
54 printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
55
56 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
57 printf ("*");
58
53 switch (message->header.kind) 59 switch (message->header.kind)
54 { 60 {
55 case GNUNET_MESSENGER_KIND_JOIN: 61 case GNUNET_MESSENGER_KIND_JOIN:
56 { 62 {
57 printf ("* '%s' joined the room! [ %u %u %u %u ]\n", sender_name, message->body.join.key.ecdsa_key.q_y[0], 63 printf ("* '%s' joined the room!\n", sender_name);
58 message->body.join.key.ecdsa_key.q_y[1], message->body.join.key.ecdsa_key.q_y[2], 64 break;
59 message->body.join.key.ecdsa_key.q_y[3]); 65 }
66 case GNUNET_MESSENGER_KIND_NAME:
67 {
68 printf ("* '%s' gets renamed to '%s'\n", sender_name, message->body.name.name);
60 break; 69 break;
61 } 70 }
62 case GNUNET_MESSENGER_KIND_LEAVE: 71 case GNUNET_MESSENGER_KIND_LEAVE:
@@ -76,6 +85,7 @@ on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GN
76 } 85 }
77 default: 86 default:
78 { 87 {
88 printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
79 break; 89 break;
80 } 90 }
81 } 91 }
@@ -86,7 +96,7 @@ struct GNUNET_SCHEDULER_Task *read_task;
86/** 96/**
87 * Task to shut down this application. 97 * Task to shut down this application.
88 * 98 *
89 * @param cls Closure 99 * @param[in/out] cls Closure
90 */ 100 */
91static void 101static void
92shutdown_hook (void *cls) 102shutdown_hook (void *cls)
@@ -108,10 +118,24 @@ listen_stdio (void *cls);
108 118
109#define MAX_BUFFER_SIZE 60000 119#define MAX_BUFFER_SIZE 60000
110 120
121static int
122iterate_send_private_message (void *cls, struct GNUNET_MESSENGER_Room *room,
123 const struct GNUNET_MESSENGER_Contact *contact)
124{
125 struct GNUNET_MESSENGER_Message *message = cls;
126
127 if (GNUNET_MESSENGER_contact_get_key(contact))
128 GNUNET_MESSENGER_send_message (room, message, contact);
129
130 return GNUNET_YES;
131}
132
133int private_mode;
134
111/** 135/**
112 * Task run in stdio mode, after some data is available at stdin. 136 * Task run in stdio mode, after some data is available at stdin.
113 * 137 *
114 * @param cls Closure 138 * @param[in/out] cls Closure
115 */ 139 */
116static void 140static void
117read_stdio (void *cls) 141read_stdio (void *cls)
@@ -140,7 +164,10 @@ read_stdio (void *cls)
140 message.header.kind = GNUNET_MESSENGER_KIND_TEXT; 164 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
141 message.body.text.text = buffer; 165 message.body.text.text = buffer;
142 166
143 GNUNET_MESSENGER_send_message (room, &message); 167 if (GNUNET_YES == private_mode)
168 GNUNET_MESSENGER_iterate_members(room, iterate_send_private_message, &message);
169 else
170 GNUNET_MESSENGER_send_message (room, &message, NULL);
144 171
145 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls); 172 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
146} 173}
@@ -148,7 +175,7 @@ read_stdio (void *cls)
148/** 175/**
149 * Wait for input on STDIO and send it out over the #ch. 176 * Wait for input on STDIO and send it out over the #ch.
150 * 177 *
151 * @param cls Closure 178 * @param[in/out] cls Closure
152 */ 179 */
153static void 180static void
154listen_stdio (void *cls) 181listen_stdio (void *cls)
@@ -160,10 +187,8 @@ listen_stdio (void *cls)
160 GNUNET_NETWORK_fdset_set_native (rs, 0); 187 GNUNET_NETWORK_fdset_set_native (rs, 0);
161 188
162 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 189 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
163 GNUNET_TIME_UNIT_FOREVER_REL, 190 GNUNET_TIME_UNIT_FOREVER_REL, rs,
164 rs, 191 NULL, &read_stdio, cls);
165 NULL,
166 &read_stdio, cls);
167 192
168 GNUNET_NETWORK_fdset_destroy (rs); 193 GNUNET_NETWORK_fdset_destroy (rs);
169} 194}
@@ -171,7 +196,7 @@ listen_stdio (void *cls)
171/** 196/**
172 * Initial task to startup application. 197 * Initial task to startup application.
173 * 198 *
174 * @param cls Closure 199 * @param[in/out] cls Closure
175 */ 200 */
176static void 201static void
177idle (void *cls) 202idle (void *cls)
@@ -192,8 +217,8 @@ struct GNUNET_SCHEDULER_Task *shutdown_task;
192/** 217/**
193 * Function called when an identity is retrieved. 218 * Function called when an identity is retrieved.
194 * 219 *
195 * @param cls Closure 220 * @param[in/out] cls Closure
196 * @param handle Handle of messenger service 221 * @param[in/out] handle Handle of messenger service
197 */ 222 */
198static void 223static void
199on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) 224on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
@@ -230,7 +255,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
230 { 255 {
231 printf ("* You try to entry a room...\n"); 256 printf ("* You try to entry a room...\n");
232 257
233 room = GNUNET_MESSENGER_entry_room (messenger, door, &key); 258 room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
234 } 259 }
235 else 260 else
236 { 261 {
@@ -246,17 +271,26 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
246 if (!room) 271 if (!room)
247 GNUNET_SCHEDULER_shutdown (); 272 GNUNET_SCHEDULER_shutdown ();
248 else 273 else
274 {
275 struct GNUNET_MESSENGER_Message message;
276 message.header.kind = GNUNET_MESSENGER_KIND_NAME;
277 message.body.name.name = GNUNET_strdup(name);
278
279 GNUNET_MESSENGER_send_message (room, &message, NULL);
280 GNUNET_free(message.body.name.name);
281
249 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle, 282 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
250 room); 283 room);
284 }
251} 285}
252 286
253/** 287/**
254 * Main function that will be run by the scheduler. 288 * Main function that will be run by the scheduler.
255 * 289 *
256 * @param cls closure 290 * @param[in/out] cls closure
257 * @param args remaining command-line arguments 291 * @param[in] args remaining command-line arguments
258 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 292 * @param[in] cfgfile name of the configuration file used (for saving, can be NULL!)
259 * @param cfg configuration 293 * @param[in] cfg configuration
260 */ 294 */
261static void 295static void
262run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) 296run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
@@ -269,38 +303,24 @@ run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFI
269/** 303/**
270 * The main function to obtain messenger information. 304 * The main function to obtain messenger information.
271 * 305 *
272 * @param argc number of arguments from the command line 306 * @param[in] argc number of arguments from the command line
273 * @param argv command line arguments 307 * @param[in] argv command line arguments
274 * @return 0 ok, 1 on error 308 * @return #EXIT_SUCCESS ok, #EXIT_FAILURE on error
275 */ 309 */
276int 310int
277main (int argc, char **argv) 311main (int argc, char **argv)
278{ 312{
279 const char *description = "Open and connect to rooms using the MESSENGER to chat."; 313 const char *description = "Open and connect to rooms using the MESSENGER to chat.";
280 314
281 struct GNUNET_GETOPT_CommandLineOption options[] = { 315 struct GNUNET_GETOPT_CommandLineOption options[] =
282 GNUNET_GETOPT_option_string ('d', 316 {
283 "door", 317 GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
284 "PEERIDENTITY", 318 GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
285 "peer identity to entry into the room", 319 GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
286 &door_id), 320 GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
287 GNUNET_GETOPT_option_string ('e', 321 GNUNET_GETOPT_OPTION_END
288 "ego", 322 };
289 "IDENTITY", 323
290 "identity to use for messaging", 324 return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
291 &ego_name), 325 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
292 GNUNET_GETOPT_option_string ('r',
293 "room",
294 "ROOMKEY",
295 "key of the room to connect to",
296 &room_key),
297 GNUNET_GETOPT_OPTION_END };
298
299 return (GNUNET_OK == GNUNET_PROGRAM_run (argc,
300 argv,
301 "gnunet-messenger\0",
302 gettext_noop(description),
303 options,
304 &run,
305 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
306} 326}
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
index 2c92305c4..187b65ed5 100644
--- a/src/messenger/gnunet-service-messenger.c
+++ b/src/messenger/gnunet-service-messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -52,7 +52,7 @@ handle_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg)
52 52
53 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name); 53 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
54 54
55 setup_handle_name (msg_client->handle, strlen (name) > 0? name : NULL); 55 setup_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
56 56
57 GNUNET_SERVICE_client_continue (msg_client->client); 57 GNUNET_SERVICE_client_continue (msg_client->client);
58} 58}
@@ -62,8 +62,7 @@ handle_update (void *cls, const struct GNUNET_MESSENGER_UpdateMessage *msg)
62{ 62{
63 struct GNUNET_MESSENGER_Client *msg_client = cls; 63 struct GNUNET_MESSENGER_Client *msg_client = cls;
64 64
65 if (GNUNET_OK != update_handle (msg_client->handle)) 65 update_handle (msg_client->handle);
66 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Name is required to update key!\n");
67 66
68 GNUNET_SERVICE_client_continue (msg_client->client); 67 GNUNET_SERVICE_client_continue (msg_client->client);
69} 68}
@@ -92,8 +91,7 @@ handle_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
92 91
93 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name); 92 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
94 93
95 if (GNUNET_YES != set_handle_name (msg_client->handle, name)) 94 set_handle_name (msg_client->handle, name);
96 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No valid name: %s\n", name);
97 95
98 GNUNET_SERVICE_client_continue (msg_client->client); 96 GNUNET_SERVICE_client_continue (msg_client->client);
99} 97}
@@ -103,15 +101,13 @@ handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
103{ 101{
104 struct GNUNET_MESSENGER_Client *msg_client = cls; 102 struct GNUNET_MESSENGER_Client *msg_client = cls;
105 103
106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", 104 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (&(msg->key)));
107 GNUNET_h2s (&(msg->key)));
108 105
109 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key))) 106 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key)))
110 { 107 {
111 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 108 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
112 109
113 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", 110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", GNUNET_sh2s (member_id));
114 GNUNET_sh2s (member_id));
115 111
116 struct GNUNET_MESSENGER_RoomMessage *response; 112 struct GNUNET_MESSENGER_RoomMessage *response;
117 struct GNUNET_MQ_Envelope *env; 113 struct GNUNET_MQ_Envelope *env;
@@ -121,8 +117,7 @@ handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
121 GNUNET_MQ_send (msg_client->handle->mq, env); 117 GNUNET_MQ_send (msg_client->handle->mq, env);
122 } 118 }
123 else 119 else
124 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", 120 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", GNUNET_h2s (&(msg->key)));
125 GNUNET_h2s (&(msg->key)));
126 121
127 GNUNET_SERVICE_client_continue (msg_client->client); 122 GNUNET_SERVICE_client_continue (msg_client->client);
128} 123}
@@ -132,15 +127,13 @@ handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
132{ 127{
133 struct GNUNET_MESSENGER_Client *msg_client = cls; 128 struct GNUNET_MESSENGER_Client *msg_client = cls;
134 129
135 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", 130 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
136 GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
137 131
138 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key))) 132 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key)))
139 { 133 {
140 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 134 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
141 135
142 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", 136 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", GNUNET_sh2s (member_id));
143 GNUNET_sh2s (member_id));
144 137
145 struct GNUNET_MESSENGER_RoomMessage *response; 138 struct GNUNET_MESSENGER_RoomMessage *response;
146 struct GNUNET_MQ_Envelope *env; 139 struct GNUNET_MQ_Envelope *env;
@@ -151,8 +144,8 @@ handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
151 GNUNET_MQ_send (msg_client->handle->mq, env); 144 GNUNET_MQ_send (msg_client->handle->mq, env);
152 } 145 }
153 else 146 else
154 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", 147 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", GNUNET_h2s (&(msg->key)),
155 GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door))); 148 GNUNET_i2s (&(msg->door)));
156 149
157 GNUNET_SERVICE_client_continue (msg_client->client); 150 GNUNET_SERVICE_client_continue (msg_client->client);
158} 151}
@@ -166,10 +159,9 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
166 159
167 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key))) 160 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key)))
168 { 161 {
169 const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); 162 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
170 163
171 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", 164 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", GNUNET_sh2s (member_id));
172 GNUNET_sh2s (member_id));
173 165
174 struct GNUNET_MESSENGER_RoomMessage *response; 166 struct GNUNET_MESSENGER_RoomMessage *response;
175 struct GNUNET_MQ_Envelope *env; 167 struct GNUNET_MQ_Envelope *env;
@@ -187,17 +179,40 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
187static int 179static int
188check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg) 180check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
189{ 181{
190 const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); 182 const uint16_t full_length = ntohs (msg->header.size);
191 183
192 if (full_length < sizeof(msg->key)) 184 if (full_length < sizeof(*msg))
193 return GNUNET_NO; 185 return GNUNET_NO;
194 186
195 const uint16_t length = full_length - sizeof(msg->key); 187 const enum GNUNET_MESSENGER_MessageFlags flags = (
188 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
189 );
190
191 const uint16_t length = full_length - sizeof(*msg);
196 const char *buffer = ((const char*) msg) + sizeof(*msg); 192 const char *buffer = ((const char*) msg) + sizeof(*msg);
197 193
194 uint16_t key_length = 0;
195
196 if (!(flags & GNUNET_MESSENGER_FLAG_PRIVATE))
197 goto check_for_message;
198
199 struct GNUNET_IDENTITY_PublicKey public_key;
200
201 key_length = GNUNET_IDENTITY_read_key_from_buffer(&public_key, buffer, length);
202
203check_for_message:
204 if (key_length < 0)
205 return GNUNET_NO;
206
207 const uint16_t msg_length = length - key_length;
208 const char* msg_buffer = buffer + key_length;
209
198 struct GNUNET_MESSENGER_Message message; 210 struct GNUNET_MESSENGER_Message message;
199 211
200 if (GNUNET_YES != decode_message (&message, length, buffer)) 212 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL))
213 return GNUNET_NO;
214
215 if (GNUNET_YES != filter_message_sending(&message))
201 return GNUNET_NO; 216 return GNUNET_NO;
202 217
203 return GNUNET_OK; 218 return GNUNET_OK;
@@ -208,42 +223,85 @@ handle_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
208{ 223{
209 struct GNUNET_MESSENGER_Client *msg_client = cls; 224 struct GNUNET_MESSENGER_Client *msg_client = cls;
210 225
226 const enum GNUNET_MESSENGER_MessageFlags flags = (
227 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
228 );
229
211 const struct GNUNET_HashCode *key = &(msg->key); 230 const struct GNUNET_HashCode *key = &(msg->key);
212 const char *buffer = ((const char*) msg) + sizeof(*msg); 231 const char *buffer = ((const char*) msg) + sizeof(*msg);
213 232
214 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); 233 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
234 uint16_t key_length = 0;
235
236 struct GNUNET_IDENTITY_PublicKey public_key;
237
238 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
239 key_length = GNUNET_IDENTITY_read_key_from_buffer(
240 &public_key, buffer, length
241 );
242
243 const uint16_t msg_length = length - key_length;
244 const char* msg_buffer = buffer + key_length;
215 245
216 struct GNUNET_MESSENGER_Message message; 246 struct GNUNET_MESSENGER_Message message;
217 decode_message (&message, length, buffer); 247 decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
248
249 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
250 (GNUNET_YES != encrypt_message(&message, &public_key)))
251 {
252 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Encrypting message failed: Message got dropped!\n");
253
254 goto end_handling;
255 }
218 256
219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n", 257 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
220 GNUNET_MESSENGER_name_of_kind (message.header.kind), 258 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
221 GNUNET_h2s (key));
222 259
223 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message)) 260 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message))
224 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n", 261 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
225 GNUNET_MESSENGER_name_of_kind (message.header.kind), 262 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
226 GNUNET_h2s (key));
227 263
264end_handling:
228 GNUNET_SERVICE_client_continue (msg_client->client); 265 GNUNET_SERVICE_client_continue (msg_client->client);
229} 266}
230 267
231static void 268static void
232handle_get_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) 269handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg)
233{ 270{
234 struct GNUNET_MESSENGER_Client *msg_client = cls; 271 struct GNUNET_MESSENGER_Client *msg_client = cls;
235 272
236 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", 273 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", GNUNET_h2s (&(msg->key)));
237 GNUNET_h2s (&(msg->key)));
238 274
239 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key)); 275 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key));
240 276
241 if (room) 277 if (!room)
242 get_room_message (room, msg_client->handle, &(msg->hash), GNUNET_YES); 278 {
243 else 279 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", GNUNET_h2s (&(msg->key)));
244 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", 280 goto end_handling;
245 GNUNET_h2s (&(msg->key))); 281 }
282
283 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, msg_client->handle, &(msg->hash),
284 GNUNET_YES);
285
286 if (!message)
287 goto end_handling;
288
289 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
290
291 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message);
292
293 if (!member)
294 {
295 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (&(msg->hash)));
296 goto end_handling;
297 }
298
299 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(msg->hash));
300
301 if (session)
302 notify_handle_message (msg_client->handle, get_room_key(room), session, message, &(msg->hash));
246 303
304end_handling:
247 GNUNET_SERVICE_client_continue (msg_client->client); 305 GNUNET_SERVICE_client_continue (msg_client->client);
248} 306}
249 307
@@ -271,16 +329,16 @@ callback_client_disconnect (void *cls, struct GNUNET_SERVICE_Client *client, voi
271/** 329/**
272 * Setup MESSENGER internals. 330 * Setup MESSENGER internals.
273 * 331 *
274 * @param cls closure 332 * @param[in/out] cls closure
275 * @param config configuration to use 333 * @param[in] config configuration to use
276 * @param service the initialized service 334 * @param[in/out] service the initialized service
277 */ 335 */
278static void 336static void
279run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service) 337run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service)
280{ 338{
281 messenger = create_service (config, service); 339 messenger = create_service (config, service);
282 340
283 if ((!messenger) || (!messenger->cadet) || (!messenger->identity)) 341 if (!messenger)
284 GNUNET_SCHEDULER_shutdown (); 342 GNUNET_SCHEDULER_shutdown ();
285} 343}
286 344
@@ -302,5 +360,5 @@ GNUNET_SERVICE_MAIN(
302 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ), 360 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ),
303 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ), 361 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ),
304 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ), 362 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ),
305 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_RecvMessage, NULL ), 363 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_GetMessage, NULL ),
306 GNUNET_MQ_handler_end()); 364 GNUNET_MQ_handler_end());
diff --git a/src/messenger/gnunet-service-messenger.h b/src/messenger/gnunet-service-messenger.h
index 85a1d2549..253fbaadb 100644
--- a/src/messenger/gnunet-service-messenger.h
+++ b/src/messenger/gnunet-service-messenger.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -74,7 +74,6 @@ struct GNUNET_MESSENGER_NameMessage
74struct GNUNET_MESSENGER_KeyMessage 74struct GNUNET_MESSENGER_KeyMessage
75{ 75{
76 struct GNUNET_MessageHeader header; 76 struct GNUNET_MessageHeader header;
77 struct GNUNET_IDENTITY_PublicKey pubkey;
78}; 77};
79 78
80/** 79/**
@@ -105,7 +104,20 @@ struct GNUNET_MESSENGER_MemberMessage
105struct GNUNET_MESSENGER_SendMessage 104struct GNUNET_MESSENGER_SendMessage
106{ 105{
107 struct GNUNET_MessageHeader header; 106 struct GNUNET_MessageHeader header;
107
108 struct GNUNET_HashCode key; 108 struct GNUNET_HashCode key;
109 uint32_t flags;
110};
111
112/**
113 * Message to request something from a room
114 */
115struct GNUNET_MESSENGER_GetMessage
116{
117 struct GNUNET_MessageHeader header;
118
119 struct GNUNET_HashCode key;
120 struct GNUNET_HashCode hash;
109}; 121};
110 122
111/** 123/**
@@ -114,8 +126,12 @@ struct GNUNET_MESSENGER_SendMessage
114struct GNUNET_MESSENGER_RecvMessage 126struct GNUNET_MESSENGER_RecvMessage
115{ 127{
116 struct GNUNET_MessageHeader header; 128 struct GNUNET_MessageHeader header;
129
117 struct GNUNET_HashCode key; 130 struct GNUNET_HashCode key;
131 struct GNUNET_HashCode sender;
132 struct GNUNET_HashCode context;
118 struct GNUNET_HashCode hash; 133 struct GNUNET_HashCode hash;
134 uint32_t flags;
119}; 135};
120 136
121#endif //GNUNET_SERVICE_MESSENGER_H 137#endif //GNUNET_SERVICE_MESSENGER_H
diff --git a/src/messenger/gnunet-service-messenger_basement.c b/src/messenger/gnunet-service-messenger_basement.c
index 190cf2de5..f302c8d66 100644
--- a/src/messenger/gnunet-service-messenger_basement.c
+++ b/src/messenger/gnunet-service-messenger_basement.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -28,6 +28,8 @@
28size_t 28size_t
29count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels) 29count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels)
30{ 30{
31 GNUNET_assert(tunnels);
32
31 const struct GNUNET_MESSENGER_ListTunnel *element; 33 const struct GNUNET_MESSENGER_ListTunnel *element;
32 size_t count = 0; 34 size_t count = 0;
33 35
diff --git a/src/messenger/gnunet-service-messenger_basement.h b/src/messenger/gnunet-service-messenger_basement.h
index 0a1a9b126..b19aec405 100644
--- a/src/messenger/gnunet-service-messenger_basement.h
+++ b/src/messenger/gnunet-service-messenger_basement.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -31,34 +31,34 @@
31/** 31/**
32 * Returns the count of peers in a list (typically from the basement of a room). 32 * Returns the count of peers in a list (typically from the basement of a room).
33 * 33 *
34 * @param tunnels List of peer identities 34 * @param[in] tunnels List of peer identities
35 * @return Count of the entries in the list 35 * @return Count of the entries in the list
36 */ 36 */
37size_t 37size_t
38count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels); 38count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels);
39 39
40/** 40/**
41 * Returns GNUNET_YES or GNUNET_NO to determine if the peer at index <i>src</i> should 41 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peer at index <i>src</i> should
42 * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete 42 * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete
43 * basement with a given <i>count</i> of peers. 43 * basement with a given <i>count</i> of peers.
44 * 44 *
45 * @param count Count of peers 45 * @param[in] count Count of peers
46 * @param src Source index 46 * @param[in] src Source index
47 * @param dst Destination index 47 * @param[in] dst Destination index
48 * @return GNUNET_YES or GNUNET_NO based on topologic requirement 48 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
49 */ 49 */
50int 50int
51should_connect_tunnel_to (size_t count, size_t src, size_t dst); 51should_connect_tunnel_to (size_t count, size_t src, size_t dst);
52 52
53/** 53/**
54 * Returns GNUNET_YES or GNUNET_NO to determine if the peers of index <i>src</i> and 54 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peers of index <i>src</i> and
55 * index <i>dst</i> should be connected in any direction to construct a complete 55 * index <i>dst</i> should be connected in any direction to construct a complete
56 * basement with a given <i>count</i> of peers. 56 * basement with a given <i>count</i> of peers.
57 * 57 *
58 * @param count Count of peers 58 * @param[in] count Count of peers
59 * @param src Source index 59 * @param[in] src Source index
60 * @param dst Destination index 60 * @param[in] dst Destination index
61 * @return GNUNET_YES or GNUNET_NO based on topologic requirement 61 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
62 */ 62 */
63int 63int
64required_connection_between (size_t count, size_t src, size_t dst); 64required_connection_between (size_t count, size_t src, size_t dst);
diff --git a/src/messenger/gnunet-service-messenger_contact.c b/src/messenger/gnunet-service-messenger_contact.c
deleted file mode 100644
index 1ec125402..000000000
--- a/src/messenger/gnunet-service-messenger_contact.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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 src/messenger/gnunet-service-messenger_contact.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_contact.h"
27
28struct GNUNET_MESSENGER_SrvContact*
29create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
30{
31 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_new(struct GNUNET_MESSENGER_SrvContact);
32
33 contact->name = NULL;
34 contact->rc = 0;
35
36 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
37
38 return contact;
39}
40
41void
42destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact)
43{
44 if (contact->name)
45 GNUNET_free(contact->name);
46
47 GNUNET_free(contact);
48}
49
50const char*
51get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact)
52{
53 return contact->name;
54}
55
56void
57set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name)
58{
59 GNUNET_assert(name);
60
61 if (contact->name)
62 GNUNET_free(contact->name);
63
64 contact->name = GNUNET_strdup(name);
65}
66
67const struct GNUNET_IDENTITY_PublicKey*
68get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact)
69{
70 return &(contact->public_key);
71}
72
73void
74increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact)
75{
76 contact->rc++;
77}
78
79int
80decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact)
81{
82 if (contact->rc > 0)
83 contact->rc--;
84
85 return contact->rc ? GNUNET_NO : GNUNET_YES;
86}
87
88const struct GNUNET_HashCode*
89get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact)
90{
91 static struct GNUNET_HashCode id;
92
93 GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id);
94
95 return &id;
96}
diff --git a/src/messenger/gnunet-service-messenger_contact.h b/src/messenger/gnunet-service-messenger_contact.h
deleted file mode 100644
index 4a4f8bf0f..000000000
--- a/src/messenger/gnunet-service-messenger_contact.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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 src/messenger/gnunet-service-messenger_contact.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_CONTACT_H
27#define GNUNET_SERVICE_MESSENGER_CONTACT_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_identity_service.h"
32
33struct GNUNET_MESSENGER_SrvContact
34{
35 char *name;
36 size_t rc;
37
38 struct GNUNET_IDENTITY_PublicKey public_key;
39};
40
41/**
42 * Creates and allocates a new contact with a given public <i>key</i> from an EGO.
43 *
44 * @param key Public key
45 * @return New contact
46 */
47struct GNUNET_MESSENGER_SrvContact*
48create_contact (const struct GNUNET_IDENTITY_PublicKey *key);
49
50/**
51 * Destroys a contact and frees its memory fully.
52 *
53 * @param contact Contact
54 */
55void
56destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact);
57
58/**
59 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet.
60 *
61 * @param contact Contact
62 * @return Name of the contact or NULL
63 */
64const char*
65get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact);
66
67/**
68 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>.
69 *
70 * @param contact Contact
71 * @param name Valid name (may not be NULL!)
72 */
73void
74set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name);
75
76/**
77 * Returns the public key of a given <i>contact</i>.
78 *
79 * @param contact Contact
80 * @return Public key of the contact
81 */
82const struct GNUNET_IDENTITY_PublicKey*
83get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact);
84
85/**
86 * Increases the reference counter of a given <i>contact</i> which is zero as default.
87 *
88 * @param contact Contact
89 */
90void
91increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact);
92
93/**
94 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
95 * and returns GNUNET_YES if the counter is equal to zero, otherwise GNUNET_NO.
96 *
97 * @param contact Contact
98 * @return GNUNET_YES or GNUNET_NO depending on the reference counter
99 */
100int
101decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact);
102
103/**
104 * Returns the resulting hashcode of the public key from a given <i>contact</i>.
105 *
106 * @param contact Contact
107 * @return Hash of the contacts public key
108 */
109const struct GNUNET_HashCode*
110get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact);
111
112#endif //GNUNET_SERVICE_MESSENGER_CONTACT_H
diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c
new file mode 100644
index 000000000..3b069fcf5
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_ego_store.c
@@ -0,0 +1,295 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_ego_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_ego_store.h"
27
28#include "gnunet-service-messenger_handle.h"
29
30static void
31callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
32{
33 if ((!ego) || (!identifier))
34 return;
35
36 struct GNUNET_MESSENGER_EgoStore *store = cls;
37
38 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
39
40 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
41}
42
43void
44init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config)
45{
46 GNUNET_assert ((store) && (config));
47
48 store->cfg = config;
49 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
50 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
51
52 store->lu_start = NULL;
53 store->lu_end = NULL;
54
55 store->op_start = NULL;
56 store->op_end = NULL;
57}
58
59
60static int
61iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
62{
63 struct GNUNET_MESSENGER_Ego *ego = value;
64 GNUNET_free(ego);
65 return GNUNET_YES;
66}
67
68void
69clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
70{
71 GNUNET_assert (store);
72
73 struct GNUNET_MESSENGER_EgoOperation *op;
74
75 while (store->op_start)
76 {
77 op = store->op_start;
78
79 GNUNET_IDENTITY_cancel (op->operation);
80 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
81
82 if (op->identifier)
83 GNUNET_free (op->identifier);
84
85 GNUNET_free (op);
86 }
87
88 struct GNUNET_MESSENGER_EgoLookup *lu;
89
90 while (store->lu_start)
91 {
92 lu = store->lu_start;
93
94 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
95 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
96
97 if (lu->identifier)
98 GNUNET_free(lu->identifier);
99
100 GNUNET_free (lu);
101 }
102
103 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
104 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
105
106 if (store->identity)
107 {
108 GNUNET_IDENTITY_disconnect (store->identity);
109
110 store->identity = NULL;
111 }
112}
113
114static void
115callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg)
116{
117 struct GNUNET_MESSENGER_EgoOperation *element = cls;
118 struct GNUNET_MESSENGER_EgoStore *store = element->store;
119
120 GNUNET_assert(element->identifier);
121
122 if (emsg)
123 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
124
125 if (key)
126 {
127 struct GNUNET_MESSENGER_SrvHandle *handle = element->handle;
128
129 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
130
131 set_handle_ego (handle, msg_ego);
132 }
133 else
134 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
135
136 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
137 GNUNET_free (element->identifier);
138 GNUNET_free (element);
139}
140
141void
142create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
143 void *handle)
144{
145 GNUNET_assert ((store) && (identifier));
146
147 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
148
149 element->store = store;
150 element->handle = handle;
151
152 element->identifier = GNUNET_strdup (identifier);
153
154 element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL,
155 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element);
156
157 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
158}
159
160static void
161callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego)
162{
163 struct GNUNET_MESSENGER_EgoLookup *element = cls;
164 struct GNUNET_MESSENGER_EgoStore *store = element->store;
165
166 GNUNET_assert(element->identifier);
167
168 struct GNUNET_MESSENGER_Ego *msg_ego;
169
170 if (ego)
171 msg_ego = update_store_ego (
172 store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego)
173 );
174 else
175 msg_ego = NULL;
176
177 if (element->cb)
178 element->cb(element->cls, element->identifier, msg_ego);
179
180 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
181 GNUNET_free (element->identifier);
182 GNUNET_free (element);
183}
184
185void
186lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
187 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls)
188{
189 GNUNET_assert (store);
190
191 if (!identifier)
192 {
193 lookup(cls, identifier, NULL);
194 return;
195 }
196
197 struct GNUNET_HashCode hash;
198 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
199
200 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
201
202 if (ego)
203 lookup(cls, identifier, ego);
204 else
205 {
206 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
207
208 element->store = store;
209
210 element->cb = lookup;
211 element->cls = cls;
212
213 element->identifier = GNUNET_strdup (identifier);
214
215 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
216
217 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
218 }
219}
220
221struct GNUNET_MESSENGER_Ego*
222update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
223 const struct GNUNET_IDENTITY_PrivateKey *key)
224{
225 GNUNET_assert ((store) && (identifier) && (key));
226
227 struct GNUNET_HashCode hash;
228 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
229
230 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
231
232 if (!ego)
233 {
234 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
235 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
236 }
237
238 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
239
240 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
241 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
242
243 return ego;
244}
245
246static void
247callback_ego_rename (void *cls, const char *emsg)
248{
249 struct GNUNET_MESSENGER_EgoOperation *element = cls;
250 struct GNUNET_MESSENGER_EgoStore *store = element->store;
251
252 GNUNET_assert(element->identifier);
253
254 if (emsg)
255 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
256
257 struct GNUNET_HashCode hash;
258 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
259
260 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
261
262 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
263 {
264 GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash);
265
266 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
267 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
268 }
269 else
270 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
271
272 GNUNET_free (element->handle);
273
274 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
275 GNUNET_free (element->identifier);
276 GNUNET_free (element);
277}
278
279void
280rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
281 const char *new_identifier)
282{
283 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
284
285 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
286
287 element->store = store;
288 element->handle = GNUNET_strdup (new_identifier);
289
290 element->identifier = GNUNET_strdup (old_identifier);
291
292 element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element);
293
294 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
295}
diff --git a/src/messenger/gnunet-service-messenger_ego_store.h b/src/messenger/gnunet-service-messenger_ego_store.h
new file mode 100644
index 000000000..41f14fff2
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_ego_store.h
@@ -0,0 +1,152 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_ego_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_EGO_STORE_H
27#define GNUNET_SERVICE_MESSENGER_EGO_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31
32#include "messenger_api_ego.h"
33
34struct GNUNET_MESSENGER_Ego;
35struct GNUNET_MESSENGER_EgoStore;
36
37typedef void
38(*GNUNET_MESSENGER_EgoLookupCallback) (void *cls, const char *identifier,
39 const struct GNUNET_MESSENGER_Ego *ego);
40
41struct GNUNET_MESSENGER_EgoLookup
42{
43 struct GNUNET_MESSENGER_EgoLookup *prev;
44 struct GNUNET_MESSENGER_EgoLookup *next;
45
46 struct GNUNET_IDENTITY_EgoLookup *lookup;
47
48 struct GNUNET_MESSENGER_EgoStore *store;
49
50 GNUNET_MESSENGER_EgoLookupCallback cb;
51 void *cls;
52
53 char *identifier;
54};
55
56struct GNUNET_MESSENGER_EgoOperation
57{
58 struct GNUNET_MESSENGER_EgoOperation *prev;
59 struct GNUNET_MESSENGER_EgoOperation *next;
60
61 struct GNUNET_IDENTITY_Operation *operation;
62
63 struct GNUNET_MESSENGER_EgoStore *store;
64 void *handle;
65
66 char *identifier;
67};
68
69struct GNUNET_MESSENGER_EgoStore
70{
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 struct GNUNET_IDENTITY_Handle *identity;
74 struct GNUNET_CONTAINER_MultiHashMap *egos;
75
76 struct GNUNET_MESSENGER_EgoLookup *lu_start;
77 struct GNUNET_MESSENGER_EgoLookup *lu_end;
78
79 struct GNUNET_MESSENGER_EgoOperation *op_start;
80 struct GNUNET_MESSENGER_EgoOperation *op_end;
81};
82
83/**
84 * Initializes an EGO-store as fully empty.
85 *
86 * @param[out] store EGO-store
87 * @param[in] config Configuration handle
88 */
89void
90init_ego_store (struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config);
91
92/**
93 * Clears an EGO-store, wipes its content and deallocates its memory.
94 *
95 * @param[in/out] store EGO-store
96 */
97void
98clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store);
99
100/**
101 * Creates a new EGO which will be registered to a <i>store</i> under
102 * a specific <i>identifier</i>. A given <i>handle</i> will be informed
103 * about the creation and changes its EGO accordingly.
104 *
105 * @param[in/out] store EGO-store
106 * @param[in] identifier Identifier string
107 * @param[in/out] handle Handle or NULL
108 */
109void
110create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
111 void *handle);
112
113/**
114 * Lookups an EGO which was registered to a <i>store</i> under
115 * a specific <i>identifier</i>.
116 *
117 * @param[in/out] store EGO-store
118 * @param[in] identifier Identifier string
119 * @param[in] lookup Lookup callback (non-NULL)
120 * @param[in] cls Closure
121 */
122void
123lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
124 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls);
125
126/**
127 * Updates the registration of an EGO to a <i>store</i> under
128 * a specific <i>identifier</i> with a new <i>key</i>.
129 *
130 * @param[in/out] store EGO-store
131 * @param[in] identifier Identifier string
132 * @param[in] key Private EGO key
133 * @return Updated EGO
134 */
135struct GNUNET_MESSENGER_Ego*
136update_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
137 const struct GNUNET_IDENTITY_PrivateKey *key);
138
139/**
140 * Updates the location of a registered EGO in a <i>store</i> to
141 * a different one under a specific <i>new_identifier<i> replacing
142 * its old one.
143 *
144 * @param[in/out] store EGO-store
145 * @param[in] old_identifier Old identifier string
146 * @param[in] new_identifier New identifier string
147 */
148void
149rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
150 const char *new_identifier);
151
152#endif //GNUNET_SERVICE_MESSENGER_EGO_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_handle.c b/src/messenger/gnunet-service-messenger_handle.c
index 38ad6fbb4..4d2318d62 100644
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ b/src/messenger/gnunet-service-messenger_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -28,18 +28,19 @@
28#include "gnunet-service-messenger.h" 28#include "gnunet-service-messenger.h"
29#include "gnunet-service-messenger_message_kind.h" 29#include "gnunet-service-messenger_message_kind.h"
30 30
31#include "messenger_api_util.h"
32
31struct GNUNET_MESSENGER_SrvHandle* 33struct GNUNET_MESSENGER_SrvHandle*
32create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) 34create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
33{ 35{
36 GNUNET_assert((service) && (mq));
37
34 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle); 38 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
35 39
36 handle->service = service; 40 handle->service = service;
37 handle->mq = mq; 41 handle->mq = mq;
38 42
39 handle->name = NULL; 43 handle->name = NULL;
40
41 handle->operation = NULL;
42
43 handle->ego = NULL; 44 handle->ego = NULL;
44 45
45 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 46 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
@@ -58,11 +59,10 @@ iterate_free_member_ids (void *cls, const struct GNUNET_HashCode *key, void *val
58void 59void
59destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle) 60destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
60{ 61{
61 if (handle->service->dir) 62 GNUNET_assert(handle);
62 save_handle_configuration(handle);
63 63
64 if (handle->operation) 64 if (handle->service->dir)
65 GNUNET_IDENTITY_cancel (handle->operation); 65 save_handle_configuration (handle);
66 66
67 if (handle->name) 67 if (handle->name)
68 GNUNET_free(handle->name); 68 GNUNET_free(handle->name);
@@ -74,8 +74,10 @@ destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
74} 74}
75 75
76void 76void
77get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir) 77get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir)
78{ 78{
79 GNUNET_assert((handle) && (dir));
80
79 if (name) 81 if (name)
80 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities", 82 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
81 DIR_SEPARATOR, name, DIR_SEPARATOR); 83 DIR_SEPARATOR, name, DIR_SEPARATOR);
@@ -87,11 +89,15 @@ get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *n
87static int 89static int
88create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 90create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
89{ 91{
90 struct GNUNET_ShortHashCode *random_id = generate_service_new_member_id (handle->service, key); 92 GNUNET_assert((handle) && (key));
93
94 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
91 95
92 if (!random_id) 96 if (!random_id)
93 return GNUNET_NO; 97 return GNUNET_NO;
94 98
99 generate_free_member_id (random_id, NULL);
100
95 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id, 101 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
96 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 102 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
97 { 103 {
@@ -99,8 +105,8 @@ create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const
99 return GNUNET_NO; 105 return GNUNET_NO;
100 } 106 }
101 107
102 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", 108 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
103 GNUNET_sh2s(random_id), GNUNET_h2s(key)); 109 GNUNET_h2s (key));
104 110
105 return GNUNET_YES; 111 return GNUNET_YES;
106} 112}
@@ -108,48 +114,61 @@ create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const
108const struct GNUNET_ShortHashCode* 114const struct GNUNET_ShortHashCode*
109get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 115get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
110{ 116{
117 GNUNET_assert((handle) && (key));
118
111 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); 119 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
112} 120}
113 121
114void 122int
115change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 123change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
116 const struct GNUNET_ShortHashCode *unique_id) 124 const struct GNUNET_ShortHashCode *unique_id)
117{ 125{
118 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); 126 GNUNET_assert((handle) && (key) && (unique_id));
119
120 if (member_id)
121 {
122 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Changed a member id (%s) for room (%s) ",
123 GNUNET_sh2s(member_id), GNUNET_h2s(key));
124 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "into (%s).\n",
125 GNUNET_sh2s(unique_id));
126
127 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
128
129 struct GNUNET_MESSENGER_MemberMessage *msg;
130 struct GNUNET_MQ_Envelope *env;
131 127
132 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID); 128 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
133
134 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
135 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
136 129
137 GNUNET_MQ_send (handle->mq, env); 130 if (!member_id)
138 }
139 else
140 { 131 {
141 member_id = GNUNET_new(struct GNUNET_ShortHashCode); 132 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
142 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id)); 133 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
143 134
144 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id, 135 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
145 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
137 {
146 GNUNET_free(member_id); 138 GNUNET_free(member_id);
139 return GNUNET_SYSERR;
140 }
147 } 141 }
142
143 if (0 == GNUNET_memcmp(unique_id, member_id))
144 goto send_message_to_client;
145
146 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
147 GNUNET_h2s (key));
148
149 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
150
151 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
152
153 struct GNUNET_MESSENGER_MemberMessage *msg;
154 struct GNUNET_MQ_Envelope *env;
155
156send_message_to_client:
157
158 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
159
160 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
161 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
162
163 GNUNET_MQ_send (handle->mq, env);
164 return GNUNET_OK;
148} 165}
149 166
150static void 167static void
151change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 168change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
152{ 169{
170 GNUNET_assert(handle);
171
153 if (handle->name) 172 if (handle->name)
154 GNUNET_free(handle->name); 173 GNUNET_free(handle->name);
155 174
@@ -173,25 +192,67 @@ change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
173} 192}
174 193
175static void 194static void
176change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, struct GNUNET_MESSENGER_Ego *ego) 195change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
177{ 196{
197 GNUNET_assert(handle);
198
178 handle->ego = ego; 199 handle->ego = ego;
179 200
180 ego = get_handle_ego(handle); 201 ego = get_handle_ego (handle);
202
203 const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
181 204
182 struct GNUNET_MESSENGER_KeyMessage *msg; 205 struct GNUNET_MESSENGER_KeyMessage *msg;
183 struct GNUNET_MQ_Envelope *env; 206 struct GNUNET_MQ_Envelope *env;
184 207
185 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY); 208 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
186 209
187 GNUNET_memcpy(&(msg->pubkey), &(ego->pub), sizeof(ego->pub)); 210 char *extra = ((char*) msg) + sizeof(*msg);
211
212 if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
213 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
188 214
189 GNUNET_MQ_send (handle->mq, env); 215 GNUNET_MQ_send (handle->mq, env);
190} 216}
191 217
192struct GNUNET_MESSENGER_Ego* 218struct GNUNET_MESSENGER_MessageHandle
193get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle) 219{
220 struct GNUNET_MESSENGER_SrvHandle *handle;
221 struct GNUNET_MESSENGER_Message *message;
222};
223
224static int
225iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value)
226{
227 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
228
229 send_handle_message (msg_handle->handle, key, msg_handle->message);
230
231 return GNUNET_YES;
232}
233
234void
235set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
236{
237 GNUNET_assert((handle) && (ego));
238
239 struct GNUNET_MESSENGER_MessageHandle msg_handle;
240
241 msg_handle.handle = handle;
242 msg_handle.message = create_message_key (&(ego->priv));
243
244 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
245
246 destroy_message (msg_handle.message);
247
248 change_handle_ego (handle, ego);
249}
250
251const struct GNUNET_MESSENGER_Ego*
252get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
194{ 253{
254 GNUNET_assert(handle);
255
195 static struct GNUNET_MESSENGER_Ego anonymous; 256 static struct GNUNET_MESSENGER_Ego anonymous;
196 static int read_keys = 0; 257 static int read_keys = 0;
197 258
@@ -200,99 +261,86 @@ get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle)
200 261
201 if (!read_keys) 262 if (!read_keys)
202 { 263 {
203 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous (); 264 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
204 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key(ego), sizeof(anonymous.priv)); 265 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
205 GNUNET_IDENTITY_ego_get_public_key(ego, &(anonymous.pub)); 266 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
206 read_keys = 1; 267 read_keys = 1;
207 } 268 }
208 269
209 return &anonymous; 270 return &anonymous;
210} 271}
211 272
212void 273static void
213setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 274callback_setup_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
214{ 275{
276 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
277
278 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
279
215 change_handle_name (handle, name); 280 change_handle_name (handle, name);
216 change_handle_ego (handle, handle->name? lookup_service_ego(handle->service, handle->name) : NULL); 281 change_handle_ego (handle, ego);
217 282
218 if (handle->service->dir) 283 if (handle->service->dir)
219 load_handle_configuration(handle); 284 load_handle_configuration (handle);
220} 285}
221 286
222struct GNUNET_MESSENGER_MessageHandle 287void
223{ 288setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
224 struct GNUNET_MESSENGER_SrvHandle *handle;
225 struct GNUNET_MESSENGER_Message *message;
226};
227
228static int
229iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value)
230{ 289{
231 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls; 290 GNUNET_assert(handle);
232 291
233 send_handle_message (msg_handle->handle, key, msg_handle->message); 292 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
234 293
235 return GNUNET_YES; 294 lookup_store_ego (store, name, callback_setup_handle_name, handle);
236} 295}
237 296
238static void 297static void
239callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) 298callback_update_handle (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
240{ 299{
241 struct GNUNET_MESSENGER_SrvHandle *handle = cls; 300 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
242 301
243 handle->operation = NULL; 302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
244 303
245 if (emsg) 304 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
246 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
247 305
248 if (key) 306 if (!ego)
249 { 307 create_store_ego(store, handle->name, handle);
250 struct GNUNET_MESSENGER_MessageHandle msg_handle; 308 else
251 309 change_handle_ego (handle, ego);
252 msg_handle.handle = handle;
253 msg_handle.message = create_message_key (key);
254
255 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
256
257 destroy_message (msg_handle.message);
258
259 update_service_ego(handle->service, handle->name, key);
260
261 change_handle_ego (handle, lookup_service_ego(handle->service, handle->name));
262 }
263} 310}
264 311
265int 312void
266update_handle (struct GNUNET_MESSENGER_SrvHandle *handle) 313update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
267{ 314{
268 GNUNET_assert(handle); 315 GNUNET_assert(handle);
269 316
270 if (!handle->name) 317 if (!handle->name)
271 return GNUNET_SYSERR; 318 {
272 319 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
273 struct GNUNET_MESSENGER_Ego *ego = lookup_service_ego(handle->service, handle->name); 320 return;
321 }
274 322
275 if (!ego) 323 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
276 handle->operation = GNUNET_IDENTITY_create (handle->service->identity, handle->name, NULL,
277 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, handle);
278 else
279 change_handle_ego (handle, ego);
280 324
281 return GNUNET_OK; 325 lookup_store_ego (store, handle->name, callback_update_handle, handle);
282} 326}
283 327
284int 328static void
285set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) 329callback_set_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
286{ 330{
287 GNUNET_assert(handle); 331 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
288 332
289 if ((name) && (lookup_service_ego(handle->service, name))) 333 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
290 return GNUNET_NO; 334
335 if (ego)
336 {
337 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
338 return;
339 }
291 340
292 struct GNUNET_IDENTITY_Operation *operation = handle->operation; 341 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
293 342
294 if (handle->name) 343 int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
295 handle->operation = GNUNET_IDENTITY_rename (handle->service->identity, handle->name, name, NULL, NULL);
296 344
297 char *old_dir; 345 char *old_dir;
298 get_handle_data_subdir (handle, handle->name, &old_dir); 346 get_handle_data_subdir (handle, handle->name, &old_dir);
@@ -323,29 +371,42 @@ set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
323 destroy_message (msg_handle.message); 371 destroy_message (msg_handle.message);
324 372
325 change_handle_name (handle, name); 373 change_handle_name (handle, name);
326
327 if (operation)
328 GNUNET_IDENTITY_cancel (operation);
329 } 374 }
330 else 375 else
376 rename_ego_in_store = GNUNET_NO;
377
378 GNUNET_free(old_dir);
379 GNUNET_free(new_dir);
380
381 if (GNUNET_YES == rename_ego_in_store)
382 rename_store_ego(store, handle->name, name);
383}
384
385void
386set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
387{
388 GNUNET_assert(handle);
389
390 if (!name)
331 { 391 {
332 if (handle->operation) 392 if (handle->ego)
333 { 393 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
334 GNUNET_IDENTITY_cancel (handle->operation); 394 else
395 change_handle_name (handle, name);
335 396
336 handle->operation = operation; 397 return;
337 }
338 } 398 }
339 399
340 GNUNET_free(old_dir); 400 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
341 GNUNET_free(new_dir);
342 401
343 return (result == 0 ? GNUNET_OK : GNUNET_NO); 402 lookup_store_ego (store, name, callback_set_handle_name, handle);
344} 403}
345 404
346int 405int
347open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 406open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
348{ 407{
408 GNUNET_assert((handle) && (key));
409
349 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) 410 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
350 return GNUNET_NO; 411 return GNUNET_NO;
351 412
@@ -356,6 +417,8 @@ int
356entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, 417entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
357 const struct GNUNET_HashCode *key) 418 const struct GNUNET_HashCode *key)
358{ 419{
420 GNUNET_assert((handle) && (door) && (key));
421
359 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) 422 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
360 return GNUNET_NO; 423 return GNUNET_NO;
361 424
@@ -365,6 +428,8 @@ entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
365int 428int
366close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) 429close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
367{ 430{
431 GNUNET_assert((handle) && (key));
432
368 if (!get_handle_member_id (handle, key)) 433 if (!get_handle_member_id (handle, key))
369 return GNUNET_NO; 434 return GNUNET_NO;
370 435
@@ -373,8 +438,10 @@ close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
373 438
374int 439int
375send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 440send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
376 struct GNUNET_MESSENGER_Message *message) 441 const struct GNUNET_MESSENGER_Message *message)
377{ 442{
443 GNUNET_assert((handle) && (key) && (message));
444
378 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); 445 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
379 446
380 if (!id) 447 if (!id)
@@ -391,45 +458,120 @@ send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNU
391 return GNUNET_NO; 458 return GNUNET_NO;
392 } 459 }
393 460
394 struct GNUNET_HashCode hash; 461 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
395 462
396 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(*id)); 463 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
397 464
398 send_room_message (room, handle, message, &hash); 465 return send_room_message (room, handle, msg);
399 return GNUNET_YES; 466}
467
468static const struct GNUNET_HashCode*
469get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
470{
471 if (session->next)
472 return get_next_member_session_contect (session->next);
473 else
474 return get_member_session_context(session);
475}
476
477void
478notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
479 const struct GNUNET_MESSENGER_MemberSession *session,
480 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
481{
482 GNUNET_assert((handle) && (key) && (session) && (message) && (hash));
483
484 if ((!handle->mq) || (!get_handle_member_id (handle, key)))
485 {
486 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
487 return;
488 }
489
490 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
491
492 struct GNUNET_HashCode sender;
493 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
494
495 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
496
497 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
498
499 struct GNUNET_MESSENGER_Message *private_message = NULL;
500
501 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
502 {
503 private_message = copy_message(message);
504
505 if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
506 {
507 destroy_message(private_message);
508 private_message = NULL;
509 }
510 else
511 message = private_message;
512 }
513
514 struct GNUNET_MESSENGER_RecvMessage *msg;
515 struct GNUNET_MQ_Envelope *env;
516
517 uint16_t length = get_message_size (message, GNUNET_YES);
518
519 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
520
521 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
522 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
523 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
524 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
525
526 msg->flags = (uint32_t) (
527 private_message? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
528 );
529
530 char *buffer = ((char*) msg) + sizeof(*msg);
531 encode_message (message, length, buffer, GNUNET_YES);
532
533 if (private_message)
534 destroy_message(private_message);
535
536 GNUNET_MQ_send (handle->mq, env);
400} 537}
401 538
402static int callback_scan_for_rooms(void* cls, const char *filename) { 539static int
403 struct GNUNET_MESSENGER_SrvHandle* handle = cls; 540callback_scan_for_rooms (void *cls, const char *filename)
541{
542 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
404 543
405 struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); 544 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
406 545
407 if ((GNUNET_YES == GNUNET_DISK_file_test(filename)) && 546 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
408 (GNUNET_OK == GNUNET_CONFIGURATION_parse(cfg, filename)))
409 { 547 {
410 struct GNUNET_HashCode key; 548 struct GNUNET_HashCode key;
411 struct GNUNET_ShortHashCode member_id; 549 struct GNUNET_ShortHashCode member_id;
412 550
413 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "key", &key, sizeof(key))) && 551 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
414 (GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "member_id", &member_id, sizeof(member_id)))) 552 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
415 change_handle_member_id(handle, &key, &member_id); 553 change_handle_member_id (handle, &key, &member_id);
416 } 554 }
417 555
418 GNUNET_CONFIGURATION_destroy(cfg); 556 GNUNET_CONFIGURATION_destroy (cfg);
419 return GNUNET_OK; 557 return GNUNET_OK;
420} 558}
421 559
422void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) { 560void
423 char* id_dir; 561load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
424 get_handle_data_subdir(handle, handle->name, &id_dir); 562{
563 GNUNET_assert(handle);
425 564
426 if (GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_YES)) 565 char *id_dir;
566 get_handle_data_subdir (handle, handle->name, &id_dir);
567
568 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
427 { 569 {
428 char* scan_dir; 570 char *scan_dir;
429 GNUNET_asprintf(&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); 571 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
430 572
431 if (GNUNET_OK == GNUNET_DISK_directory_test(scan_dir, GNUNET_YES)) 573 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
432 GNUNET_DISK_directory_scan(scan_dir, callback_scan_for_rooms, handle); 574 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
433 575
434 GNUNET_free(scan_dir); 576 GNUNET_free(scan_dir);
435 } 577 }
@@ -438,63 +580,64 @@ void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) {
438} 580}
439 581
440static int 582static int
441iterate_save_rooms(void* cls, const struct GNUNET_HashCode* key, void* value) 583iterate_save_rooms (void *cls, const struct GNUNET_HashCode *key, void *value)
442{ 584{
443 struct GNUNET_MESSENGER_SrvHandle* handle = cls; 585 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
444 struct GNUNET_ShortHashCode* member_id = value; 586 struct GNUNET_ShortHashCode *member_id = value;
445 587
446 char* id_dir; 588 char *id_dir;
447 get_handle_data_subdir(handle, handle->name, &id_dir); 589 get_handle_data_subdir (handle, handle->name, &id_dir);
448 590
449 char* filename; 591 char *filename;
450 GNUNET_asprintf(&filename, "%s%s%c%s.cfg", 592 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
451 id_dir, "rooms", DIR_SEPARATOR,
452 GNUNET_h2s(key));
453 593
454 GNUNET_free(id_dir); 594 GNUNET_free(id_dir);
455 595
456 struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); 596 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
457 597
458 char* key_data = GNUNET_STRINGS_data_to_string_alloc(key, sizeof(*key)); 598 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
459 599
460 if (key_data) 600 if (key_data)
461 { 601 {
462 GNUNET_CONFIGURATION_set_value_string(cfg, "room", "key", key_data); 602 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
463 603
464 GNUNET_free(key_data); 604 GNUNET_free(key_data);
465 } 605 }
466 606
467 char* member_id_data = GNUNET_STRINGS_data_to_string_alloc(member_id, sizeof(*member_id)); 607 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
468 608
469 if (member_id_data) 609 if (member_id_data)
470 { 610 {
471 GNUNET_CONFIGURATION_set_value_string(cfg, "room", "member_id", member_id_data); 611 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
472 612
473 GNUNET_free(member_id_data); 613 GNUNET_free(member_id_data);
474 } 614 }
475 615
476 GNUNET_CONFIGURATION_write(cfg, filename); 616 GNUNET_CONFIGURATION_write (cfg, filename);
477 GNUNET_CONFIGURATION_destroy(cfg); 617 GNUNET_CONFIGURATION_destroy (cfg);
478 618
479 GNUNET_free(filename); 619 GNUNET_free(filename);
480 620
481 return GNUNET_YES; 621 return GNUNET_YES;
482} 622}
483 623
484void save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) 624void
625save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
485{ 626{
486 char* id_dir; 627 GNUNET_assert(handle);
487 get_handle_data_subdir(handle, handle->name, &id_dir); 628
629 char *id_dir;
630 get_handle_data_subdir (handle, handle->name, &id_dir);
488 631
489 if ((GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_NO)) || 632 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
490 (GNUNET_OK == GNUNET_DISK_directory_create(id_dir))) 633 == GNUNET_DISK_directory_create (id_dir)))
491 { 634 {
492 char* save_dir; 635 char *save_dir;
493 GNUNET_asprintf(&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); 636 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
494 637
495 if ((GNUNET_YES == GNUNET_DISK_directory_test(save_dir, GNUNET_NO)) || 638 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
496 (GNUNET_OK == GNUNET_DISK_directory_create(save_dir))) 639 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
497 GNUNET_CONTAINER_multihashmap_iterate(handle->member_ids, iterate_save_rooms, handle); 640 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
498 641
499 GNUNET_free(save_dir); 642 GNUNET_free(save_dir);
500 } 643 }
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h
index 81cf377a8..70b2cac6d 100644
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ b/src/messenger/gnunet-service-messenger_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -35,6 +35,7 @@
35#include "gnunet_mq_lib.h" 35#include "gnunet_mq_lib.h"
36 36
37#include "gnunet-service-messenger_service.h" 37#include "gnunet-service-messenger_service.h"
38#include "gnunet-service-messenger_member_session.h"
38 39
39#include "messenger_api_ego.h" 40#include "messenger_api_ego.h"
40#include "messenger_api_message.h" 41#include "messenger_api_message.h"
@@ -46,9 +47,7 @@ struct GNUNET_MESSENGER_SrvHandle
46 47
47 char *name; 48 char *name;
48 49
49 struct GNUNET_IDENTITY_Operation *operation; 50 const struct GNUNET_MESSENGER_Ego *ego;
50
51 struct GNUNET_MESSENGER_Ego *ego;
52 51
53 struct GNUNET_CONTAINER_MultiHashMap *member_ids; 52 struct GNUNET_CONTAINER_MultiHashMap *member_ids;
54}; 53};
@@ -56,8 +55,8 @@ struct GNUNET_MESSENGER_SrvHandle
56/** 55/**
57 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue). 56 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue).
58 * 57 *
59 * @param service MESSENGER Service 58 * @param[in/out] service MESSENGER Service
60 * @param mq Message queue 59 * @param[in/out] mq Message queue
61 * @return New handle 60 * @return New handle
62 */ 61 */
63struct GNUNET_MESSENGER_SrvHandle* 62struct GNUNET_MESSENGER_SrvHandle*
@@ -66,7 +65,7 @@ create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle
66/** 65/**
67 * Destroys a handle and frees its memory fully. 66 * Destroys a handle and frees its memory fully.
68 * 67 *
69 * @param handle Handle 68 * @param[in/out] handle Handle
70 */ 69 */
71void 70void
72destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle); 71destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
@@ -75,52 +74,63 @@ destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
75 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter 74 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter
76 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages. 75 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages.
77 * 76 *
78 * @param handle Handle 77 * @param[in] handle Handle
79 * @param name Potential name of the handle 78 * @param[in] name Potential name of the handle
80 * @param dir[out] Path to store data 79 * @param[out] dir Path to store data
81 */ 80 */
82void 81void
83get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir); 82get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir);
84 83
85/** 84/**
86 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>. 85 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>.
87 * 86 *
88 * If the handle is not a member of the specific <i>room</i>, NULL gets returned. 87 * If the handle is not a member of the specific <i>room</i>, NULL gets returned.
89 * 88 *
90 * @param handle Handle 89 * @param[in] handle Handle
91 * @param key Key of a room 90 * @param[in] key Key of a room
92 * @return Member id or NULL 91 * @return Member id or NULL
93 */ 92 */
94const struct GNUNET_ShortHashCode* 93const struct GNUNET_ShortHashCode*
95get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 94get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
96 95
97/** 96/**
98 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>. 97 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>
98 * and returns GNUNET_OK on success.
99 * 99 *
100 * The client connected to the <i>handle</i> will be informed afterwards automatically. 100 * The client connected to the <i>handle</i> will be informed afterwards automatically.
101 * 101 *
102 * @param handle Handle 102 * @param[in/out] handle Handle
103 * @param key Key of a room 103 * @param[in] key Key of a room
104 * @param unique_id Unique member id 104 * @param[in] unique_id Unique member id
105 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
105 */ 106 */
106void 107int
107change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 108change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
108 const struct GNUNET_ShortHashCode *unique_id); 109 const struct GNUNET_ShortHashCode *unique_id);
109 110
110/** 111/**
112 * Sets the EGO used by a given <i>handle</i>.
113 *
114 * @param[in/out] handle Handle
115 * @param[in] ego EGO keypair
116 */
117void
118set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego);
119
120/**
111 * Returns the EGO used by a given <i>handle</i>. 121 * Returns the EGO used by a given <i>handle</i>.
112 * 122 *
113 * @param handle Handle 123 * @param[in] handle Handle
114 * @return EGO keypair 124 * @return EGO keypair
115 */ 125 */
116struct GNUNET_MESSENGER_Ego* 126const struct GNUNET_MESSENGER_Ego*
117get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle); 127get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
118 128
119/** 129/**
120 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>. 130 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>.
121 * 131 *
122 * @param handle Handle 132 * @param[in/out] handle Handle
123 * @param name Name (optionally: valid EGO name) 133 * @param[in] name Name (optionally: valid EGO name)
124 */ 134 */
125void 135void
126setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); 136setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
@@ -129,10 +139,9 @@ setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
129 * Tries to change the keypair of an EGO of a <i>handle</i> under the same name and informs all rooms 139 * Tries to change the keypair of an EGO of a <i>handle</i> under the same name and informs all rooms
130 * about the change automatically. 140 * about the change automatically.
131 * 141 *
132 * @param handle Handle 142 * @param[in/out] handle Handle
133 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
134 */ 143 */
135int 144void
136update_handle (struct GNUNET_MESSENGER_SrvHandle *handle); 145update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
137 146
138/** 147/**
@@ -141,20 +150,19 @@ update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
141 * 150 *
142 * The client connected to the <i>handle</i> will be informed afterwards automatically. 151 * The client connected to the <i>handle</i> will be informed afterwards automatically.
143 * 152 *
144 * @param handle Handle 153 * @param[in/out] handle Handle
145 * @param name New name 154 * @param[in] name New name
146 * @return GNUNET_OK on success, otherwise GNUNET_NO
147 */ 155 */
148int 156void
149set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); 157set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
150 158
151/** 159/**
152 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the 160 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the
153 * room from the handles service. 161 * room from the handles service.
154 * 162 *
155 * @param handle Handle 163 * @param[in/out] handle Handle
156 * @param key Key of a room 164 * @param[in] key Key of a room
157 * @return GNUNET_YES on success, otherwise GNUNET_NO 165 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
158 */ 166 */
159int 167int
160open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 168open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
@@ -163,10 +171,10 @@ open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET
163 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room 171 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room
164 * through a tunnel to a peer identified by a given <i>door</i> (peer identity). 172 * through a tunnel to a peer identified by a given <i>door</i> (peer identity).
165 * 173 *
166 * @param handle Handle 174 * @param[in/out] handle Handle
167 * @param door Peer identity 175 * @param[in] door Peer identity
168 * @param key Key of a room 176 * @param[in] key Key of a room
169 * @return GNUNET_YES on success, otherwise GNUNET_NO 177 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
170 */ 178 */
171int 179int
172entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, 180entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
@@ -176,9 +184,9 @@ entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
176 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle 184 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle
177 * from this service is still a member of it. 185 * from this service is still a member of it.
178 * 186 *
179 * @param handle Handle 187 * @param[in/out] handle Handle
180 * @param key Key of a room 188 * @param[in] key Key of a room
181 * @return GNUNET_YES on success, otherwise GNUNET_NO 189 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
182 */ 190 */
183int 191int
184close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); 192close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
@@ -186,31 +194,45 @@ close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNE
186/** 194/**
187 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>. 195 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>.
188 * 196 *
189 * @param handle Handle 197 * @param[in/out] handle Handle
190 * @param key Key of a room 198 * @param[in] key Key of a room
191 * @param message Message 199 * @param[in] message Message
192 * @return GNUNET_YES on success, otherwise GNUNET_NO 200 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
193 */ 201 */
194int 202int
195send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, 203send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
196 struct GNUNET_MESSENGER_Message *message); 204 const struct GNUNET_MESSENGER_Message *message);
205
206/**
207 * Notifies the handle that a new message was received or sent.
208 *
209 * @param[in/out] handle Handle
210 * @param[in] key Key of room
211 * @param[in] session Member session
212 * @param[in] message Message
213 * @param[in] hash Hash of message
214 */
215void
216notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
217 const struct GNUNET_MESSENGER_MemberSession *session,
218 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
197 219
198/** 220/**
199 * Loads member ids and other potential configuration from a given <i>handle</i> which 221 * Loads member ids and other potential configuration from a given <i>handle</i> which
200 * depends on the given name the <i>handle</i> uses. 222 * depends on the given name the <i>handle</i> uses.
201 * 223 *
202 * @param handle Handle 224 * @param[out] handle Handle
203 */ 225 */
204void 226void
205load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); 227load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
206 228
207/** 229/**
208 * Saves member ids and other potential configuration from a given <i>handle</i> which 230 * Saves member ids and other potential configuration from a given <i>handle</i> which
209 * depends on the given name the <i>handle</i> uses. 231 * depends on the given name the <i>handle</i> uses.
210 * 232 *
211 * @param handle Handle 233 * @param[in] handle Handle
212 */ 234 */
213void 235void
214save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); 236save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
215 237
216#endif //GNUNET_SERVICE_MESSENGER_HANDLE_H 238#endif //GNUNET_SERVICE_MESSENGER_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_list_handles.c b/src/messenger/gnunet-service-messenger_list_handles.c
index 16a160dea..adcbf6a42 100644
--- a/src/messenger/gnunet-service-messenger_list_handles.c
+++ b/src/messenger/gnunet-service-messenger_list_handles.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -55,8 +55,10 @@ clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
55} 55}
56 56
57void 57void
58add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) 58add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
59{ 59{
60 GNUNET_assert((handles) && (handle));
61
60 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle); 62 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle);
61 63
62 element->handle = handle; 64 element->handle = handle;
@@ -65,8 +67,10 @@ add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle)
65} 67}
66 68
67int 69int
68remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) 70remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
69{ 71{
72 GNUNET_assert((handles) && (handle));
73
70 struct GNUNET_MESSENGER_ListHandle *element; 74 struct GNUNET_MESSENGER_ListHandle *element;
71 75
72 for (element = handles->head; element; element = element->next) 76 for (element = handles->head; element; element = element->next)
@@ -82,9 +86,11 @@ remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle)
82 return GNUNET_YES; 86 return GNUNET_YES;
83} 87}
84 88
85void* 89struct GNUNET_MESSENGER_SrvHandle*
86find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key) 90find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key)
87{ 91{
92 GNUNET_assert((handles) && (key));
93
88 struct GNUNET_MESSENGER_ListHandle *element; 94 struct GNUNET_MESSENGER_ListHandle *element;
89 95
90 for (element = handles->head; element; element = element->next) 96 for (element = handles->head; element; element = element->next)
diff --git a/src/messenger/gnunet-service-messenger_list_handles.h b/src/messenger/gnunet-service-messenger_list_handles.h
index fe92cc58a..9f7ca725f 100644
--- a/src/messenger/gnunet-service-messenger_list_handles.h
+++ b/src/messenger/gnunet-service-messenger_list_handles.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -30,12 +30,14 @@
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32 32
33struct GNUNET_MESSENGER_SrvHandle;
34
33struct GNUNET_MESSENGER_ListHandle 35struct GNUNET_MESSENGER_ListHandle
34{ 36{
35 struct GNUNET_MESSENGER_ListHandle *prev; 37 struct GNUNET_MESSENGER_ListHandle *prev;
36 struct GNUNET_MESSENGER_ListHandle *next; 38 struct GNUNET_MESSENGER_ListHandle *next;
37 39
38 void *handle; 40 struct GNUNET_MESSENGER_SrvHandle *handle;
39}; 41};
40 42
41struct GNUNET_MESSENGER_ListHandles 43struct GNUNET_MESSENGER_ListHandles
@@ -45,17 +47,17 @@ struct GNUNET_MESSENGER_ListHandles
45}; 47};
46 48
47/** 49/**
48 * Initializes list of handles as empty list. 50 * Initializes list of <i>handles</i> as empty list.
49 * 51 *
50 * @param handles List of handles 52 * @param[out] handles List of handles
51 */ 53 */
52void 54void
53init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); 55init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
54 56
55/** 57/**
56 * Destroys remaining handles and clears the list. 58 * Destroys remaining <i>handles</i> and clears the list.
57 * 59 *
58 * @param handles List of handles 60 * @param[in/out] handles List of handles
59 */ 61 */
60void 62void
61clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); 63clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
@@ -63,34 +65,34 @@ clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
63/** 65/**
64 * Adds a specific <i>handle</i> to the end of the list. 66 * Adds a specific <i>handle</i> to the end of the list.
65 * 67 *
66 * @param handles List of handles 68 * @param[in/out] handles List of handles
67 * @param handle Handle 69 * @param[in/out] handle Handle
68 */ 70 */
69void 71void
70add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); 72add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
71 73
72/** 74/**
73 * Removes the first entry matching with a specific <i>handle</i> from the list and 75 * Removes the first entry matching with a specific <i>handle</i> from the list of
74 * returns GNUNET_YES on success or GNUNET_NO on failure. 76 * <i>handles</i> and returns #GNUNET_YES on success or #GNUNET_NO on failure.
75 * 77 *
76 * @param handles List of handles 78 * @param[in/out] handles List of handles
77 * @param handle Handle 79 * @param[in/out] handle Handle
78 * @return GNUNET_YES on success, otherwise GNUNET_NO 80 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
79 */ 81 */
80int 82int
81remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); 83remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
82 84
83/** 85/**
84 * Searches linearly through the list of handles for members of a specific room 86 * Searches linearly through the list of <i>handles</i> for members of a specific room
85 * which is identified by a given <i>key</i>. 87 * which is identified by a given <i>key</i>.
86 * 88 *
87 * If no handle is found which is a current member, NULL gets returned. 89 * If no handle is found which is a current member, NULL gets returned.
88 * 90 *
89 * @param handles List of handles 91 * @param[in] handles List of handles
90 * @param key Common key of a room 92 * @param[in] key Common key of a room
91 * @return First handle which is a current member 93 * @return First handle which is a current member
92 */ 94 */
93void* 95struct GNUNET_MESSENGER_SrvHandle*
94find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key); 96find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key);
95 97
96#endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H 98#endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H
diff --git a/src/messenger/gnunet-service-messenger_list_messages.c b/src/messenger/gnunet-service-messenger_list_messages.c
index c4f1f7043..bb6086e41 100644
--- a/src/messenger/gnunet-service-messenger_list_messages.c
+++ b/src/messenger/gnunet-service-messenger_list_messages.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -54,6 +54,8 @@ clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
54void 54void
55add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) 55add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
56{ 56{
57 GNUNET_assert((messages) && (hash));
58
57 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage); 59 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage);
58 60
59 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode)); 61 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
@@ -62,8 +64,21 @@ add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const stru
62} 64}
63 65
64void 66void
67copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin)
68{
69 GNUNET_assert((messages) && (origin));
70
71 struct GNUNET_MESSENGER_ListMessage *element;
72
73 for (element = origin->head; element; element = element->next)
74 add_to_list_messages (messages, &(element->hash));
75}
76
77void
65remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) 78remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
66{ 79{
80 GNUNET_assert((messages) && (hash));
81
67 struct GNUNET_MESSENGER_ListMessage *element; 82 struct GNUNET_MESSENGER_ListMessage *element;
68 83
69 for (element = messages->head; element; element = element->next) 84 for (element = messages->head; element; element = element->next)
@@ -74,3 +89,62 @@ remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const
74 break; 89 break;
75 } 90 }
76} 91}
92
93void
94load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
95{
96 GNUNET_assert((messages) && (path));
97
98 if (GNUNET_YES != GNUNET_DISK_file_test (path))
99 return;
100
101 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
102
103 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
104 path, GNUNET_DISK_OPEN_READ, permission
105 );
106
107 if (!handle)
108 return;
109
110 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
111
112 struct GNUNET_HashCode hash;
113 ssize_t len;
114
115 do {
116 len = GNUNET_DISK_file_read(handle, &hash, sizeof(hash));
117
118 if (len != sizeof(hash))
119 break;
120
121 add_to_list_messages(messages, &hash);
122 } while (len == sizeof(hash));
123
124 GNUNET_DISK_file_close(handle);
125}
126
127void
128save_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
129{
130 GNUNET_assert((messages) && (path));
131
132 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
133
134 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
135 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
136 );
137
138 if (!handle)
139 return;
140
141 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
142
143 struct GNUNET_MESSENGER_ListMessage *element;
144
145 for (element = messages->head; element; element = element->next)
146 GNUNET_DISK_file_write(handle, &(element->hash), sizeof(element->hash));
147
148 GNUNET_DISK_file_sync(handle);
149 GNUNET_DISK_file_close(handle);
150}
diff --git a/src/messenger/gnunet-service-messenger_list_messages.h b/src/messenger/gnunet-service-messenger_list_messages.h
index 266c30ec6..9ace84cbf 100644
--- a/src/messenger/gnunet-service-messenger_list_messages.h
+++ b/src/messenger/gnunet-service-messenger_list_messages.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32#include "gnunet_disk_lib.h"
32 33
33struct GNUNET_MESSENGER_ListMessage 34struct GNUNET_MESSENGER_ListMessage
34{ 35{
@@ -47,7 +48,7 @@ struct GNUNET_MESSENGER_ListMessages
47/** 48/**
48 * Initializes list of message hashes as empty list. 49 * Initializes list of message hashes as empty list.
49 * 50 *
50 * @param messages List of hashes 51 * @param[out] messages List of hashes
51 */ 52 */
52void 53void
53init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); 54init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
@@ -55,7 +56,7 @@ init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
55/** 56/**
56 * Clears the list of message hashes. 57 * Clears the list of message hashes.
57 * 58 *
58 * @param messages List of hashes 59 * @param[in/out] messages List of hashes
59 */ 60 */
60void 61void
61clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); 62clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
@@ -63,19 +64,46 @@ clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
63/** 64/**
64 * Adds a specific <i>hash</i> from a message to the end of the list. 65 * Adds a specific <i>hash</i> from a message to the end of the list.
65 * 66 *
66 * @param messages List of hashes 67 * @param[in/out] messages List of hashes
67 * @param hash Hash of message 68 * @param[in] hash Hash of message
68 */ 69 */
69void 70void
70add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); 71add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
71 72
72/** 73/**
74 * Copies all message hashes from an <i>origin</i> to another list.
75 *
76 * @param[in/out] messages Destination list of hashes
77 * @param[in] origin Source list of hashes
78 */
79void
80copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin);
81
82/**
73 * Removes the first entry with a matching <i>hash</i> from the list. 83 * Removes the first entry with a matching <i>hash</i> from the list.
74 * 84 *
75 * @param messages List of hashes 85 * @param[in/out] messages List of hashes
76 * @param hash Hash of message 86 * @param[in] hash Hash of message
77 */ 87 */
78void 88void
79remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); 89remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
80 90
91/**
92 * Loads the list of message hashes from a file under a given <i>path</i>.
93 *
94 * @param[out] messages List of hashes
95 * @param[in] path Path of file
96 */
97void
98load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
99
100/**
101 * Saves the list of message hashes to a file under a given <i>path</i>.
102 *
103 * @param[in] messages List of hashes
104 * @param[in] path Path of file
105 */
106void
107save_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
108
81#endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H 109#endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H
diff --git a/src/messenger/gnunet-service-messenger_member.c b/src/messenger/gnunet-service-messenger_member.c
new file mode 100644
index 000000000..6e39cec13
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member.c
@@ -0,0 +1,379 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_member.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member.h"
27
28#include "gnunet-service-messenger_member_session.h"
29
30struct GNUNET_MESSENGER_Member*
31create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
32{
33 GNUNET_assert (store);
34
35 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
36
37 member->store = store;
38
39 if (id)
40 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
41 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
42 {
43 GNUNET_free (member);
44 return NULL;
45 }
46
47 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
48
49 return member;
50}
51
52static int
53iterate_destroy_session (void *cls, const struct GNUNET_HashCode *key, void *value)
54{
55 struct GNUNET_MESSENGER_MemberSession *session = value;
56 destroy_member_session(session);
57 return GNUNET_YES;
58}
59
60void
61destroy_member (struct GNUNET_MESSENGER_Member *member)
62{
63 GNUNET_assert((member) && (member->sessions));
64
65 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
67
68 GNUNET_free (member);
69}
70
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member)
73{
74 GNUNET_assert (member);
75
76 return &(member->id);
77}
78
79static int
80callback_scan_for_sessions (void *cls, const char *filename)
81{
82 struct GNUNET_MESSENGER_Member *member = cls;
83
84 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
85 {
86 char *directory;
87
88 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
89
90 load_member_session(member, directory);
91 }
92
93 return GNUNET_OK;
94}
95
96void
97load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
98{
99 GNUNET_assert ((store) && (directory));
100
101 char *config_file;
102 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
103
104 struct GNUNET_MESSENGER_Member *member = NULL;
105
106 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
107 goto free_config;
108
109 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
110
111 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
112 {
113 struct GNUNET_ShortHashCode id;
114
115 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
116 goto destroy_config;
117
118 member = add_store_member(store, &id);
119 }
120
121destroy_config:
122
123 GNUNET_CONFIGURATION_destroy (cfg);
124
125free_config:
126 GNUNET_free(config_file);
127
128 if (!member)
129 return;
130
131 char *scan_dir;
132 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
133
134 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
135 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
136
137 GNUNET_free(scan_dir);
138}
139
140static int
141iterate_load_next_session (void *cls, const struct GNUNET_HashCode *key, void *value)
142{
143 const char* sessions_directory = cls;
144
145 char* load_dir;
146 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
147
148 struct GNUNET_MESSENGER_MemberSession *session = value;
149
150 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
151 load_member_session_next (session, load_dir);
152
153 GNUNET_free (load_dir);
154 return GNUNET_YES;
155}
156
157void
158load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory)
159{
160 GNUNET_assert ((member) && (directory));
161
162 char* load_dir;
163 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
164
165 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
166
167 GNUNET_free(load_dir);
168}
169
170static int
171iterate_save_session (void *cls, const struct GNUNET_HashCode *key, void *value)
172{
173 const char* sessions_directory = cls;
174
175 char* save_dir;
176 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
177
178 struct GNUNET_MESSENGER_MemberSession *session = value;
179
180 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
181 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
182 save_member_session (session, save_dir);
183
184 GNUNET_free (save_dir);
185 return GNUNET_YES;
186}
187
188void
189save_member (struct GNUNET_MESSENGER_Member *member, const char *directory)
190{
191 GNUNET_assert ((member) && (directory));
192
193 char *config_file;
194 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
195
196 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
197
198 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
199
200 if (id_data)
201 {
202 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
203
204 GNUNET_free(id_data);
205 }
206
207 GNUNET_CONFIGURATION_write (cfg, config_file);
208 GNUNET_CONFIGURATION_destroy (cfg);
209
210 GNUNET_free(config_file);
211
212 char* save_dir;
213 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
214
215 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
216 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
217 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
218
219 GNUNET_free(save_dir);
220}
221
222static void
223sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
224{
225 GNUNET_assert((session) && (next));
226
227 if (session == next)
228 return;
229
230 if (next->next)
231 sync_session_contact_from_next (session, next->next);
232 else
233 session->contact = next->contact;
234}
235
236static int
237iterate_sync_session_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
238{
239 struct GNUNET_MESSENGER_MemberSession *session = value;
240
241 if (session->next)
242 sync_session_contact_from_next (session, session->next);
243
244 return GNUNET_YES;
245}
246
247void
248sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
249{
250 GNUNET_assert ((member) && (member->sessions));
251
252 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
253}
254
255struct GNUNET_MESSENGER_MemberSession*
256get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
257{
258 GNUNET_assert ((member) && (public_key));
259
260 struct GNUNET_HashCode hash;
261 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
262
263 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
264}
265
266struct GNUNET_MESSENGER_ClosureSearchSession {
267 const struct GNUNET_MESSENGER_Message *message;
268 const struct GNUNET_HashCode *hash;
269
270 struct GNUNET_MESSENGER_MemberSession *match;
271};
272
273static int
274iterate_search_session (void *cls, const struct GNUNET_HashCode *key, void *value)
275{
276 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
277 struct GNUNET_MESSENGER_MemberSession *session = value;
278
279 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
280 return GNUNET_YES;
281
282 search->match = session;
283 return GNUNET_NO;
284}
285
286static struct GNUNET_MESSENGER_MemberSession*
287try_member_session (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
288{
289 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
290
291 if (session)
292 return session;
293
294 session = create_member_session(member, public_key);
295
296 if (session)
297 add_member_session(member, session);
298
299 return session;
300}
301
302struct GNUNET_MESSENGER_MemberSession*
303get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
304 const struct GNUNET_HashCode *hash)
305{
306 GNUNET_assert ((member) && (message) && (hash) &&
307 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
308
309 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
310 return try_member_session(member, &(message->body.info.host_key));
311 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
312 return try_member_session(member, &(message->body.join.key));
313
314 struct GNUNET_MESSENGER_ClosureSearchSession search;
315
316 search.message = message;
317 search.hash = hash;
318
319 search.match = NULL;
320 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
321
322 return search.match;
323}
324
325void
326add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
327{
328 if (!session)
329 return;
330
331 GNUNET_assert((member) && (session->member == member));
332
333 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
334
335 struct GNUNET_HashCode hash;
336 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
337
338 GNUNET_CONTAINER_multihashmap_put(member->sessions, &hash, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
339}
340
341void
342remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
343{
344 GNUNET_assert ((member) && (session) && (session->member == member));
345
346 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
347
348 struct GNUNET_HashCode hash;
349 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
350
351 GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session);
352}
353
354struct GNUNET_MESSENGER_ClosureIterateSessions {
355 GNUNET_MESSENGER_MemberIteratorCallback it;
356 void *cls;
357};
358
359static int
360iterate_member_sessions_it (void *cls, const struct GNUNET_HashCode *key, void *value)
361{
362 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
363 struct GNUNET_MESSENGER_MemberSession *session = value;
364
365 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
366}
367
368int
369iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
370{
371 GNUNET_assert ((member) && (member->sessions) && (it));
372
373 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
374
375 iterate.it = it;
376 iterate.cls = cls;
377
378 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
379}
diff --git a/src/messenger/gnunet-service-messenger_member.h b/src/messenger/gnunet-service-messenger_member.h
new file mode 100644
index 000000000..fb2e57cfb
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member.h
@@ -0,0 +1,170 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_member.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_H
28
29#include "messenger_api_contact.h"
30
31#include "gnunet-service-messenger_list_messages.h"
32#include "gnunet-service-messenger_member_store.h"
33#include "messenger_api_message.h"
34#include "messenger_api_util.h"
35
36struct GNUNET_MESSENGER_Member
37{
38 struct GNUNET_MESSENGER_MemberStore *store;
39 struct GNUNET_ShortHashCode id;
40
41 struct GNUNET_CONTAINER_MultiHashMap *sessions;
42};
43
44/**
45 * Creates and allocates a new member of a <i>room</i> with an optionally defined or
46 * random <i>id</i>.
47 *
48 * If the creation fails, NULL gets returned.
49 *
50 * @param[in/out] store Member store
51 * @param[in] id Member id or NULL
52 * @return New member or NULL
53 */
54struct GNUNET_MESSENGER_Member*
55create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
56
57/**
58 * Destroys a member and frees its memory fully.
59 *
60 * @param[in/out] member Member
61 */
62void
63destroy_member (struct GNUNET_MESSENGER_Member *member);
64
65/**
66 * Returns the current id of a given <i>member</i>.
67 *
68 * @param[in] member Member
69 * @return Member id
70 */
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member);
73
74/**
75 * Loads data from a <i>directory</i> into a new allocated and created member
76 * of a <i>store</i> if the required information can be read from the content
77 * of the given directory.
78 *
79 * @param[out] store Member store
80 * @param[in] directory Path to a directory
81 */
82void
83load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
84
85/**
86 * Loads data about next sessions from a <i>directory</i> into an empty loaded
87 * <i>member</i> which does not contain a fully built session graph yet.
88 *
89 * @param[in/out] member Member
90 * @param[in] directory Path to a directory
91 */
92void
93load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory);
94
95/**
96 * Saves data from a <i>member</i> into a directory which
97 * can be load to restore the member completely.
98 *
99 * @param[in] member Member
100 * @param[in] directory Path to a directory
101 */
102void
103save_member (struct GNUNET_MESSENGER_Member *member, const char *directory);
104
105/**
106 * Synchronizes contacts between all sessions from a given <i>member</i>
107 * and other sessions which are linked to them.
108 *
109 * @param[in/out] member Member
110 */
111void
112sync_member_contacts (struct GNUNET_MESSENGER_Member *member);
113
114/**
115 * Returns the member session of a <i>member</i> identified by a given public key.
116 * If the member does not provide a session with the given key, NULL gets returned.
117 *
118 * @param[in] member Member
119 * @param[in] public_key Public key of EGO
120 * @return Member session
121 */
122struct GNUNET_MESSENGER_MemberSession*
123get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key);
124
125/**
126 * Returns the member session of a <i>member</i> using a public key which can verify
127 * the signature of a given <i>message</i> and its <i>hash</i>. If the member does
128 * not provide a matching session, NULL gets returned.
129 *
130 * @param[in] member Member
131 * @param[in] message Message
132 * @param[in] hash Hash of message
133 * @return Member session
134 */
135struct GNUNET_MESSENGER_MemberSession*
136get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
137 const struct GNUNET_HashCode *hash);
138
139/**
140 * Adds a given member <i>session</i> to its <i>member</i>.
141 *
142 * @param[in/out] member Member
143 * @param[in/out] session Member session
144 */
145void
146add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
147
148/**
149 * Removes a given member <i>session</i> from its <i>member</i>.
150 *
151 * @param[in/out] member Member
152 * @param[in/out] session Member session
153 */
154void
155remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
156
157/**
158 * Iterate through all member sessions currently connected to a given <i>member</i>
159 * and call the provided iterator callback with a selected closure. The function
160 * will return the amount of member sessions it iterated through.
161 *
162 * @param[in/out] member Member
163 * @param[in] it Iterator callback
164 * @param[in/out] cls Closure
165 * @return Amount of sessions iterated through
166 */
167int
168iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void* cls);
169
170#endif //GNUNET_SERVICE_MESSENGER_MEMBER_H
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
new file mode 100644
index 000000000..636285d93
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_session.c
@@ -0,0 +1,707 @@
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 src/messenger/gnunet-service-messenger_member_session.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_session.h"
27
28#include "gnunet-service-messenger_room.h"
29#include "gnunet-service-messenger_message_store.h"
30
31#include "messenger_api_contact_store.h"
32
33struct GNUNET_MESSENGER_MemberSession*
34create_member_session (struct GNUNET_MESSENGER_Member *member,
35 const struct GNUNET_IDENTITY_PublicKey *pubkey)
36{
37 if ((!member) || (!pubkey) || (!(member->store)))
38 return NULL;
39
40 struct GNUNET_MESSENGER_MemberSession *session = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
41 session->member = member;
42
43 GNUNET_memcpy(&(session->public_key), pubkey, sizeof(session->public_key));
44
45 get_context_from_member (
46 get_member_session_key (session),
47 get_member_session_id (session),
48 &(session->context)
49 );
50
51 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
52
53 session->contact = get_store_contact(
54 store,
55 get_member_session_context (session),
56 get_member_session_public_key (session)
57 );
58
59 if (!(session->contact))
60 {
61 GNUNET_free(session);
62 return NULL;
63 }
64
65 increase_contact_rc (session->contact);
66
67 session->history = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
68
69 init_list_messages(&(session->messages));
70
71 session->next = NULL;
72
73 session->closed = GNUNET_NO;
74 session->completed = GNUNET_NO;
75
76 return session;
77}
78
79static void
80check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
81{
82 GNUNET_assert (session);
83
84 if (!session->messages.tail)
85 {
86 session->completed = GNUNET_YES;
87 goto completion;
88 }
89
90 const struct GNUNET_HashCode* start = &(session->messages.head->hash);
91 const struct GNUNET_HashCode* end = &(session->messages.tail->hash);
92
93 struct GNUNET_MESSENGER_ListMessages level;
94 init_list_messages(&level);
95
96 add_to_list_messages(&level, end);
97
98 struct GNUNET_MESSENGER_MessageStore *store = get_room_message_store(session->member->store->room);
99
100 struct GNUNET_MESSENGER_ListMessages list;
101 init_list_messages(&list);
102
103 while (level.head)
104 {
105 struct GNUNET_MESSENGER_ListMessage *element;
106
107 for (element = level.head; element; element = element->next)
108 {
109 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
110 store, &(element->hash), GNUNET_NO
111 );
112
113 if (!link)
114 continue;
115
116 add_to_list_messages(&list, &(link->first));
117
118 if (GNUNET_YES == link->multiple)
119 add_to_list_messages(&list, &(link->second));
120 }
121
122 clear_list_messages(&level);
123
124 for (element = list.head; element; element = element->next)
125 if (GNUNET_YES == check_member_session_history(session, &(element->hash), GNUNET_YES))
126 break;
127
128 if (element)
129 if (0 != GNUNET_CRYPTO_hash_cmp(&(element->hash), start))
130 add_to_list_messages(&level, &(element->hash));
131 else
132 session->completed = GNUNET_YES;
133 else
134 copy_list_messages(&level, &list);
135
136 clear_list_messages(&list);
137 }
138
139completion:
140 if (GNUNET_YES == is_member_session_completed(session))
141 {
142 GNUNET_CONTAINER_multihashmap_destroy (session->history);
143
144 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
145
146 if ((session->contact) && (GNUNET_YES == decrease_contact_rc (session->contact)))
147 remove_store_contact (
148 store,
149 session->contact,
150 get_member_session_context(session)
151 );
152
153 session->contact = NULL;
154 }
155}
156
157static int
158iterate_copy_history (void *cls, const struct GNUNET_HashCode *key, void *value)
159{
160 struct GNUNET_MESSENGER_MemberSession *next = cls;
161
162 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
163 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
164
165 return GNUNET_YES;
166}
167
168struct GNUNET_MESSENGER_MemberSession*
169switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
170 const struct GNUNET_MESSENGER_Message *message,
171 const struct GNUNET_HashCode *hash)
172{
173 if ((!session) || (!message) || (!hash))
174 return NULL;
175
176 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
177 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
178
179 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
180
181 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
182 next->member = add_store_member(session->member->store, &(message->body.id.id));
183 else
184 next->member = session->member;
185
186 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
187 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
188 else
189 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
190
191 get_context_from_member (
192 get_member_session_key (next),
193 get_member_session_id (next),
194 &(next->context)
195 );
196
197 update_store_contact(
198 get_member_contact_store(next->member->store),
199 get_member_session_contact(session),
200 get_member_session_context(session),
201 get_member_session_context(next),
202 get_member_session_public_key(next)
203 );
204
205 next->contact = get_member_session_contact(session);
206
207 if (!(next->contact))
208 {
209 GNUNET_free(next);
210 return NULL;
211 }
212
213 increase_contact_rc (next->contact);
214
215 next->history = GNUNET_CONTAINER_multihashmap_create(
216 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
217 );
218
219 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
220
221 init_list_messages(&(next->messages));
222 copy_list_messages(&(next->messages), &(session->messages));
223
224 session->next = next;
225 next->next = NULL;
226
227 session->closed = GNUNET_YES;
228 next->closed = GNUNET_NO;
229 next->completed = GNUNET_NO;
230
231 check_member_session_completion (session);
232
233 return next;
234}
235
236void
237destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
238{
239 GNUNET_assert (session);
240
241 GNUNET_CONTAINER_multihashmap_destroy (session->history);
242
243 clear_list_messages (&(session->messages));
244
245 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
246
247 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
248 remove_store_contact (
249 get_member_contact_store(session->member->store),
250 contact,
251 get_member_session_context(session)
252 );
253
254 GNUNET_free(session);
255}
256
257int
258reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
259 const struct GNUNET_HashCode *hash)
260{
261 GNUNET_assert ((session) && (hash));
262
263 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
264 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
265 store,
266 get_member_session_context (session),
267 get_member_session_public_key (session)
268 );
269
270 if (!contact)
271 return GNUNET_SYSERR;
272
273 if (contact == session->contact)
274 goto clear_messages;
275
276 session->contact = contact;
277 increase_contact_rc (session->contact);
278
279clear_messages:
280 clear_list_messages(&(session->messages));
281 add_to_list_messages(&(session->messages), hash);
282
283 session->next = NULL;
284 session->closed = GNUNET_NO;
285 session->completed = GNUNET_NO;
286
287 return GNUNET_OK;
288}
289
290void
291close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
292{
293 GNUNET_assert (session);
294
295 session->closed = GNUNET_YES;
296 check_member_session_completion (session);
297}
298
299int
300is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
301{
302 GNUNET_assert(session);
303
304 return session->closed;
305}
306
307int
308is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
309{
310 GNUNET_assert(session);
311
312 return session->completed;
313}
314
315const struct GNUNET_HashCode*
316get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
317{
318 GNUNET_assert((session) && (session->member));
319
320 return get_member_store_key(session->member->store);
321}
322
323const struct GNUNET_ShortHashCode*
324get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
325{
326 GNUNET_assert(session);
327
328 return get_member_id(session->member);
329}
330
331const struct GNUNET_IDENTITY_PublicKey*
332get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
333{
334 GNUNET_assert(session);
335
336 return &(session->public_key);
337}
338
339const struct GNUNET_HashCode*
340get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
341{
342 GNUNET_assert(session);
343
344 return &(session->context);
345}
346
347struct GNUNET_MESSENGER_Contact*
348get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
349{
350 GNUNET_assert (session);
351
352 return session->contact;
353}
354
355int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
356 const struct GNUNET_MESSENGER_Message *message,
357 const struct GNUNET_HashCode *hash)
358{
359 GNUNET_assert((session) && (message) && (hash));
360
361 if (GNUNET_YES == is_member_session_completed(session))
362 return GNUNET_SYSERR;
363
364 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
365 return GNUNET_SYSERR;
366
367 return verify_message(message, hash, get_member_session_public_key(session));
368}
369
370int
371check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
372 const struct GNUNET_HashCode *hash, int ownership)
373{
374 GNUNET_assert((session) && (hash));
375
376 if (GNUNET_YES == ownership)
377 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
378 else
379 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
380}
381
382static void
383update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
384 const struct GNUNET_HashCode *hash, int ownership)
385{
386 GNUNET_assert ((session) && (hash));
387
388 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
389 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
390 update_member_chain_history (session->next, hash, ownership);
391}
392
393void
394update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
395 const struct GNUNET_MESSENGER_Message *message,
396 const struct GNUNET_HashCode *hash)
397{
398 GNUNET_assert((session) && (message) && (hash));
399
400 if (GNUNET_YES == is_member_session_completed(session))
401 return;
402
403 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
404 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
405
406 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
407 {
408 if (GNUNET_YES == is_message_session_bound (message))
409 add_to_list_messages(&(session->messages), hash);
410
411 update_member_chain_history (session, hash, GNUNET_YES);
412 }
413 else
414 update_member_chain_history (session, hash, GNUNET_NO);
415
416 if (GNUNET_YES == session->closed)
417 check_member_session_completion(session);
418}
419
420static void
421clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
422 const struct GNUNET_HashCode *hash)
423{
424 GNUNET_assert ((session) && (hash));
425
426 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
427 clear_member_session_history(session->next, hash);
428}
429
430void
431clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
432 const struct GNUNET_HashCode *hash)
433{
434 GNUNET_assert((session) && (hash));
435
436 clear_member_chain_history (session, hash);
437}
438
439struct GNUNET_MESSENGER_MemberSessionHistoryEntry
440{
441 struct GNUNET_HashCode hash;
442 unsigned char ownership;
443};
444
445static void
446load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
447{
448 GNUNET_assert((session) && (path));
449
450 if (GNUNET_YES != GNUNET_DISK_file_test (path))
451 return;
452
453 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
454
455 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
456 path, GNUNET_DISK_OPEN_READ, permission
457 );
458
459 if (!handle)
460 return;
461
462 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
463
464 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
465 ssize_t len;
466
467 int status;
468
469 do {
470 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
471
472 if (len != sizeof(entry.hash))
473 break;
474
475 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
476
477 if (len != sizeof(entry.ownership))
478 break;
479
480 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
481 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
482 } while (status == GNUNET_OK);
483
484 GNUNET_DISK_file_close(handle);
485}
486
487void
488load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory)
489{
490 GNUNET_assert ((member) && (directory));
491
492 char *config_file;
493 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
494
495 struct GNUNET_MESSENGER_MemberSession *session = NULL;
496
497 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
498 goto free_config;
499
500 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
501
502 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
503 {
504 char *key_data;
505
506 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
507 goto destroy_config;
508
509 struct GNUNET_IDENTITY_PublicKey key;
510
511 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
512
513 GNUNET_free(key_data);
514
515 if (GNUNET_OK != key_return)
516 goto destroy_config;
517
518 session = create_member_session(member, &key);
519 }
520
521destroy_config:
522 GNUNET_CONFIGURATION_destroy (cfg);
523
524free_config:
525 GNUNET_free(config_file);
526
527 if (!session)
528 return;
529
530 char *history_file;
531 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
532
533 load_member_session_history (session, history_file);
534 GNUNET_free(history_file);
535
536 char *messages_file;
537 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
538
539 load_list_messages(&(session->messages), messages_file);
540 GNUNET_free(messages_file);
541
542 add_member_session(member, session);
543}
544
545static struct GNUNET_MESSENGER_MemberSession*
546get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
547{
548 if (!next)
549 return NULL;
550
551 struct GNUNET_MESSENGER_MemberSession *check = next;
552
553 do {
554 if (check == session)
555 return NULL;
556
557 check = check->next;
558 } while (check);
559
560 return next;
561}
562
563void
564load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
565{
566 GNUNET_assert ((session) && (directory));
567
568 char *config_file;
569 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
570
571 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
572 goto free_config;
573
574 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
575
576 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
577 {
578 char *key_data;
579
580 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
581 goto destroy_config;
582
583 struct GNUNET_IDENTITY_PublicKey next_key;
584
585 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
586
587 GNUNET_free(key_data);
588
589 if (GNUNET_OK != key_return)
590 goto destroy_config;
591
592 struct GNUNET_ShortHashCode next_id;
593
594 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
595 goto destroy_config;
596
597 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
598
599 session->next = get_cycle_safe_next_session(
600 session, member? get_member_session (member, &next_key) : NULL
601 );
602 }
603
604destroy_config:
605 GNUNET_CONFIGURATION_destroy (cfg);
606
607free_config:
608 GNUNET_free(config_file);
609}
610
611static int
612iterate_save_member_session_history_hentries (void *cls, const struct GNUNET_HashCode *key, void *value)
613{
614 struct GNUNET_DISK_FileHandle *handle = cls;
615 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
616
617 GNUNET_DISK_file_write(handle, key, sizeof(*key));
618 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
619
620 return GNUNET_YES;
621}
622
623static void
624save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
625{
626 GNUNET_assert((session) && (path));
627
628 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
629
630 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
631 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
632 );
633
634 if (!handle)
635 return;
636
637 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
638
639 GNUNET_CONTAINER_multihashmap_iterate(
640 session->history,
641 iterate_save_member_session_history_hentries,
642 handle
643 );
644
645 GNUNET_DISK_file_sync(handle);
646 GNUNET_DISK_file_close(handle);
647}
648
649void
650save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
651{
652 GNUNET_assert ((session) && (directory));
653
654 char *config_file;
655 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
656
657 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
658
659 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
660
661 if (key_data)
662 {
663 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
664
665 GNUNET_free(key_data);
666 }
667
668 if (session->next)
669 {
670 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
671
672 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
673
674 if (next_id_data)
675 {
676 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
677
678 GNUNET_free(next_id_data);
679 }
680
681 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
682
683 if (key_data)
684 {
685 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
686
687 GNUNET_free(key_data);
688 }
689 }
690
691 GNUNET_CONFIGURATION_write (cfg, config_file);
692 GNUNET_CONFIGURATION_destroy (cfg);
693
694 GNUNET_free(config_file);
695
696 char *history_file;
697 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
698
699 save_member_session_history (session, history_file);
700 GNUNET_free(history_file);
701
702 char *messages_file;
703 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
704
705 save_list_messages(&(session->messages), messages_file);
706 GNUNET_free(messages_file);
707}
diff --git a/src/messenger/gnunet-service-messenger_member_session.h b/src/messenger/gnunet-service-messenger_member_session.h
new file mode 100644
index 000000000..dd753be2a
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_session.h
@@ -0,0 +1,275 @@
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 src/messenger/gnunet-service-messenger_member_session.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33
34#include "gnunet-service-messenger_member.h"
35
36#include "messenger_api_contact.h"
37
38struct GNUNET_MESSENGER_MemberSession {
39 struct GNUNET_MESSENGER_Member *member;
40
41 struct GNUNET_IDENTITY_PublicKey public_key;
42 struct GNUNET_HashCode context;
43
44 struct GNUNET_MESSENGER_Contact *contact;
45
46 struct GNUNET_CONTAINER_MultiHashMap *history;
47 struct GNUNET_MESSENGER_ListMessages messages;
48
49 struct GNUNET_MESSENGER_MemberSession* next;
50
51 int closed;
52 int completed;
53};
54
55/**
56 * Creates and allocates a new member session of a <i>member</i> with a given
57 * public key.
58 *
59 * If the creation fails, NULL gets returned.
60 *
61 * @param[in/out] member Member
62 * @param[in] pubkey Public key of EGO
63 * @return New member session
64 */
65struct GNUNET_MESSENGER_MemberSession*
66create_member_session (struct GNUNET_MESSENGER_Member *member,
67 const struct GNUNET_IDENTITY_PublicKey *pubkey);
68
69/**
70 * Creates and allocates a new member session closing and replacing a given
71 * other <i>session</i> of the same member. The new session could have significant
72 * changes to the members public key or its member id depending on the used
73 * <i>message</i> to switch session. The new session will be linked to the old
74 * one.
75 *
76 * @param[in/out] session Old member session
77 * @param[in] message Message
78 * @param[in] hash Hash of message
79 * @return New member session
80 */
81struct GNUNET_MESSENGER_MemberSession*
82switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
83 const struct GNUNET_MESSENGER_Message *message,
84 const struct GNUNET_HashCode *hash);
85
86/**
87 * Destroys a member session and frees its memory fully.
88 *
89 * @param[in/out] session Member session
90 */
91void
92destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session);
93
94/**
95 * Resets a given member <i>session</i> which re-opens a member
96 * session for new usage. Every connection to other sessions will be
97 * be dropped. The member sessions messages will be cleared but old
98 * history from uncompleted sessions however can be reused!
99 *
100 * @param[in/out] session Member session
101 * @param[in] hash Hash of initial message (JOIN message!)
102 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
103 */
104int
105reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
106 const struct GNUNET_HashCode *hash);
107
108/**
109 * Closes a given member <i>session</i> which opens the request
110 * for completion of the given member session.
111 *
112 * Closing a session may complete a session and can't be used without
113 * a reset! ( @see #reset_member_session() )
114 *
115 * @param[in/out] session Member session
116 */
117void
118close_member_session (struct GNUNET_MESSENGER_MemberSession* session);
119
120/**
121 * Returns if the given member <i>session</i> has been closed.
122 *
123 * @param[in] session Member session
124 * @return #GNUNET_YES or #GNUNET_NO
125 */
126int
127is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session);
128
129/**
130 * Returns if the given member <i>session</i> has been completed.
131 *
132 * A completed member session can't verify any message as its own and
133 * it won't add any message to its history.
134 *
135 * @param[in] session Member session
136 * @return #GNUNET_YES or #GNUNET_NO
137 */
138int
139is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session);
140
141/**
142 * Returns the key of the room a given member <i>session</i> belongs to.
143 *
144 * @param[in] session Member session
145 * @return Key of room
146 */
147const struct GNUNET_HashCode*
148get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session);
149
150/**
151 * Returns the member id of a given member <i>session</i>.
152 *
153 * @param[in] session Member session
154 * @return Member id
155 */
156const struct GNUNET_ShortHashCode*
157get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session);
158
159/**
160 * Returns the public key from an EGO of a given member <i>session</i>.
161 *
162 * @param[in] session Member session
163 * @return Public key of EGO
164 */
165const struct GNUNET_IDENTITY_PublicKey*
166get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session);
167
168/**
169 * Returns the member context of a given member <i>session</i>.
170 *
171 * @param[in] session Member session
172 * @return Member context as hash
173 */
174const struct GNUNET_HashCode*
175get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session);
176
177/**
178 * Retruns the contact which is connected to a given member <i>session</i>.
179 *
180 * @param[in] session Member session
181 * @return Contact
182 */
183struct GNUNET_MESSENGER_Contact*
184get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session);
185
186/**
187 * Verifies a given member <i>session</i> as sender of a selected <i>message</i> and
188 * its <i>hash</i>. The function returns #GNUNET_OK if the message session is verified
189 * as sender, otherwise #GNUNET_SYSERR.
190 *
191 * @see #is_member_session_completed() for verification.
192 *
193 * @param[in] session Member session
194 * @param[in] message Message
195 * @param[in] hash Hash of message
196 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
197 */
198int
199verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
200 const struct GNUNET_MESSENGER_Message *message,
201 const struct GNUNET_HashCode *hash);
202
203/**
204 * Checks the history of a <i>session</i> for a specific message which is identified
205 * by its <i>hash</i> and if the <i>ownership</i> flag is set, if the message is
206 * owned by the sessions contact.
207 *
208 * @param[in] session Member session
209 * @param[in] hash Hash of message
210 * @param[in] ownership Ownership flag
211 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
212 */
213int
214check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
215 const struct GNUNET_HashCode *hash, int ownership);
216
217/**
218 * Adds a given <i>message</i> to the history of a <i>session</i> using the messages
219 * <i>hash</i>. The ownership will be set automatically.
220 *
221 * @see #is_member_session_completed() for updating a history.
222 *
223 * @param[in/out] session Member session
224 * @param[in] message Message
225 * @param[in] hash Hash of message
226 */
227void
228update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
229 const struct GNUNET_MESSENGER_Message *message,
230 const struct GNUNET_HashCode *hash);
231
232/**
233 * Removes a message from the history of a <i>session</i> using the messages
234 * <i>hash</i>.
235 *
236 * @param[in/out] session Member session
237 * @param[in] hash Hash of message
238 */
239void
240clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
241 const struct GNUNET_HashCode *hash);
242
243/**
244 * Loads data from a <i>directory</i> into a new allocated and created member
245 * session of a <i>member</i> if the required information can be read from the
246 * content of the given directory.
247 *
248 * @param[out] member Member
249 * @param[in] directory Path to a directory
250 */
251void
252load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory);
253
254/**
255 * Loads the connection from one <i>session</i> to another through the
256 * next attribute. Necessary information will be loaded from a configuration
257 * file inside of a given <i>directory</i>.
258 *
259 * @param[in/out] session Member session
260 * @param[in] directory Path to a directory
261 */
262void
263load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
264
265/**
266 * Saves data from a member <i>session</i> into a <i>directory</i> which can be
267 * load to restore the member session completely.
268 *
269 * @param[in] session Member session
270 * @param[in] directory Path to a directory
271 */
272void
273save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
274
275#endif //GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
diff --git a/src/messenger/gnunet-service-messenger_member_store.c b/src/messenger/gnunet-service-messenger_member_store.c
new file mode 100644
index 000000000..2925965d4
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_store.c
@@ -0,0 +1,250 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_member_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_store.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_service.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
34{
35 GNUNET_assert ((store) && (room));
36
37 store->room = room;
38 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
43{
44 struct GNUNET_MESSENGER_Member *member = value;
45 destroy_member(member);
46 return GNUNET_YES;
47}
48
49void
50clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
51{
52 GNUNET_assert ((store) && (store->members));
53
54 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
55 GNUNET_CONTAINER_multishortmap_destroy (store->members);
56}
57
58
59struct GNUNET_MESSENGER_ContactStore*
60get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
61{
62 GNUNET_assert ((store) && (store->room));
63
64 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
65
66 return get_service_contact_store(room->service);
67}
68
69const struct GNUNET_HashCode*
70get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
71{
72 GNUNET_assert (store);
73
74 return get_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
75}
76
77static int
78callback_scan_for_members (void *cls, const char *filename)
79{
80 struct GNUNET_MESSENGER_MemberStore *store = cls;
81
82 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
83 {
84 char *directory;
85
86 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
87
88 load_member(store, directory);
89
90 GNUNET_free(directory);
91 }
92
93 return GNUNET_OK;
94}
95
96static int
97iterate_load_next_member_sessions (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
98{
99 const char *sync_dir = cls;
100
101 struct GNUNET_MESSENGER_Member *member = value;
102
103 if (!member)
104 return GNUNET_YES;
105
106 char *member_dir;
107 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
108
109 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
110 load_member_next_sessions (member, member_dir);
111
112 GNUNET_free(member_dir);
113 return GNUNET_YES;
114}
115
116static int
117iterate_sync_member_contacts (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
118{
119 struct GNUNET_MESSENGER_Member *member = value;
120
121 if (!member)
122 return GNUNET_YES;
123
124 sync_member_contacts (member);
125 return GNUNET_YES;
126}
127
128void
129load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
130{
131 GNUNET_assert ((store) && (directory));
132
133 char *scan_dir;
134 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
135
136 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
137 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
138
139 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
140 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
141
142 GNUNET_free(scan_dir);
143}
144
145static int
146iterate_save_members (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
147{
148 const char *save_dir = cls;
149
150 struct GNUNET_MESSENGER_Member *member = value;
151
152 if (!member)
153 return GNUNET_YES;
154
155 char *member_dir;
156 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
157
158 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
159 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
160 save_member(member, member_dir);
161
162 GNUNET_free(member_dir);
163 return GNUNET_YES;
164}
165
166void
167save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
168{
169 GNUNET_assert ((store) && (directory));
170
171 char* save_dir;
172 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
173
174 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
175 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
176 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
177
178 GNUNET_free(save_dir);
179}
180
181struct GNUNET_MESSENGER_Member*
182get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
183{
184 GNUNET_assert ((store) && (store->members) && (id));
185
186 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
187}
188
189struct GNUNET_MESSENGER_Member*
190get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message)
191{
192 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
193 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
194 return add_store_member(store, &(message->header.sender_id));
195 else
196 return get_store_member(store, &(message->header.sender_id));
197}
198
199struct GNUNET_MESSENGER_Member*
200add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
201{
202 GNUNET_assert ((store) && (store->members));
203
204 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
205
206 if (member)
207 return member;
208
209 member = create_member(store, id);
210
211 if (!member)
212 return NULL;
213
214 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
215 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
216 {
217 destroy_member(member);
218 return NULL;
219 }
220
221 return member;
222}
223
224struct GNUNET_MESSENGER_ClosureIterateMembers {
225 GNUNET_MESSENGER_MemberIteratorCallback it;
226 void *cls;
227};
228
229static int
230iterate_store_members_it (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
231{
232 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
233 struct GNUNET_MESSENGER_Member *member = value;
234
235 return iterate_member_sessions(member, iterate->it, iterate->cls);
236}
237
238int
239iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
240 void* cls)
241{
242 GNUNET_assert ((store) && (store->members) && (it));
243
244 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
245
246 iterate.it = it;
247 iterate.cls = cls;
248
249 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
250}
diff --git a/src/messenger/gnunet-service-messenger_member_store.h b/src/messenger/gnunet-service-messenger_member_store.h
new file mode 100644
index 000000000..859e4683d
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_store.h
@@ -0,0 +1,151 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/gnunet-service-messenger_member_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33#include "messenger_api_message.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_Member;
38struct GNUNET_MESSENGER_MemberSession;
39
40struct GNUNET_MESSENGER_MemberStore
41{
42 struct GNUNET_MESSENGER_SrvRoom *room;
43
44 struct GNUNET_CONTAINER_MultiShortmap *members;
45};
46
47typedef int (*GNUNET_MESSENGER_MemberIteratorCallback) (
48 void *cls,
49 const struct GNUNET_IDENTITY_PublicKey *public_key,
50 struct GNUNET_MESSENGER_MemberSession *session);
51
52/**
53 * Initializes a member <i>store</i> as fully empty connected to a <i>room</i>.
54 *
55 * @param[out] store Member store
56 * @param room Room
57 */
58void
59init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
60
61/**
62 * Clears a member <i>store</i>, wipes its content and deallocates its memory.
63 *
64 * @param[in/out] store Member store
65 */
66void
67clear_member_store (struct GNUNET_MESSENGER_MemberStore *store);
68
69/**
70 * Returns the used contact store of a given member <i>store</i>.
71 *
72 * @param[in/out] store Member store
73 * @return Contact store
74 */
75struct GNUNET_MESSENGER_ContactStore*
76get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store);
77
78/**
79 * Returns the shared secret you need to access a room of the <i>store</i>.
80 *
81 * @param[in] store Member store
82 * @return Shared secret
83 */
84const struct GNUNET_HashCode*
85get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store);
86
87/**
88 * Loads members from a directory into a member <i>store</i>.
89 *
90 * @param[out] store Member store
91 * @param[in] directory Path to a directory
92 */
93void
94load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
95
96/**
97 * Saves members from a member <i>store</i> into a directory.
98 *
99 * @param[in] store Member store
100 * @param[in] directory Path to a directory
101 */
102void
103save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
104
105/**
106 * Returns the member in a <i>store</i> identified by a given <i>id</i>. If the <i>store</i>
107 * does not contain a member with the given <i>id</i>, NULL gets returned.
108 *
109 * @param[in] store Member store
110 * @param[in] id Member id
111 * @return Member or NULL
112 */
113struct GNUNET_MESSENGER_Member*
114get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
115
116/**
117 * Returns the member of a <i>store</i> using a sender id of a given <i>message</i>.
118 * If the member does not provide a matching session, NULL gets returned.
119 *
120 * @param[in/out] store Member store
121 * @param[in] message Message
122 * @return Member or NULL
123 */
124struct GNUNET_MESSENGER_Member*
125get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message);
126
127/**
128 * Adds a member to a <i>store</i> under a specific <i>id</i> and returns it on success.
129 *
130 * @param[in/out] store Member store
131 * @param[in] id Member id
132 * @return Member or NULL
133 */
134struct GNUNET_MESSENGER_Member*
135add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
136
137/**
138 * Iterate through all member sessions currently connected to the members of the given
139 * member <i>store</i> and call the provided iterator callback with a selected closure.
140 * The function will return the amount of members it iterated through.
141 *
142 * @param[in/out] store Member store
143 * @param[in] it Iterator callback
144 * @param[in/out] cls Closure
145 * @return Amount of members iterated through
146 */
147int
148iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
149 void* cls);
150
151#endif //GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c b/src/messenger/gnunet-service-messenger_message_handle.c
index 1652435c8..c22e51fbf 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ b/src/messenger/gnunet-service-messenger_message_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -25,75 +25,59 @@
25 25
26#include "gnunet-service-messenger_message_handle.h" 26#include "gnunet-service-messenger_message_handle.h"
27 27
28void 28static void
29handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 29handle_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
30 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 30 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
31{ 31{
32 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 32 struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, message, hash);
33
34 if (!contact)
35 add_room_contact (room, &(message->header.sender_id), &(message->body.join.key));
36
37 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id));
38
39 if (!info)
40 {
41 info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo);
42
43 info->access = GNUNET_MESSENGER_MEMBER_UNKNOWN;
44 init_list_messages (&(info->session_messages));
45 }
46 else
47 clear_list_messages (&(info->session_messages));
48 33
49 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, &(message->header.sender_id), info, 34 if (next != session)
50 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 35 add_member_session(next->member, next);
51 add_to_list_messages (&(info->session_messages), hash);
52} 36}
53 37
54void 38void
55handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 39handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
56 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 40 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
57{ 41{
58 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 42 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
43 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
59 44
60 if (info) 45 if (GNUNET_OK != reset_member_session(session, hash))
61 clear_list_messages (&(info->session_messages)); 46 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
62} 47}
63 48
64void 49void
65handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 50handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
66 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
67{ 52{
68 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 53 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
54 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
69 55
70 if (contact) 56 close_member_session(session);
71 set_contact_name (contact, message->body.name.name);
72
73 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id));
74
75 if (info)
76 add_to_list_messages (&(info->session_messages), hash);
77} 57}
78 58
79void 59void
80handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 60handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
81 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
82{ 62{
83 struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); 63 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact(session);
84 64
85 if (contact) 65 if (!contact)
86 swap_service_contact_by_pubkey (room->service, contact, &(message->body.key.key)); 66 return;
87 67
88 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 68 set_contact_name (contact, message->body.name.name);
69}
89 70
90 if (info) 71void
91 add_to_list_messages (&(info->session_messages), hash); 72handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
73 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
74{
75 handle_session_switch (session, message, hash);
92} 76}
93 77
94void 78void
95handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 79handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
96 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 80 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
97{ 81{
98 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer))) 82 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer)))
99 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer)); 83 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
@@ -103,20 +87,15 @@ handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
103} 87}
104 88
105void 89void
106handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 90handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
107 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 91 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
108{ 92{
109 struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); 93 handle_session_switch (session, message, hash);
110
111 if (info)
112 add_to_list_messages (&(info->session_messages), hash);
113
114 switch_room_member_id (room, &(message->header.sender_id), &(message->body.id.id), hash);
115} 94}
116 95
117void 96void
118handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 97handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
119 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 98 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
120{ 99{
121 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL); 100 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL);
122 101
@@ -128,3 +107,16 @@ handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
128 if (room->peer_message) 107 if (room->peer_message)
129 rebuild_room_basement_structure (room); 108 rebuild_room_basement_structure (room);
130} 109}
110
111void
112handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
113 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
114{
115 struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_ntoh (message->body.delete.delay);
116 struct GNUNET_TIME_Absolute action = GNUNET_TIME_absolute_ntoh (message->header.timestamp);
117
118 action = GNUNET_TIME_absolute_add (action, delay);
119 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
120
121 delete_room_message (room, session, &(message->body.delete.hash), delay);
122}
diff --git a/src/messenger/gnunet-service-messenger_message_handle.h b/src/messenger/gnunet-service-messenger_message_handle.h
index d091e1d11..844142b77 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.h
+++ b/src/messenger/gnunet-service-messenger_message_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -31,6 +31,7 @@
31 31
32#include "gnunet-service-messenger_message_kind.h" 32#include "gnunet-service-messenger_message_kind.h"
33 33
34#include "gnunet-service-messenger_member_session.h"
34#include "gnunet-service-messenger_tunnel.h" 35#include "gnunet-service-messenger_tunnel.h"
35#include "messenger_api_message.h" 36#include "messenger_api_message.h"
36 37
@@ -38,91 +39,104 @@
38 * Handles a received or sent join message to make changes of current member information. 39 * Handles a received or sent join message to make changes of current member information.
39 * (add matching member and clear member info) 40 * (add matching member and clear member info)
40 * 41 *
41 * @param room Room of the message 42 * @param[in/out] room Room of the message
42 * @param tunnel Receiving/sending connection (may be NULL) 43 * @param[in/out] session Member session
43 * @param message JOIN-Message 44 * @param[in] message JOIN-Message
44 * @param hash Hash of the message 45 * @param[in] hash Hash of the message
45 */ 46 */
46void 47void
47handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 48handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
48 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 49 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
49 50
50/** 51/**
51 * Handles a received or sent leave message to make changes of current member information. 52 * Handles a received or sent leave message to make changes of current member information.
52 * (remove matching member and clear member info) 53 * (remove matching member and clear member info)
53 * 54 *
54 * @param room Room of the message 55 * @param[in/out] room Room of the message
55 * @param tunnel Receiving/sending connection (may be NULL) 56 * @param[in/out] session Member session
56 * @param message LEAVE-Message 57 * @param[in] message LEAVE-Message
57 * @param hash Hash of the message 58 * @param[in] hash Hash of the message
58 */ 59 */
59void 60void
60handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 61handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
61 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 62 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
62 63
63/** 64/**
64 * Handles a received or sent name message to rename a current member. 65 * Handles a received or sent name message to rename a current member.
65 * (change name of matching member) 66 * (change name of matching member)
66 * 67 *
67 * @param room Room of the message 68 * @param[in/out] room Room of the message
68 * @param tunnel Receiving/sending connection (may be NULL) 69 * @param[in/out] session Member session
69 * @param message NAME-Message 70 * @param[in] message NAME-Message
70 * @param hash Hash of the message 71 * @param[in] hash Hash of the message
71 */ 72 */
72void 73void
73handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 74handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
74 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 75 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
75 76
76/** 77/**
77 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly. 78 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly.
78 * (move the member in the contacts and change its key) 79 * (move the member in the contacts and change its key)
79 * 80 *
80 * @param room Room of the message 81 * @param[in/out] room Room of the message
81 * @param tunnel Receiving/sending connection (may be NULL) 82 * @param[in/out] session Member session
82 * @param message KEY-Message 83 * @param[in] message KEY-Message
83 * @param hash Hash of the message 84 * @param[in] hash Hash of the message
84 */ 85 */
85void 86void
86handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 87handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
87 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 88 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
88 89
89/** 90/**
90 * Handles a received or sent peer message to make changes of the basement in the room. 91 * Handles a received or sent peer message to make changes of the basement in the room.
91 * (add a new peer to the basement and restructure connections based on updated list of peers) 92 * (add a new peer to the basement and restructure connections based on updated list of peers)
92 * 93 *
93 * @param room Room of the message 94 * @param[in/out] room Room of the message
94 * @param tunnel Receiving/sending connection (may be NULL) 95 * @param[in/out] session Member session
95 * @param message PEER-Message 96 * @param[in] message PEER-Message
96 * @param hash Hash of the message 97 * @param[in] hash Hash of the message
97 */ 98 */
98void 99void
99handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 100handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
100 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 101 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
101 102
102/** 103/**
103 * Handles a received or sent id message to change a members id. 104 * Handles a received or sent id message to change a members id.
104 * (change id of matching member) 105 * (change id of matching member)
105 * 106 *
106 * @param room Room of the message 107 * @param[in/out] room Room of the message
107 * @param tunnel Receiving/sending connection (may be NULL) 108 * @param[in/out] session Member session
108 * @param message ID-Message 109 * @param[in] message ID-Message
109 * @param hash Hash of the message 110 * @param[in] hash Hash of the message
110 */ 111 */
111void 112void
112handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 113handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
113 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 114 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
114 115
115/** 116/**
116 * Handles a received or sent miss message to drop a peer from the basement in the room. 117 * Handles a received or sent miss message to drop a peer from the basement in the room.
117 * (remove a peer from the basement and restructure connections based on updated list of peers) 118 * (remove a peer from the basement and restructure connections based on updated list of peers)
118 * 119 *
119 * @param room Room of the message 120 * @param[in/out] room Room of the message
120 * @param tunnel Receiving/sending connection (may be NULL) 121 * @param[in/out] session Member session
121 * @param message MISS-Message 122 * @param[in] message MISS-Message
122 * @param hash Hash of the message 123 * @param[in] hash Hash of the message
123 */ 124 */
124void 125void
125handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 126handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
126 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 127 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
128
129/**
130 * Handles a received or sent delete message to delete a specific message from the store.
131 * (remove a message from the store of a room under a given delay)
132 *
133 * @param[in/out] room Room of the message
134 * @param[in/out] session Member session
135 * @param[in] message DELETE-Message
136 * @param[in] hash Hash of the message
137 */
138void
139handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
140 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
127 141
128#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H 142#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c b/src/messenger/gnunet-service-messenger_message_kind.c
index 9c829fe09..ef9bbfd2e 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ b/src/messenger/gnunet-service-messenger_message_kind.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -24,11 +24,15 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_kind.h" 26#include "gnunet-service-messenger_message_kind.h"
27#include "gnunet-service-messenger_util.h" 27
28#include "messenger_api_util.h"
28 29
29struct GNUNET_MESSENGER_Message* 30struct GNUNET_MESSENGER_Message*
30create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members) 31create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
31{ 32{
33 if (!ego)
34 return NULL;
35
32 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO); 36 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO);
33 37
34 if (!message) 38 if (!message)
@@ -36,18 +40,17 @@ create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_M
36 40
37 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub)); 41 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
38 42
39 if (GNUNET_YES == generate_free_member_id (&(message->body.info.unique_id), members)) 43 message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
40 return message; 44
41 else 45 return message;
42 {
43 destroy_message (message);
44 return NULL;
45 }
46} 46}
47 47
48struct GNUNET_MESSENGER_Message* 48struct GNUNET_MESSENGER_Message*
49create_message_join (struct GNUNET_MESSENGER_Ego *ego) 49create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
50{ 50{
51 if (!ego)
52 return NULL;
53
51 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN); 54 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN);
52 55
53 if (!message) 56 if (!message)
@@ -67,6 +70,9 @@ create_message_leave ()
67struct GNUNET_MESSENGER_Message* 70struct GNUNET_MESSENGER_Message*
68create_message_name (const char *name) 71create_message_name (const char *name)
69{ 72{
73 if (!name)
74 return NULL;
75
70 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME); 76 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME);
71 77
72 if (!message) 78 if (!message)
@@ -79,6 +85,9 @@ create_message_name (const char *name)
79struct GNUNET_MESSENGER_Message* 85struct GNUNET_MESSENGER_Message*
80create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key) 86create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
81{ 87{
88 if (!key)
89 return NULL;
90
82 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY); 91 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY);
83 92
84 if (!message) 93 if (!message)
@@ -91,6 +100,9 @@ create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
91struct GNUNET_MESSENGER_Message* 100struct GNUNET_MESSENGER_Message*
92create_message_peer (const struct GNUNET_MESSENGER_Service *service) 101create_message_peer (const struct GNUNET_MESSENGER_Service *service)
93{ 102{
103 if (!service)
104 return NULL;
105
94 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER); 106 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER);
95 107
96 if (!message) 108 if (!message)
@@ -108,6 +120,9 @@ create_message_peer (const struct GNUNET_MESSENGER_Service *service)
108struct GNUNET_MESSENGER_Message* 120struct GNUNET_MESSENGER_Message*
109create_message_id (const struct GNUNET_ShortHashCode *unique_id) 121create_message_id (const struct GNUNET_ShortHashCode *unique_id)
110{ 122{
123 if (!unique_id)
124 return NULL;
125
111 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID); 126 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID);
112 127
113 if (!message) 128 if (!message)
@@ -121,6 +136,9 @@ create_message_id (const struct GNUNET_ShortHashCode *unique_id)
121struct GNUNET_MESSENGER_Message* 136struct GNUNET_MESSENGER_Message*
122create_message_miss (const struct GNUNET_PeerIdentity *peer) 137create_message_miss (const struct GNUNET_PeerIdentity *peer)
123{ 138{
139 if (!peer)
140 return NULL;
141
124 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS); 142 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS);
125 143
126 if (!message) 144 if (!message)
@@ -136,6 +154,9 @@ create_message_miss (const struct GNUNET_PeerIdentity *peer)
136struct GNUNET_MESSENGER_Message* 154struct GNUNET_MESSENGER_Message*
137create_message_merge (const struct GNUNET_HashCode *previous) 155create_message_merge (const struct GNUNET_HashCode *previous)
138{ 156{
157 if (!previous)
158 return NULL;
159
139 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE); 160 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE);
140 161
141 if (!message) 162 if (!message)
@@ -149,6 +170,9 @@ create_message_merge (const struct GNUNET_HashCode *previous)
149struct GNUNET_MESSENGER_Message* 170struct GNUNET_MESSENGER_Message*
150create_message_request (const struct GNUNET_HashCode *hash) 171create_message_request (const struct GNUNET_HashCode *hash)
151{ 172{
173 if (!hash)
174 return NULL;
175
152 struct GNUNET_HashCode zero; 176 struct GNUNET_HashCode zero;
153 memset (&zero, 0, sizeof(zero)); 177 memset (&zero, 0, sizeof(zero));
154 178
@@ -168,6 +192,9 @@ create_message_request (const struct GNUNET_HashCode *hash)
168struct GNUNET_MESSENGER_Message* 192struct GNUNET_MESSENGER_Message*
169create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) 193create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
170{ 194{
195 if ((!door) || (!key))
196 return NULL;
197
171 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE); 198 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE);
172 199
173 if (!message) 200 if (!message)
@@ -182,6 +209,9 @@ create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUN
182struct GNUNET_MESSENGER_Message* 209struct GNUNET_MESSENGER_Message*
183create_message_text (const char *text) 210create_message_text (const char *text)
184{ 211{
212 if (!text)
213 return NULL;
214
185 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT); 215 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT);
186 216
187 if (!message) 217 if (!message)
@@ -190,3 +220,20 @@ create_message_text (const char *text)
190 message->body.text.text = GNUNET_strdup(text); 220 message->body.text.text = GNUNET_strdup(text);
191 return message; 221 return message;
192} 222}
223
224struct GNUNET_MESSENGER_Message*
225create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
226{
227 if (!hash)
228 return NULL;
229
230 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_DELETE);
231
232 if (!message)
233 return NULL;
234
235 GNUNET_memcpy(&(message->body.delete.hash), hash, sizeof(struct GNUNET_HashCode));
236 message->body.delete.delay = GNUNET_TIME_relative_hton (delay);
237
238 return message;
239}
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h b/src/messenger/gnunet-service-messenger_message_kind.h
index dd89d0b2f..c098868c0 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ b/src/messenger/gnunet-service-messenger_message_kind.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -30,31 +30,32 @@
30#include "gnunet_container_lib.h" 30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h" 31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h" 32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
33 34
34#include "messenger_api_message.h" 35#include "messenger_api_message.h"
35#include "gnunet-service-messenger_service.h" 36#include "gnunet-service-messenger_service.h"
36#include "messenger_api_ego.h" 37#include "messenger_api_ego.h"
37 38
38/** 39/**
39 * Creates and allocates a new info message containing the hosts public key and a newly generated unique member id. 40 * Creates and allocates a new info message containing the hosts EGO public key and a newly generated unique member id.
40 * (all values are stored as copy) 41 * (all values are stored as copy)
41 * 42 *
42 * @param ego EGO of the host 43 * @param[in] ego EGO of the host
43 * @param members Map of all assigned member ids 44 * @param[in] members Map of all assigned member ids
44 * @return New message 45 * @return New message
45 */ 46 */
46struct GNUNET_MESSENGER_Message* 47struct GNUNET_MESSENGER_Message*
47create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members); 48create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
48 49
49/** 50/**
50 * Creates and allocates a new join message containing the clients public key. 51 * Creates and allocates a new join message containing the clients EGO public key.
51 * (all values are stored as copy) 52 * (all values are stored as copy)
52 * 53 *
53 * @param ego EGO of the client 54 * @param[in] ego EGO of the client
54 * @return New message 55 * @return New message
55 */ 56 */
56struct GNUNET_MESSENGER_Message* 57struct GNUNET_MESSENGER_Message*
57create_message_join (struct GNUNET_MESSENGER_Ego *ego); 58create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
58 59
59/** 60/**
60 * Creates and allocates a new leave message. 61 * Creates and allocates a new leave message.
@@ -68,17 +69,17 @@ create_message_leave ();
68 * Creates and allocates a new name message containing the <i>name</i> to change to. 69 * Creates and allocates a new name message containing the <i>name</i> to change to.
69 * (all values are stored as copy) 70 * (all values are stored as copy)
70 * 71 *
71 * @param name New name 72 * @param[in] name New name
72 * @return New message 73 * @return New message
73 */ 74 */
74struct GNUNET_MESSENGER_Message* 75struct GNUNET_MESSENGER_Message*
75create_message_name (const char *name); 76create_message_name (const char *name);
76 77
77/** 78/**
78 * Creates and allocates a new key message containing the public key to change to derived 79 * Creates and allocates a new key message containing the public <i>key</i> to change to derived
79 * from its private counterpart. (all values are stored as copy) 80 * from its private counterpart. (all values are stored as copy)
80 * 81 *
81 * @param key Private key of EGO 82 * @param[in] key Private key of EGO
82 * @return New message 83 * @return New message
83 */ 84 */
84struct GNUNET_MESSENGER_Message* 85struct GNUNET_MESSENGER_Message*
@@ -88,7 +89,7 @@ create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
88 * Creates and allocates a new peer message containing a services peer identity. 89 * Creates and allocates a new peer message containing a services peer identity.
89 * (all values are stored as copy) 90 * (all values are stored as copy)
90 * 91 *
91 * @param service Service 92 * @param[in] service Service
92 * @return New message 93 * @return New message
93 */ 94 */
94struct GNUNET_MESSENGER_Message* 95struct GNUNET_MESSENGER_Message*
@@ -98,38 +99,38 @@ create_message_peer (const struct GNUNET_MESSENGER_Service *service);
98 * Creates and allocates a new id message containing the unique member id to change to. 99 * Creates and allocates a new id message containing the unique member id to change to.
99 * (all values are stored as copy) 100 * (all values are stored as copy)
100 * 101 *
101 * @param unique_id Unique member id 102 * @param[in] unique_id Unique member id
102 * @return New message 103 * @return New message
103 */ 104 */
104struct GNUNET_MESSENGER_Message* 105struct GNUNET_MESSENGER_Message*
105create_message_id (const struct GNUNET_ShortHashCode *unique_id); 106create_message_id (const struct GNUNET_ShortHashCode *unique_id);
106 107
107/** 108/**
108 * Creates and allocates a new miss message containing the missing peer identity. 109 * Creates and allocates a new miss message containing the missing <i>peer</i> identity.
109 * (all values are stored as copy) 110 * (all values are stored as copy)
110 * 111 *
111 * @param peer Missing peer identity 112 * @param[in] peer Missing peer identity
112 * @return New message 113 * @return New message
113 */ 114 */
114struct GNUNET_MESSENGER_Message* 115struct GNUNET_MESSENGER_Message*
115create_message_miss (const struct GNUNET_PeerIdentity *peer); 116create_message_miss (const struct GNUNET_PeerIdentity *peer);
116 117
117/** 118/**
118 * Creates and allocates a new merge message containing the hash of a second previous message 119 * Creates and allocates a new merge message containing the hash of a second <i>previous</i> message
119 * besides the regular previous message mentioned in a messages header. 120 * besides the regular previous message mentioned in a messages header.
120 * (all values are stored as copy) 121 * (all values are stored as copy)
121 * 122 *
122 * @param previous Hash of message 123 * @param[in] previous Hash of message
123 * @return New message 124 * @return New message
124 */ 125 */
125struct GNUNET_MESSENGER_Message* 126struct GNUNET_MESSENGER_Message*
126create_message_merge (const struct GNUNET_HashCode *previous); 127create_message_merge (const struct GNUNET_HashCode *previous);
127 128
128/** 129/**
129 * Creates and allocates a new request message containing the hash of a missing message. 130 * Creates and allocates a new request message containing the <i>hash</i> of a missing message.
130 * (all values are stored as copy) 131 * (all values are stored as copy)
131 * 132 *
132 * @param hash Hash of message 133 * @param[in] hash Hash of message
133 * @return New message 134 * @return New message
134 */ 135 */
135struct GNUNET_MESSENGER_Message* 136struct GNUNET_MESSENGER_Message*
@@ -140,21 +141,32 @@ create_message_request (const struct GNUNET_HashCode *hash);
140 * to a room using a given <i>key</i> as shared secret for communication. 141 * to a room using a given <i>key</i> as shared secret for communication.
141 * (all values are stored as copy) 142 * (all values are stored as copy)
142 * 143 *
143 * @param door Peer identity 144 * @param[in] door Peer identity
144 * @param key Shared secret of a room 145 * @param[in] key Shared secret of a room
145 * @return New message 146 * @return New message
146 */ 147 */
147struct GNUNET_MESSENGER_Message* 148struct GNUNET_MESSENGER_Message*
148create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key); 149create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key);
149 150
150/** 151/**
151 * Creates and allocates a new text message containing a string representing text. 152 * Creates and allocates a new <i>text message containing a string representing text.
152 * (all values are stored as copy) 153 * (all values are stored as copy)
153 * 154 *
154 * @param text Text 155 * @param[in] text Text
155 * @return New message 156 * @return New message
156 */ 157 */
157struct GNUNET_MESSENGER_Message* 158struct GNUNET_MESSENGER_Message*
158create_message_text (const char *text); 159create_message_text (const char *text);
159 160
161/**
162 * Creates and allocates a new delete message containing the <i>hash</i> of a message to delete after a specific <i>delay</i>.
163 * (all values are stored as copy)
164 *
165 * @param[in] hash Hash of message
166 * @param[in] delay Delay of deletion
167 * @return New message
168 */
169struct GNUNET_MESSENGER_Message*
170create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
171
160#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H 172#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c b/src/messenger/gnunet-service-messenger_message_recv.c
index aa28a36ea..8aab805d2 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ b/src/messenger/gnunet-service-messenger_message_recv.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -24,137 +24,64 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_recv.h" 26#include "gnunet-service-messenger_message_recv.h"
27#include "gnunet-service-messenger_message_handle.h"
28 27
29void 28#include "gnunet-service-messenger_operation.h"
30recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
31 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
32{
33 int conflict = GNUNET_CONTAINER_multishortmap_contains (room->members, &(message->body.info.unique_id));
34
35 if (GNUNET_NO == conflict)
36 {
37 struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&(message->body.info.unique_id));
38 struct GNUNET_HashCode sync_hash;
39
40 send_room_message_ext (room, room->host, sync_message, &sync_hash, tunnel);
41 destroy_message (sync_message);
42
43 switch_room_member_id (room, get_room_host_id (room), &(message->body.info.unique_id), NULL);
44
45 change_room_host_id (room, &(message->body.info.unique_id));
46 }
47
48 if (!tunnel->contact_id)
49 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
50
51 GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode));
52
53 struct GNUNET_ShortHashCode original_id;
54
55 if (GNUNET_YES == conflict)
56 {
57 GNUNET_memcpy(&original_id, get_room_host_id (room), sizeof(struct GNUNET_ShortHashCode));
58
59 change_room_host_id (room, &(message->body.info.unique_id));
60 }
61
62 {
63 struct GNUNET_MESSENGER_Message *join_message = create_message_join (room->host->ego);
64 struct GNUNET_HashCode join_hash;
65
66 send_tunnel_message (tunnel, room->host, join_message, &join_hash);
67 destroy_message (join_message);
68 }
69
70 if ((GNUNET_YES == conflict) && (0 != GNUNET_memcmp(&original_id, get_room_host_id (room))))
71 {
72 struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&original_id);
73 struct GNUNET_HashCode sync_hash;
74
75 send_tunnel_message (tunnel, room->host, sync_message, &sync_hash);
76 destroy_message (sync_message);
77 }
78}
79
80struct GNUNET_MESSENGER_MemberInfoSpread
81{
82 struct GNUNET_MESSENGER_SrvRoom *room;
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
84};
85 29
86static int 30static int
87iterate_send_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value) 31iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
32 struct GNUNET_MESSENGER_MemberSession *session)
88{ 33{
89 struct GNUNET_MESSENGER_MemberInfo *info = value; 34 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
90 struct GNUNET_MESSENGER_MemberInfoSpread *spread = cls; 35 struct GNUNET_MESSENGER_SrvRoom *room = tunnel->room;
91 36
92 struct GNUNET_MESSENGER_ListMessage *element = info->session_messages.head; 37 struct GNUNET_MESSENGER_ListMessage *element;
93 38
94 while (element) 39 for (element = session->messages.head; element; element = element->next)
95 { 40 forward_tunnel_message(tunnel, get_room_message(room, NULL, &(element->hash), GNUNET_NO), &(element->hash));
96 const struct GNUNET_MESSENGER_Message *message = get_room_message (spread->room, spread->room->host,
97 &(element->hash), GNUNET_NO);
98
99 if (message)
100 forward_tunnel_message (spread->tunnel, message, &(element->hash));
101
102 element = element->next;
103 }
104 41
105 return GNUNET_YES; 42 return GNUNET_YES;
106} 43}
107 44
108void 45int
109recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 46recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
110 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 47 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
111{ 48{
112 const struct GNUNET_MESSENGER_Message *info_msg = get_room_message (room, room->host, &(message->header.previous), 49 const uint32_t version = get_tunnel_messenger_version(tunnel);
113 GNUNET_NO);
114 50
115 if ((info_msg) && (0 == GNUNET_memcmp(&(info_msg->header.sender_id), get_room_host_id (room))) 51 if (GNUNET_OK != update_tunnel_messenger_version(tunnel, message->body.info.messenger_version))
116 && (GNUNET_MESSENGER_KIND_INFO == info_msg->header.kind))
117 { 52 {
118 struct GNUNET_MESSENGER_MemberInfoSpread spread; 53 disconnect_tunnel(tunnel);
54 return GNUNET_NO;
55 }
119 56
120 spread.room = room; 57 if (version == get_tunnel_messenger_version(tunnel))
58 return GNUNET_NO;
121 59
122 if ((tunnel) && (tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) 60 if (room->host)
123 spread.tunnel = tunnel; 61 {
124 else 62 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(room->host);
125 spread.tunnel = find_room_tunnel_to (room, &(message->header.sender_id));
126 63
127 if (spread.tunnel) 64 send_tunnel_message (tunnel, room->host, create_message_info(ego));
128 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_send_member_infos, &spread);
129 } 65 }
130 66
131 handle_message_join (room, tunnel, message, hash); 67 struct GNUNET_PeerIdentity peer;
132} 68 get_tunnel_peer_identity(tunnel, &peer);
133 69
134void 70 if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
135recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 71 {
136 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 72 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
137{
138 handle_message_leave (room, tunnel, message, hash);
139}
140 73
141void 74 iterate_store_members(member_store, iterate_forward_members, tunnel);
142recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 75 }
143 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
144{
145 handle_message_name (room, tunnel, message, hash);
146}
147 76
148void 77 check_room_peer_status(room, tunnel);
149recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 78
150 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 79 return GNUNET_NO;
151{
152 handle_message_key (room, tunnel, message, hash);
153} 80}
154 81
155void 82int
156recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 83recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
157 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 84 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
158{ 85{
159 struct GNUNET_PeerIdentity peer; 86 struct GNUNET_PeerIdentity peer;
160 GNUNET_PEER_resolve (tunnel->peer, &peer); 87 GNUNET_PEER_resolve (tunnel->peer, &peer);
@@ -164,41 +91,48 @@ recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
164 if (!tunnel->peer_message) 91 if (!tunnel->peer_message)
165 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode); 92 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode);
166 93
167 GNUNET_memcpy(tunnel->peer_message, hash, sizeof(struct GNUNET_HashCode)); 94 GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
168
169 if (!tunnel->contact_id)
170 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
171
172 GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode));
173 } 95 }
174 96
175 handle_message_peer (room, tunnel, message, hash); 97 return GNUNET_YES;
176} 98}
177 99
178void 100int
179recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 101recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
180 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 102 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
181{ 103{
182 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) 104 const struct GNUNET_MESSENGER_Message *msg = get_room_message (
183 GNUNET_memcpy(tunnel->contact_id, &(message->body.id.id), sizeof(struct GNUNET_ShortHashCode)); 105 room, NULL, &(message->body.request.hash), GNUNET_NO
106 );
184 107
185 handle_message_id (room, tunnel, message, hash); 108 if (!msg)
186} 109 {
110 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
187 111
188void 112 use_store_operation(
189recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 113 operation_store,
190 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 114 &(message->body.request.hash),
191{ 115 GNUNET_MESSENGER_OP_REQUEST,
192 handle_message_miss (room, tunnel, message, hash); 116 GNUNET_MESSENGER_REQUEST_DELAY
193} 117 );
194 118
195void 119 return GNUNET_YES;
196recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 120 }
197 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 121
198{ 122 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
199 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(message->body.request.hash), 123 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
200 GNUNET_NO); 124
125 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
126
127 if (!member)
128 return GNUNET_NO;
129
130 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
131
132 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
133 return GNUNET_NO;
134
135 forward_tunnel_message (tunnel, msg, &(message->body.request.hash));
201 136
202 if (msg) 137 return GNUNET_NO;
203 forward_tunnel_message (tunnel, msg, &(message->body.request.hash));
204} 138}
diff --git a/src/messenger/gnunet-service-messenger_message_recv.h b/src/messenger/gnunet-service-messenger_message_recv.h
index 245612cb0..9cb36c466 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.h
+++ b/src/messenger/gnunet-service-messenger_message_recv.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,9 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31 31
32#include "gnunet-service-messenger_message_kind.h"
33
34#include "gnunet-service-messenger_member_session.h"
32#include "gnunet-service-messenger_tunnel.h" 35#include "gnunet-service-messenger_tunnel.h"
33#include "messenger_api_message.h" 36#include "messenger_api_message.h"
34 37
@@ -36,124 +39,43 @@
36 * Handles a received info message to change the current member id to the one generated by 39 * Handles a received info message to change the current member id to the one generated by
37 * the host connected to. (all current tunnels will be informed about the id change) 40 * the host connected to. (all current tunnels will be informed about the id change)
38 * 41 *
39 * @param room Room of the message 42 * @param[in/out] room Room of the message
40 * @param tunnel Receiving connection 43 * @param[in/out] tunnel Receiving connection
41 * @param message INFO-Message 44 * @param[in] message INFO-Message
42 * @param hash Hash of the message 45 * @param[in] hash Hash of the message
46 * @return #GNUNET_NO to not forward the message
43 */ 47 */
44void 48int
45recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 49recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
46 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 50 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
47
48/**
49 * Handles a received join message to forward all member information to the new member if the message was
50 * the direct reaction to a previous info message from this peer.
51 *
52 * @param room Room of the message
53 * @param tunnel Receiving connection
54 * @param message JOIN-Message
55 * @param hash Hash of the message
56 */
57void
58recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
59 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
60
61/**
62 * Handles a received leave message.
63 * @see handle_message_leave()
64 *
65 * @param room Room of the message
66 * @param tunnel Receiving connection
67 * @param message LEAVE-Message
68 * @param hash Hash of the message
69 */
70void
71recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
72 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
73
74/**
75 * Handles a received name message.
76 * @see handle_message_name()
77 *
78 * @param room Room of the message
79 * @param tunnel Receiving connection
80 * @param message NAME-Message
81 * @param hash Hash of the message
82 */
83void
84recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
85 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
86
87/**
88 * Handles a received key message.
89 * @see handle_message_key()
90 *
91 * @param room Room of the message
92 * @param tunnel Receiving connection
93 * @param message KEY-Message
94 * @param hash Hash of the message
95 */
96void
97recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
98 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
99 51
100/** 52/**
101 * Handles a received peer message to link it to its origin tunnel if the peer identity matches. 53 * Handles a received peer message to link it to its origin tunnel if the peer identity matches.
102 * (the peer message and the member id can potentially be linked to the tunnel) 54 * (the peer message and the member id can potentially be linked to the tunnel)
103 * 55 *
104 * TODO: This handling will only check the one given tunnel! 56 * @param[in/out] room Room of the message
105 * 57 * @param[in/out] tunnel Receiving connection
106 * @param room Room of the message 58 * @param[in] message PEER-Message
107 * @param tunnel Receiving connection 59 * @param[in] hash Hash of the message
108 * @param message PEER-Message 60 * @return #GNUNET_YES to forward the message
109 * @param hash Hash of the message
110 */ 61 */
111void 62int
112recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 63recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
113 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 64 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
114
115/**
116 * Handles a received id message to change the tunnels linked member id if necessary.
117 * (the tunnels linked member id will be changed if the sender id is matching)
118 *
119 * TODO: This handling will only check the one given tunnel!
120 *
121 * @param room Room of the message
122 * @param tunnel Receiving connection
123 * @param message ID-Message
124 * @param hash Hash of the message
125 */
126void
127recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
128 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
129
130/**
131 * Handles a received miss message.
132 * @see handle_message_miss()
133 *
134 * @param room Room of the message
135 * @param tunnel Receiving connection
136 * @param message MISS-Message
137 * @param hash Hash of the message
138 */
139void
140recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
141 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
142 65
143/** 66/**
144 * Handles a received request message by checking for the requested message and forwarding it back 67 * Handles a received request message by checking for the requested message and forwarding it back
145 * if the message was found. 68 * if the message was found.
146 * (this can also cause this peer to send a new request instead of only forwarding the received one) 69 * (this can also cause this peer to send a new request instead of only forwarding the received one)
147 * 70 *
148 * TODO: Requests can cause exponentially more requests! 71 * @param[in/out] room Room of the message
149 * 72 * @param[in/out] tunnel Receiving connection
150 * @param room Room of the message 73 * @param[in] message REQUEST-Message
151 * @param tunnel Receiving connection 74 * @param[in] hash Hash of the message
152 * @param message REQUEST-Message 75 * @return #GNUNET_YES or #GNUNET_NO depending on required forwarding
153 * @param hash Hash of the message
154 */ 76 */
155void 77int
156recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 78recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
157 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 79 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
158 80
159#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H 81#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H
diff --git a/src/messenger/gnunet-service-messenger_message_send.c b/src/messenger/gnunet-service-messenger_message_send.c
index 86cf9b888..59bbaea8d 100644
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ b/src/messenger/gnunet-service-messenger_message_send.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -24,95 +24,38 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_message_send.h" 26#include "gnunet-service-messenger_message_send.h"
27#include "gnunet-service-messenger_message_handle.h"
28 27
29void 28#include "gnunet-service-messenger_member.h"
30send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 29#include "gnunet-service-messenger_member_session.h"
31 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 30#include "gnunet-service-messenger_operation.h"
32 const struct GNUNET_HashCode *hash)
33{
34 if (!tunnel->contact_id)
35 {
36 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
37
38 GNUNET_memcpy(tunnel->contact_id, &(message->body.info.unique_id), sizeof(struct GNUNET_ShortHashCode));
39 }
40 else
41 {
42 disconnect_tunnel (tunnel);
43 }
44}
45 31
46void 32void
47send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 33send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
48 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 34 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
49 const struct GNUNET_HashCode *hash)
50{
51 handle_message_join (room, tunnel, message, hash);
52
53 if (room->peer_message)
54 {
55 const struct GNUNET_MESSENGER_Message *peer_message = get_room_message (room, handle, room->peer_message,
56 GNUNET_NO);
57
58 if ((peer_message) && (tunnel))
59 {
60 forward_tunnel_message (tunnel, peer_message, room->peer_message);
61 }
62 }
63}
64
65void
66send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
67 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
68 const struct GNUNET_HashCode *hash)
69{
70 handle_message_leave (room, tunnel, message, hash);
71}
72
73void
74send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
75 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
76 const struct GNUNET_HashCode *hash)
77{ 35{
78 handle_message_name (room, tunnel, message, hash); 36 check_room_peer_status(room, NULL);
79}
80
81void
82send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
84 const struct GNUNET_HashCode *hash)
85{
86 handle_message_key (room, tunnel, message, hash);
87} 37}
88 38
89void 39void
90send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 40send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
91 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 41 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
92 const struct GNUNET_HashCode *hash)
93{ 42{
94 if (!room->peer_message) 43 if (!room->peer_message)
95 {
96 room->peer_message = GNUNET_new(struct GNUNET_HashCode); 44 room->peer_message = GNUNET_new(struct GNUNET_HashCode);
97 }
98 45
99 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode)); 46 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode));
100
101 handle_message_peer (room, tunnel, message, hash);
102} 47}
103 48
104void 49void
105send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 50send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
106 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
107 const struct GNUNET_HashCode *hash)
108{ 52{
109 handle_message_id (room, tunnel, message, hash); 53 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
110}
111 54
112void 55 use_store_operation(
113send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 56 operation_store,
114 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 57 &(message->body.request.hash),
115 const struct GNUNET_HashCode *hash) 58 GNUNET_MESSENGER_OP_REQUEST,
116{ 59 GNUNET_MESSENGER_REQUEST_DELAY
117 handle_message_miss (room, tunnel, message, hash); 60 );
118} 61}
diff --git a/src/messenger/gnunet-service-messenger_message_send.h b/src/messenger/gnunet-service-messenger_message_send.h
index c1096205a..8e3ff4495 100644
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ b/src/messenger/gnunet-service-messenger_message_send.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,127 +29,48 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31 31
32#include "gnunet-service-messenger_message_kind.h"
33
32#include "gnunet-service-messenger_tunnel.h" 34#include "gnunet-service-messenger_tunnel.h"
33#include "messenger_api_message.h" 35#include "messenger_api_message.h"
34 36
35/** 37/**
36 * Handles a sent info message to setup a tunnels linked member id.
37 * (if a tunnel has already got a member id linked to it, the connection will be closed)
38 *
39 * @param room Room of the message
40 * @param handle Sending handle
41 * @param tunnel Sending connection (may be NULL)
42 * @param message INFO-Message
43 * @param hash Hash of the message
44 */
45void
46send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
47 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
48 const struct GNUNET_HashCode *hash);
49
50/**
51 * Handles a sent join message to ensure growth of the decentralized room structure. 38 * Handles a sent join message to ensure growth of the decentralized room structure.
52 * (if the service provides a peer message for this room currently, it will be forwarded) 39 * (if the service provides a peer message for this room currently, it will be forwarded)
53 * 40 *
54 * @param room Room of the message 41 * @param[in/out] room Room of the message
55 * @param handle Sending handle 42 * @param[in/out] handle Sending handle
56 * @param tunnel Sending connection (may be NULL) 43 * @param[in] message JOIN-Message
57 * @param message JOIN-Message 44 * @param[in] hash Hash of the message
58 * @param hash Hash of the message
59 */ 45 */
60void 46void
61send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 47send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
62 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 48 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
63 const struct GNUNET_HashCode *hash);
64
65/**
66 * Handles a sent leave message.
67 * @see handle_message_leave()
68 *
69 * @param room Room of the message
70 * @param handle Sending handle
71 * @param tunnel Sending connection (may be NULL)
72 * @param message LEAVE-Message
73 * @param hash Hash of the message
74 */
75void
76send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
77 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
78 const struct GNUNET_HashCode *hash);
79
80/**
81 * Handles a sent name message.
82 * @see handle_message_name()
83 *
84 * @param room Room of the message
85 * @param handle Sending handle
86 * @param tunnel Sending connection (may be NULL)
87 * @param message NAME-Message
88 * @param hash Hash of the message
89 */
90void
91send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
92 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
93 const struct GNUNET_HashCode *hash);
94
95/**
96 * Handles a sent key message.
97 * @see handle_message_key()
98 *
99 * @param room Room of the message
100 * @param handle Sending handle
101 * @param tunnel Sending connection (may be NULL)
102 * @param message KEY-Message
103 * @param hash Hash of the message
104 */
105void
106send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
107 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
108 const struct GNUNET_HashCode *hash);
109 49
110/** 50/**
111 * Handles a sent peer message to update the rooms peer message of this service. 51 * Handles a sent peer message to update the rooms peer message of this service.
112 * (a set peer message indicates this service being a part of the decentralized room structure) 52 * (a set peer message indicates this service being a part of the decentralized room structure)
113 * 53 *
114 * @param room Room of the message 54 * @param[in/out] room Room of the message
115 * @param handle Sending handle 55 * @param[in/out] handle Sending handle
116 * @param tunnel Sending connection (may be NULL) 56 * @param[in] message PEER-Message
117 * @param message PEER-Message 57 * @param[in] hash Hash of the message
118 * @param hash Hash of the message
119 */ 58 */
120void 59void
121send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 60send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
122 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
123 const struct GNUNET_HashCode *hash);
124
125/**
126 * Handles a sent id message.
127 * @see handle_message_id()
128 *
129 * @param room Room of the message
130 * @param handle Sending handle
131 * @param tunnel Sending connection (may be NULL)
132 * @param message ID-Message
133 * @param hash Hash of the message
134 */
135void
136send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
137 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message,
138 const struct GNUNET_HashCode *hash);
139 62
140/** 63/**
141 * Handles a sent miss message. 64 * Handles a sent request message to trigger the request operation for this service.
142 * @see handle_message_miss() 65 * (the request operation will deactivate the possibility of spamming requests)
143 * 66 *
144 * @param room Room of the message 67 * @param[in/out] room Room of the message
145 * @param handle Sending handle 68 * @param[in/out] handle Sending handle
146 * @param tunnel Sending connection (may be NULL) 69 * @param[in] message PEER-Message
147 * @param message MISS-Message 70 * @param[in] hash Hash of the message
148 * @param hash Hash of the message
149 */ 71 */
150void 72void
151send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 73send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
152 struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, 74 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
153 const struct GNUNET_HashCode *hash);
154 75
155#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H 76#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c
index 5933d6390..1f3d262ac 100644
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ b/src/messenger/gnunet-service-messenger_message_store.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,10 +29,16 @@
29void 29void
30init_message_store (struct GNUNET_MESSENGER_MessageStore *store) 30init_message_store (struct GNUNET_MESSENGER_MessageStore *store)
31{ 31{
32 GNUNET_assert(store);
33
32 store->storage_messages = NULL; 34 store->storage_messages = NULL;
33 35
34 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 36 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
35 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 37 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39
40 store->rewrite_entries = GNUNET_NO;
41 store->write_links = GNUNET_NO;
36} 42}
37 43
38static int 44static int
@@ -55,9 +61,21 @@ iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *va
55 return GNUNET_YES; 61 return GNUNET_YES;
56} 62}
57 63
64static int
65iterate_destroy_links (void *cls, const struct GNUNET_HashCode *key, void *value)
66{
67 struct GNUNET_HashCode *previous = value;
68
69 GNUNET_free(previous);
70
71 return GNUNET_YES;
72}
73
58void 74void
59clear_message_store (struct GNUNET_MESSENGER_MessageStore *store) 75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
60{ 76{
77 GNUNET_assert(store);
78
61 if (store->storage_messages) 79 if (store->storage_messages)
62 { 80 {
63 GNUNET_DISK_file_close (store->storage_messages); 81 GNUNET_DISK_file_close (store->storage_messages);
@@ -67,9 +85,11 @@ clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
67 85
68 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL); 86 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
69 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL); 87 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
88 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
70 89
71 GNUNET_CONTAINER_multihashmap_destroy (store->entries); 90 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
72 GNUNET_CONTAINER_multihashmap_destroy (store->messages); 91 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
92 GNUNET_CONTAINER_multihashmap_destroy (store->links);
73} 93}
74 94
75struct GNUNET_MESSENGER_MessageEntryStorage 95struct GNUNET_MESSENGER_MessageEntryStorage
@@ -78,36 +98,15 @@ struct GNUNET_MESSENGER_MessageEntryStorage
78 struct GNUNET_MESSENGER_MessageEntry entry; 98 struct GNUNET_MESSENGER_MessageEntry entry;
79}; 99};
80 100
81void 101static void
82load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 102load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
83{ 103{
84 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 104 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
85
86 if (store->storage_messages)
87 GNUNET_DISK_file_close (store->storage_messages);
88
89 char *filename;
90 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
91
92 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
93 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
94 else
95 store->storage_messages = NULL;
96
97 GNUNET_free(filename);
98
99 if (!store->storage_messages)
100 return;
101
102 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
103
104 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
105 goto free_filename;
106 105
107 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission); 106 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
108 107
109 if (!entries) 108 if (!entries)
110 goto free_filename; 109 return;
111 110
112 struct GNUNET_MESSENGER_MessageEntryStorage storage; 111 struct GNUNET_MESSENGER_MessageEntryStorage storage;
113 struct GNUNET_MESSENGER_MessageEntry *entry; 112 struct GNUNET_MESSENGER_MessageEntry *entry;
@@ -120,9 +119,13 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
120 { 119 {
121 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry)); 120 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
122 121
123 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry, 122 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 123 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
125 {
126 store->rewrite_entries = GNUNET_YES;
125 GNUNET_free(entry); 127 GNUNET_free(entry);
128 }
126 } 129 }
127 else 130 else
128 { 131 {
@@ -134,22 +137,118 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
134 while (entry); 137 while (entry);
135 138
136 GNUNET_DISK_file_close (entries); 139 GNUNET_DISK_file_close (entries);
140}
141
142struct GNUNET_MESSENGER_MessageLinkStorage
143{
144 struct GNUNET_HashCode hash;
145 struct GNUNET_MESSENGER_MessageLink link;
146};
147
148static void
149load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
150{
151 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
152
153 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
154
155 if (!entries)
156 return;
157
158 struct GNUNET_MESSENGER_MessageLinkStorage storage;
159 struct GNUNET_MESSENGER_MessageLink *link = NULL;
160
161 do
162 {
163 if ((sizeof(storage.hash) != GNUNET_DISK_file_read (entries, &(storage.hash), sizeof(storage.hash))) ||
164 (sizeof(storage.link.multiple) != GNUNET_DISK_file_read (entries, &(storage.link.multiple), sizeof(storage.link.multiple))) ||
165 (sizeof(storage.link.first) != GNUNET_DISK_file_read (entries, &(storage.link.first), sizeof(storage.link.first))) ||
166 ((GNUNET_YES == storage.link.multiple) &&
167 (sizeof(storage.link.second) != GNUNET_DISK_file_read (entries, &(storage.link.second), sizeof(storage.link.second)))))
168 break;
169
170 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
171
172 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
173
174 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
175 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
176 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
177 break;
178 }
179 while (link);
180
181 if (link)
182 GNUNET_free(link);
183
184 GNUNET_DISK_file_close (entries);
185}
186
187void
188load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
189{
190 GNUNET_assert((store) && (directory));
191
192 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
193
194 if (store->storage_messages)
195 GNUNET_DISK_file_close (store->storage_messages);
196
197 char *filename;
198 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
199
200 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
201 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
202 else
203 store->storage_messages = NULL;
204
205 GNUNET_free(filename);
206
207 if (!store->storage_messages)
208 return;
209
210 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
211
212 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
213 load_message_store_entries(store, filename);
214
215 GNUNET_free(filename);
216
217 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
218
219 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
220 load_message_store_links(store, filename);
137 221
138free_filename:
139 GNUNET_free(filename); 222 GNUNET_free(filename);
140} 223}
141 224
142struct GNUNET_MESSENGER_MessageSave 225struct GNUNET_MESSENGER_ClosureMessageSave
143{ 226{
144 struct GNUNET_MESSENGER_MessageStore *store; 227 struct GNUNET_MESSENGER_MessageStore *store;
145 228
146 struct GNUNET_DISK_FileHandle *storage_entries; 229 struct GNUNET_DISK_FileHandle *storage;
147}; 230};
148 231
149static int 232static int
233iterate_save_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
234{
235 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
236 struct GNUNET_MESSENGER_MessageEntry *entry = value;
237
238 struct GNUNET_MESSENGER_MessageEntryStorage storage;
239
240 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
241 GNUNET_memcpy(&(storage.entry), entry, sizeof(*entry));
242
243 GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage));
244
245 return GNUNET_YES;
246}
247
248static int
150iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value) 249iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
151{ 250{
152 struct GNUNET_MESSENGER_MessageSave *save = cls; 251 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
153 252
154 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key)) 253 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
155 return GNUNET_YES; 254 return GNUNET_YES;
@@ -159,16 +258,16 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
159 258
160 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash)); 259 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
161 260
162 storage.entry.length = get_message_size (message); 261 storage.entry.length = get_message_size (message, GNUNET_YES);
163 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END); 262 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
164 263
165 if ((GNUNET_SYSERR == storage.entry.offset) || 264 if ((GNUNET_SYSERR == storage.entry.offset) || (sizeof(storage)
166 (sizeof(storage) != GNUNET_DISK_file_write (save->storage_entries, &storage, sizeof(storage)))) 265 != GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage))))
167 return GNUNET_YES; 266 return GNUNET_YES;
168 267
169 char *buffer = GNUNET_malloc(storage.entry.length); 268 char *buffer = GNUNET_malloc(storage.entry.length);
170 269
171 encode_message (message, storage.entry.length, buffer); 270 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
172 271
173 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length); 272 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
174 273
@@ -177,25 +276,74 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
177 return GNUNET_YES; 276 return GNUNET_YES;
178} 277}
179 278
279static int
280iterate_save_links (void *cls, const struct GNUNET_HashCode *key, void *value)
281{
282 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
283 struct GNUNET_MESSENGER_MessageLink *link = value;
284
285 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
286 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
287 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
288
289 if (GNUNET_YES == link->multiple)
290 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
291
292 return GNUNET_YES;
293}
294
180void 295void
181save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 296save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
182{ 297{
183 struct GNUNET_MESSENGER_MessageSave save; 298 GNUNET_assert((store) && (directory));
299
300 struct GNUNET_MESSENGER_ClosureMessageSave save;
184 301
185 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 302 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
186 303
187 char *filename; 304 char *filename;
305
306 if (GNUNET_YES != store->write_links)
307 goto save_entries;
308
309 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
310
311 save.store = store;
312 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
313
314 if (!save.storage)
315 goto save_entries;
316
317 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
318 goto close_links;
319
320 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
321 store->write_links = GNUNET_NO;
322
323close_links:
324 GNUNET_DISK_file_close (save.storage);
325
326save_entries:
327 GNUNET_free(filename);
188 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store"); 328 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
189 329
190 save.store = store; 330 save.store = store;
191 save.storage_entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission); 331 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
192 332
193 GNUNET_free(filename); 333 GNUNET_free(filename);
194 334
195 if (!save.storage_entries) 335 if (!save.storage)
196 return; 336 return;
197 337
198 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage_entries, 0, GNUNET_DISK_SEEK_END)) 338 if (GNUNET_YES == store->rewrite_entries)
339 {
340 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
341 goto close_entries;
342
343 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
344 store->rewrite_entries = GNUNET_NO;
345 }
346 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
199 goto close_entries; 347 goto close_entries;
200 348
201 if (store->storage_messages) 349 if (store->storage_messages)
@@ -213,16 +361,18 @@ save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
213 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save); 361 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
214 362
215 GNUNET_DISK_file_sync (store->storage_messages); 363 GNUNET_DISK_file_sync (store->storage_messages);
216 GNUNET_DISK_file_sync (save.storage_entries); 364 GNUNET_DISK_file_sync (save.storage);
217 } 365 }
218 366
219close_entries: 367close_entries:
220 GNUNET_DISK_file_close (save.storage_entries); 368 GNUNET_DISK_file_close (save.storage);
221} 369}
222 370
223int 371int
224contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 372contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
225{ 373{
374 GNUNET_assert((store) && (hash));
375
226 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash)) 376 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
227 return GNUNET_YES; 377 return GNUNET_YES;
228 378
@@ -232,6 +382,8 @@ contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struc
232const struct GNUNET_MESSENGER_Message* 382const struct GNUNET_MESSENGER_Message*
233get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 383get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
234{ 384{
385 GNUNET_assert((store) && (hash));
386
235 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash); 387 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
236 388
237 if (message) 389 if (message)
@@ -250,33 +402,141 @@ get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNU
250 402
251 char *buffer = GNUNET_malloc(entry->length); 403 char *buffer = GNUNET_malloc(entry->length);
252 404
405 if (!buffer)
406 return NULL;
407
253 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) 408 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length)
254 goto free_buffer; 409 goto free_buffer;
255 410
256
257 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN); 411 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
258 412
259 if ((GNUNET_YES != decode_message (message, entry->length, buffer)) || (GNUNET_OK 413 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
260 != GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
261 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
262 {
263 destroy_message (message);
264 414
265 message = NULL; 415 struct GNUNET_HashCode check;
416 hash_message (message, entry->length, buffer, &check);
266 417
418 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
419 {
267 GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry); 420 GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry);
421 store->rewrite_entries = GNUNET_YES;
422
423 goto free_message;
268 } 424 }
269 425
426 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
427 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
428 goto free_buffer;
429
430free_message: destroy_message (message);
431 message = NULL;
432
270free_buffer: 433free_buffer:
271 GNUNET_free(buffer); 434 GNUNET_free(buffer);
272 435
273 return message; 436 return message;
274} 437}
275 438
439const struct GNUNET_MESSENGER_MessageLink*
440get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
441 int deleted_only)
442{
443 if (deleted_only)
444 goto get_link;
445
446 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
447
448 if (!message)
449 goto get_link;
450
451 static struct GNUNET_MESSENGER_MessageLink link;
452
453 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
454
455 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
456
457 if (GNUNET_YES == link.multiple)
458 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
459 else
460 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
461
462 return &link;
463
464get_link:
465 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
466}
467
276int 468int
277put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, 469put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
278 struct GNUNET_MESSENGER_Message *message) 470 struct GNUNET_MESSENGER_Message *message)
279{ 471{
472 GNUNET_assert((store) && (hash) && (message));
473
280 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, 474 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
281 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 475 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
282} 476}
477
478static void
479add_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
480 const struct GNUNET_MESSENGER_Message *message)
481{
482 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
483
484 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
485
486 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
487
488 if (GNUNET_YES == link->multiple)
489 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
490 else
491 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
492
493 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
494 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
495 GNUNET_free(link);
496}
497
498int
499delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
500{
501 GNUNET_assert((store) && (hash));
502
503 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
504
505 if (!entry)
506 goto clear_memory;
507
508 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
509
510 if (message)
511 add_link (store, hash, message);
512
513 if (!store->storage_messages)
514 goto clear_entry;
515
516 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
517 return GNUNET_SYSERR;
518
519 char *clear_buffer = GNUNET_malloc(entry->length);
520
521 if (!clear_buffer)
522 return GNUNET_SYSERR;
523
524 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
525
526 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
527 != GNUNET_DISK_file_sync (store->storage_messages)))
528 {
529 GNUNET_free(clear_buffer);
530 return GNUNET_SYSERR;
531 }
532
533 GNUNET_free(clear_buffer);
534
535clear_entry:
536 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
537 store->rewrite_entries = GNUNET_YES;
538
539clear_memory:
540 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
541 return GNUNET_OK;
542}
diff --git a/src/messenger/gnunet-service-messenger_message_store.h b/src/messenger/gnunet-service-messenger_message_store.h
index e58459b21..87305826a 100644
--- a/src/messenger/gnunet-service-messenger_message_store.h
+++ b/src/messenger/gnunet-service-messenger_message_store.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -36,85 +36,127 @@ struct GNUNET_MESSENGER_MessageEntry
36 uint16_t length; 36 uint16_t length;
37}; 37};
38 38
39struct GNUNET_MESSENGER_Message;
40
41struct GNUNET_MESSENGER_MessageLink
42{
43 uint8_t multiple;
44
45 struct GNUNET_HashCode first;
46 struct GNUNET_HashCode second;
47};
48
39struct GNUNET_MESSENGER_MessageStore 49struct GNUNET_MESSENGER_MessageStore
40{ 50{
41 struct GNUNET_DISK_FileHandle *storage_messages; 51 struct GNUNET_DISK_FileHandle *storage_messages;
42 52
43 struct GNUNET_CONTAINER_MultiHashMap *entries; 53 struct GNUNET_CONTAINER_MultiHashMap *entries;
44 struct GNUNET_CONTAINER_MultiHashMap *messages; 54 struct GNUNET_CONTAINER_MultiHashMap *messages;
55 struct GNUNET_CONTAINER_MultiHashMap *links;
56
57 int rewrite_entries;
58 int write_links;
45}; 59};
46 60
47/** 61/**
48 * Initializes a message store as fully empty. 62 * Initializes a message <i>store</i> as fully empty.
49 * 63 *
50 * @param store Message store 64 * @param[out] store Message store
51 */ 65 */
52void 66void
53init_message_store (struct GNUNET_MESSENGER_MessageStore *store); 67init_message_store (struct GNUNET_MESSENGER_MessageStore *store);
54 68
55/** 69/**
56 * Clears a message store, wipes its content and deallocates its memory. 70 * Clears a message <i>store</i>, wipes its content and deallocates its memory.
57 * 71 *
58 * @param store Message store 72 * @param[in/out] store Message store
59 */ 73 */
60void 74void
61clear_message_store (struct GNUNET_MESSENGER_MessageStore *store); 75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store);
62 76
63/** 77/**
64 * Loads messages from a directory into a message store. 78 * Loads messages from a <i>directory</i> into a message <i>store</i>.
65 * 79 *
66 * @param store Message store 80 * @param[out] store Message store
67 * @param directory Path to a directory 81 * @param[in] directory Path to a directory
68 */ 82 */
69void 83void
70load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); 84load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
71 85
72/** 86/**
73 * Saves messages from a message store into a directory. 87 * Saves messages from a message <i>store</i> into a <i>directory</i>.
74 * 88 *
75 * @param store Message store 89 * @param[in] store Message store
76 * @param directory Path to a directory 90 * @param[in] directory Path to a directory
77 */ 91 */
78void 92void
79save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); 93save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
80 94
81/** 95/**
82 * Checks if a message matching a given <i>hash</i> is stored in a message store. The function returns 96 * Checks if a message matching a given <i>hash</i> is stored in a message <i>store</i>.
83 * GNUNET_YES if a match is found, GNUNET_NO otherwise. 97 * The function returns #GNUNET_YES if a match is found, #GNUNET_NO otherwise.
84 * 98 *
85 * The message has not to be loaded from disk into memory for this check! 99 * The message has not to be loaded from disk into memory for this check!
86 * 100 *
87 * @param store Message store 101 * @param[in] store Message store
88 * @param hash Hash of message 102 * @param[in] hash Hash of message
89 * @return GNUNET_YES on match, otherwise GNUNET_NO 103 * @return #GNUNET_YES on match, otherwise #GNUNET_NO
90 */ 104 */
91int 105int
92contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); 106contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
93 107
94/** 108/**
95 * Returns the message from a message store matching a given <i>hash</i>. If no matching message is found, 109 * Returns the message from a message <i>store</i> matching a given <i>hash</i>. If no matching
96 * NULL gets returned. 110 * message is found, NULL gets returned.
97 * 111 *
98 * This function requires the message to be loaded into memory! 112 * This function requires the message to be loaded into memory!
99 * @see contains_store_message() 113 * @see contains_store_message()
100 * 114 *
101 * @param store Message store 115 * @param[in/out] store Message store
102 * @param hash Hash of message 116 * @param[in] hash Hash of message
103 * @return Message or NULL 117 * @return Message or NULL
104 */ 118 */
105const struct GNUNET_MESSENGER_Message* 119const struct GNUNET_MESSENGER_Message*
106get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); 120get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
107 121
108/** 122/**
123 * Returns the message link from a message <i>store</i> matching a given <i>hash</i>. If the
124 * flag is set to #GNUNET_YES, only links from deleted messages will be returned or NULL.
125 *
126 * Otherwise message links will also returned for messages found in the store under the given
127 * hash. The link which will be returned copies link information from the message for
128 * temporary usage.
129 *
130 * @param[in/out] store Message store
131 * @param[in] hash Hash of message
132 * @param[in] deleted_only Flag
133 * @return Message link or NULL
134 */
135const struct GNUNET_MESSENGER_MessageLink*
136get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
137 int deleted_only);
138
139/**
109 * Stores a message into the message store. The result indicates if the operation was successful. 140 * Stores a message into the message store. The result indicates if the operation was successful.
110 * 141 *
111 * @param store Message store 142 * @param[in/out] store Message store
112 * @param hash Hash of message 143 * @param[in] hash Hash of message
113 * @param message Message 144 * @param[in/out] message Message
114 * @return GNUNET_OK on success, otherwise GNUNET_NO 145 * @return #GNUNET_OK on success, otherwise #GNUNET_NO
115 */ 146 */
116int 147int
117put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, 148put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
118 struct GNUNET_MESSENGER_Message *message); 149 struct GNUNET_MESSENGER_Message *message);
119 150
151/**
152 * Deletes a message in the message store. It will be removed from disk space and memory. The result
153 * indicates if the operation was successful.
154 *
155 * @param[in/out] store Message store
156 * @param[in] hash Hash of message
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
158 */
159int
160delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
161
120#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H 162#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_operation.c b/src/messenger/gnunet-service-messenger_operation.c
new file mode 100644
index 000000000..d0c378699
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation.c
@@ -0,0 +1,214 @@
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 src/messenger/gnunet-service-messenger_operation.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation.h"
27
28#include "gnunet-service-messenger_operation_store.h"
29
30struct GNUNET_MESSENGER_Operation*
31create_operation (const struct GNUNET_HashCode *hash)
32{
33 GNUNET_assert(hash);
34
35 struct GNUNET_MESSENGER_Operation *op = GNUNET_new(struct GNUNET_MESSENGER_Operation);
36
37 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
38 GNUNET_memcpy(&(op->hash), hash, sizeof(*hash));
39 op->timestamp = GNUNET_TIME_absolute_get_zero_();
40 op->store = NULL;
41 op->task = NULL;
42
43 return op;
44}
45
46void
47destroy_operation (struct GNUNET_MESSENGER_Operation *op)
48{
49 GNUNET_assert(op);
50
51 if (op->task)
52 GNUNET_SCHEDULER_cancel(op->task);
53
54 GNUNET_free(op);
55}
56
57static void
58callback_operation (void *cls);
59
60struct GNUNET_MESSENGER_Operation*
61load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path)
62{
63 GNUNET_assert((store) && (path));
64
65 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
66 struct GNUNET_MESSENGER_Operation* op = NULL;
67
68 if (GNUNET_OK != GNUNET_CONFIGURATION_parse(cfg, path))
69 goto destroy_config;
70
71 struct GNUNET_HashCode hash;
72
73 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "hash", &hash, sizeof(hash)))
74 goto destroy_config;
75
76 op = create_operation(&hash);
77
78 unsigned long long type_number;
79 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg, "operation", "type", &type_number))
80 switch (type_number)
81 {
82 case GNUNET_MESSENGER_OP_REQUEST:
83 op->type = GNUNET_MESSENGER_OP_REQUEST;
84 break;
85 case GNUNET_MESSENGER_OP_DELETE:
86 op->type = GNUNET_MESSENGER_OP_DELETE;
87 break;
88 case GNUNET_MESSENGER_OP_MERGE:
89 op->type = GNUNET_MESSENGER_OP_MERGE;
90 break;
91 default:
92 break;
93 }
94
95 if ((GNUNET_MESSENGER_OP_UNKNOWN == op->type) ||
96 (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "timestamp", &(op->timestamp), sizeof(op->timestamp))))
97 {
98 destroy_operation(op);
99 op = NULL;
100 goto destroy_config;
101 }
102
103 const struct GNUNET_TIME_Relative delay = GNUNET_TIME_absolute_get_remaining(op->timestamp);
104
105 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
106 delay,
107 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
108 callback_operation,
109 op
110 );
111
112 op->store = store;
113
114destroy_config:
115 GNUNET_CONFIGURATION_destroy (cfg);
116
117 return op;
118}
119
120void
121save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path)
122{
123 GNUNET_assert((path) && (op));
124
125 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
126
127 char *hash_data;
128 hash_data = GNUNET_STRINGS_data_to_string_alloc (&(op->hash), sizeof(op->hash));
129
130 if (hash_data)
131 {
132 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "hash", hash_data);
133
134 GNUNET_free(hash_data);
135 }
136
137 GNUNET_CONFIGURATION_set_value_number(cfg, "operation", "type", op->type);
138
139 char *timestamp_data;
140 timestamp_data = GNUNET_STRINGS_data_to_string_alloc (&(op->timestamp), sizeof(op->timestamp));
141
142 if (timestamp_data)
143 {
144 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "timestamp", timestamp_data);
145
146 GNUNET_free(timestamp_data);
147 }
148
149 GNUNET_CONFIGURATION_write (cfg, path);
150 GNUNET_CONFIGURATION_destroy (cfg);
151}
152
153extern void
154callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
155 enum GNUNET_MESSENGER_OperationType type,
156 const struct GNUNET_HashCode *hash);
157
158static void
159callback_operation (void *cls)
160{
161 struct GNUNET_MESSENGER_Operation *op = cls;
162
163 op->task = NULL;
164
165 callback_store_operation (op->store, op->type, &(op->hash));
166}
167
168int
169start_operation (struct GNUNET_MESSENGER_Operation *op,
170 enum GNUNET_MESSENGER_OperationType type,
171 struct GNUNET_MESSENGER_OperationStore *store,
172 struct GNUNET_TIME_Relative delay)
173{
174 GNUNET_assert((op) && (store));
175
176 if (op->task)
177 return GNUNET_SYSERR;
178
179 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_add(
180 GNUNET_TIME_absolute_get(),
181 delay
182 );
183
184 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
185 delay,
186 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
187 callback_operation,
188 op
189 );
190
191 op->type = type;
192 op->timestamp = timestamp;
193 op->store = store;
194
195 return GNUNET_OK;
196}
197
198int
199stop_operation (struct GNUNET_MESSENGER_Operation *op)
200{
201 GNUNET_assert(op);
202
203 if (!op->task)
204 return GNUNET_SYSERR;
205
206 GNUNET_SCHEDULER_cancel(op->task);
207 op->task = NULL;
208
209 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
210 op->timestamp = GNUNET_TIME_absolute_get_zero_();
211 op->store = NULL;
212
213 return GNUNET_OK;
214}
diff --git a/src/messenger/gnunet-service-messenger_operation.h b/src/messenger/gnunet-service-messenger_operation.h
new file mode 100644
index 000000000..7757b8e88
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation.h
@@ -0,0 +1,129 @@
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 src/messenger/gnunet-service-messenger_operation.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_H
28
29#include "platform.h"
30#include "gnunet_configuration_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_strings_lib.h"
34#include "gnunet_time_lib.h"
35
36enum GNUNET_MESSENGER_OperationType
37{
38 GNUNET_MESSENGER_OP_REQUEST = 1,
39 GNUNET_MESSENGER_OP_DELETE = 2,
40 GNUNET_MESSENGER_OP_MERGE = 3,
41
42 GNUNET_MESSENGER_OP_UNKNOWN = 0
43};
44
45struct GNUNET_MESSENGER_OperationStore;
46
47struct GNUNET_MESSENGER_Operation
48{
49 enum GNUNET_MESSENGER_OperationType type;
50
51 struct GNUNET_HashCode hash;
52 struct GNUNET_TIME_Absolute timestamp;
53
54 struct GNUNET_MESSENGER_OperationStore *store;
55 struct GNUNET_SCHEDULER_Task* task;
56};
57
58/**
59 * Creates and allocates a new operation under a given <i>hash</i>.
60 *
61 * @param[in] hash Hash of message
62 */
63struct GNUNET_MESSENGER_Operation*
64create_operation (const struct GNUNET_HashCode *hash);
65
66/**
67 * Destroys an operation and frees its memory fully.
68 *
69 * @param[in/out] op Operation
70 */
71void
72destroy_operation (struct GNUNET_MESSENGER_Operation *op);
73
74/**
75 * Loads data from a configuration file at a selected <i>path</i> into
76 * a new allocated and created operation for a specific operation
77 * <i>store</i> if the required information could be read successfully.
78 *
79 * The method will return the new operation and it will be started
80 * automatically to match its timestamp of execution.
81 *
82 * If the method fails to restore any valid operation from the file,
83 * NULL gets returned instead.
84 *
85 * @param[in/out] store Operation store
86 * @param[in] path Path of a configuration file
87 */
88struct GNUNET_MESSENGER_Operation*
89load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path);
90
91/**
92 * Saves data from an <i>operation</i> into a configuration file at a
93 * selected <i>path</i> which can be load to restore the operation
94 * completely and continue its process.
95 *
96 * @param[in] op Operation
97 * @param[in] path Path of a configuration file
98 */
99void
100save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path);
101
102/**
103 * Starts an inactive operation with a given <i>delay</i> in a
104 * specific operation <i>store</i>. The method will replace the
105 * operations type to process it correctly. An opeation can't be
106 * started twice, it has to be stopped or fully processed first.
107 *
108 * @param[in/out] op Operation
109 * @param[in] type Type of operation
110 * @param[in/out] store Operation store
111 * @param[in] delay Delay
112 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
113 */
114int
115start_operation (struct GNUNET_MESSENGER_Operation *op,
116 enum GNUNET_MESSENGER_OperationType type,
117 struct GNUNET_MESSENGER_OperationStore *store,
118 struct GNUNET_TIME_Relative delay);
119
120/**
121 * Stops an active operation and resets its type to be
122 * #GNUNET_MESSENGER_OP_UNKNOWN.
123 *
124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
125 */
126int
127stop_operation (struct GNUNET_MESSENGER_Operation *op);
128
129#endif //GNUNET_SERVICE_MESSENGER_OPERATION_H
diff --git a/src/messenger/gnunet-service-messenger_operation_store.c b/src/messenger/gnunet-service-messenger_operation_store.c
new file mode 100644
index 000000000..05985ef84
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation_store.c
@@ -0,0 +1,224 @@
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 src/messenger/gnunet-service-messenger_operation_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation_store.h"
27
28#include "gnunet-service-messenger_operation.h"
29#include "gnunet-service-messenger_room.h"
30
31void
32init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
33{
34 GNUNET_assert((store) && (room));
35
36 store->room = room;
37 store->operations = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Operation *op = value;
44
45 destroy_operation(op);
46
47 return GNUNET_YES;
48}
49
50void
51clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
52{
53 GNUNET_assert(store);
54
55 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_destroy_operations, NULL);
56 GNUNET_CONTAINER_multihashmap_destroy(store->operations);
57}
58
59static int
60callback_scan_for_operations (void *cls, const char *filename)
61{
62 struct GNUNET_MESSENGER_OperationStore *store = cls;
63
64 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
65 {
66 char *path;
67
68 GNUNET_asprintf (&path, "%s%c", filename, DIR_SEPARATOR);
69
70 struct GNUNET_MESSENGER_Operation *op = load_operation(store, path);
71
72 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
73 store->operations,
74 &(op->hash), op,
75 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
76 {
77 destroy_operation(op);
78 }
79
80 GNUNET_free(path);
81 }
82
83 return GNUNET_OK;
84}
85
86void
87load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
88 const char *directory)
89{
90 GNUNET_assert ((store) && (directory));
91
92 if (GNUNET_OK == GNUNET_DISK_directory_test (directory, GNUNET_YES))
93 GNUNET_DISK_directory_scan (directory, callback_scan_for_operations, store);
94}
95
96static int
97iterate_save_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
98{
99 const char *save_dir = cls;
100
101 struct GNUNET_MESSENGER_Operation *op = value;
102
103 if (!op)
104 return GNUNET_YES;
105
106 char *op_dir;
107 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s(key));
108 save_operation(op, op_dir);
109
110 GNUNET_free(op_dir);
111 return GNUNET_YES;
112}
113
114void
115save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
116 const char *directory)
117{
118 GNUNET_assert ((store) && (directory));
119
120 char* save_dir;
121 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
122
123 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
124 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
125 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_save_operations, save_dir);
126
127 GNUNET_free(save_dir);
128}
129
130enum GNUNET_MESSENGER_OperationType
131get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
132 const struct GNUNET_HashCode *hash)
133{
134 GNUNET_assert((store) && (hash));
135
136 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
137
138 if (!op)
139 return GNUNET_MESSENGER_OP_UNKNOWN;
140
141 return op->type;
142}
143
144int
145use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
146 const struct GNUNET_HashCode *hash,
147 enum GNUNET_MESSENGER_OperationType type,
148 struct GNUNET_TIME_Relative delay)
149{
150 GNUNET_assert((store) && (hash));
151
152 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
153
154 if (op)
155 goto use_op;
156
157 op = create_operation(hash);
158
159 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->operations, hash, op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
160 {
161 destroy_operation(op);
162
163 return GNUNET_SYSERR;
164 }
165
166use_op:
167 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
168 (type == GNUNET_MESSENGER_OP_DELETE))
169 stop_operation (op);
170
171 return start_operation(op, type, store, delay);
172}
173
174void
175cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
176 const struct GNUNET_HashCode *hash)
177{
178 GNUNET_assert((store) && (hash));
179
180 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
181
182 if (!op)
183 return;
184
185 stop_operation(op);
186
187 GNUNET_CONTAINER_multihashmap_remove(store->operations, hash, op);
188
189 destroy_operation(op);
190}
191
192extern void
193callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
194
195extern void
196callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
197
198void
199callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
200 enum GNUNET_MESSENGER_OperationType type,
201 const struct GNUNET_HashCode *hash)
202{
203 GNUNET_assert((store) && (hash));
204
205 struct GNUNET_HashCode op_hash;
206 GNUNET_memcpy(&op_hash, hash, sizeof(op_hash));
207 cancel_store_operation (store, &op_hash);
208
209 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
210
211 switch (type)
212 {
213 case GNUNET_MESSENGER_OP_REQUEST:
214 break;
215 case GNUNET_MESSENGER_OP_DELETE:
216 callback_room_deletion (room, &op_hash);
217 break;
218 case GNUNET_MESSENGER_OP_MERGE:
219 callback_room_merge (room, &op_hash);
220 break;
221 default:
222 break;
223 }
224}
diff --git a/src/messenger/gnunet-service-messenger_operation_store.h b/src/messenger/gnunet-service-messenger_operation_store.h
new file mode 100644
index 000000000..2fd604340
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_operation_store.h
@@ -0,0 +1,131 @@
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 src/messenger/gnunet-service-messenger_operation_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_time_lib.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_OperationStore
38{
39 struct GNUNET_MESSENGER_SrvRoom *room;
40
41 struct GNUNET_CONTAINER_MultiHashMap *operations;
42};
43
44/**
45 * Initializes an operation <i>store</i> as fully empty with a given <i>room</i>.
46 *
47 * @param[out] store Operation store
48 * @param[in/out] room Room
49 */
50void
51init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
52
53/**
54 * Clears an operation <i>store</i>, stops all operations and deallocates its memory.
55 *
56 * @param[in/out] store Operation store
57 */
58void
59clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store);
60
61/**
62 * Loads operations from a <i>directory</i> into an operation <i>store</i>.
63 *
64 * @param[out] store Operation store
65 * @param[in] directory Path to a directory
66 */
67void
68load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
69 const char *directory);
70
71/**
72 * Saves operations from an operation <i>store</i> into a <i>directory</i>.
73 *
74 * @param[in] store Operation store
75 * @param[in] directory Path to a directory
76 */
77void
78save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
79 const char *directory);
80
81/**
82 * Retruns the type of the active operation under a given <i>hash</i> in
83 * a specific operation <i>store</i>. If there is no active operation under
84 * the given <i>hash</i>, #GNUNET_MESSENGER_OP_UNKNOWN gets returned instead.
85 *
86 * @param[in] store Operation store
87 * @param[in] hash Hash of message
88 * @return Type of operation or #GNUNET_MESSENGER_OP_UNKNOWN
89 */
90enum GNUNET_MESSENGER_OperationType
91get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
92 const struct GNUNET_HashCode *hash);
93
94/**
95 * Tries to use an operation under a given <i>hash</i> in a specific
96 * operation <i>store</i>. The operation will use the selected <i>type</i>
97 * if successful. The operation will be delayed by a given <i>delay</i>.
98 *
99 * If the selected type is #GNUNET_MESSENGER_OP_DELETE any active operation
100 * under the given hash will be stopped and replaced.
101 *
102 * If the new operation could be started successfully the method returns
103 * #GNUNET_OK, otherwise #GNUNET_SYSERR.
104 *
105 * @param[in/out] store Operation store
106 * @param[in] hash Hash of message
107 * @param[in] type Operation type
108 * @param[in] delay Delay
109 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
110 */
111int
112use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
113 const struct GNUNET_HashCode *hash,
114 enum GNUNET_MESSENGER_OperationType type,
115 struct GNUNET_TIME_Relative delay);
116
117/**
118 * Stops any active operation under a given <i>hash</i> in a specific
119 * operation <i>store</i>.
120 *
121 * Beware that calling this method will also implicitly free the memory
122 * of any active operation under the given hash!
123 *
124 * @param[in/out] store Operation store
125 * @param[in] hash Hash of message
126 */
127void
128cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
129 const struct GNUNET_HashCode *hash);
130
131#endif //GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
index 7383e1d20..e0bec7991 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -25,10 +25,19 @@
25 25
26#include "gnunet-service-messenger_room.h" 26#include "gnunet-service-messenger_room.h"
27 27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_member_session.h"
30
28#include "gnunet-service-messenger_message_kind.h" 31#include "gnunet-service-messenger_message_kind.h"
32#include "gnunet-service-messenger_message_handle.h"
33#include "gnunet-service-messenger_message_send.h"
29 34
35#include "gnunet-service-messenger_operation.h"
36
37#include "gnunet-service-messenger.h"
30#include "gnunet-service-messenger_service.h" 38#include "gnunet-service-messenger_service.h"
31#include "gnunet-service-messenger_util.h" 39#include "gnunet-service-messenger_tunnel.h"
40#include "messenger_api_util.h"
32 41
33static void 42static void
34idle_request_room_messages (void *cls); 43idle_request_room_messages (void *cls);
@@ -47,11 +56,10 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
47 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode)); 56 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
48 57
49 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO); 58 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
50 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
51 room->member_infos = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
52 59
53 init_message_store (&(room->store)); 60 init_member_store(get_room_member_store(room), room);
54 room->requested = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 61 init_message_store (get_room_message_store(room));
62 init_operation_store(get_room_operation_store(room), room);
55 63
56 init_list_tunnels (&(room->basement)); 64 init_list_tunnels (&(room->basement));
57 init_list_messages (&(room->last_messages)); 65 init_list_messages (&(room->last_messages));
@@ -61,10 +69,8 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
61 init_list_messages (&(room->handling)); 69 init_list_messages (&(room->handling));
62 room->idle = NULL; 70 room->idle = NULL;
63 71
64 room->strict_access = GNUNET_NO;
65
66 if (room->service->dir) 72 if (room->service->dir)
67 load_service_room_and_messages (room->service, room); 73 load_room (room);
68 74
69 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room); 75 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
70 76
@@ -79,34 +85,8 @@ iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void
79 return GNUNET_YES; 85 return GNUNET_YES;
80} 86}
81 87
82static int 88static void
83iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value) 89handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
84{
85 struct GNUNET_MESSENGER_SrvContact *contact = value;
86
87 if (GNUNET_YES == decrease_contact_rc (contact))
88 {
89 struct GNUNET_MESSENGER_SrvRoom *room = cls;
90
91 const struct GNUNET_HashCode *id = get_contact_id_from_key (contact);
92
93 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->service->contacts, id, contact))
94 destroy_contact (contact);
95 }
96
97 return GNUNET_YES;
98}
99
100static int
101iterate_destroy_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
102{
103 struct GNUNET_MESSENGER_MemberInfo *info = value;
104
105 clear_list_messages (&(info->session_messages));
106
107 GNUNET_free(info);
108 return GNUNET_YES;
109}
110 90
111void 91void
112destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) 92destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
@@ -123,26 +103,18 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
123 if (room->port) 103 if (room->port)
124 GNUNET_CADET_close_port (room->port); 104 GNUNET_CADET_close_port (room->port);
125 105
126 merge_room_last_messages (room, room->host); 106 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
127
128 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels,
129 NULL);
130 107
131 handle_room_messages (room); 108 handle_room_messages (room);
132 109
133 if (room->service->dir) 110 if (room->service->dir)
134 save_service_room_and_messages (room->service, room); 111 save_room (room);
135
136 GNUNET_CONTAINER_multishortmap_iterate (room->members, iterate_clear_members, room);
137 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_destroy_member_infos, NULL);
138 112
139 clear_message_store (&(room->store)); 113 clear_member_store (get_room_member_store(room));
140 114 clear_message_store (get_room_message_store(room));
141 GNUNET_CONTAINER_multihashmap_destroy (room->requested); 115 clear_operation_store(get_room_operation_store(room));
142 116
143 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); 117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
144 GNUNET_CONTAINER_multishortmap_destroy (room->members);
145 GNUNET_CONTAINER_multishortmap_destroy (room->member_infos);
146 118
147 clear_list_tunnels (&(room->basement)); 119 clear_list_tunnels (&(room->basement));
148 clear_list_messages (&(room->last_messages)); 120 clear_list_messages (&(room->last_messages));
@@ -153,47 +125,28 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
153 GNUNET_free(room); 125 GNUNET_free(room);
154} 126}
155 127
156struct GNUNET_MESSENGER_SrvContact* 128struct GNUNET_MESSENGER_MemberStore*
157get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) 129get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
158{ 130{
159 GNUNET_assert((room) && (room->members)); 131 GNUNET_assert(room);
160
161 return GNUNET_CONTAINER_multishortmap_get (room->members, id);
162}
163
164void
165add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id,
166 const struct GNUNET_IDENTITY_PublicKey *pubkey)
167{
168 struct GNUNET_MESSENGER_SrvContact *contact = get_service_contact_by_pubkey (room->service, pubkey);
169 132
170 if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, id, contact, 133 return &(room->member_store);
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
172 increase_contact_rc (contact);
173} 134}
174 135
175struct GNUNET_MESSENGER_MemberInfo* 136struct GNUNET_MESSENGER_MessageStore*
176get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) 137get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
177{ 138{
178 GNUNET_assert((room) && (room->member_infos)); 139 GNUNET_assert(room);
179 140
180 return GNUNET_CONTAINER_multishortmap_get (room->member_infos, id); 141 return &(room->message_store);
181} 142}
182 143
183struct GNUNET_ShortHashCode* 144struct GNUNET_MESSENGER_OperationStore*
184generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room) 145get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
185{ 146{
186 struct GNUNET_ShortHashCode *unique_id = GNUNET_new(struct GNUNET_ShortHashCode);
187
188 GNUNET_assert(room); 147 GNUNET_assert(room);
189 148
190 if (GNUNET_YES == generate_free_member_id (unique_id, room->members)) 149 return &(room->operation_store);
191 return unique_id;
192 else
193 {
194 GNUNET_free(unique_id);
195 return NULL;
196 }
197} 150}
198 151
199const struct GNUNET_ShortHashCode* 152const struct GNUNET_ShortHashCode*
@@ -201,7 +154,7 @@ get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room)
201{ 154{
202 GNUNET_assert(room); 155 GNUNET_assert(room);
203 156
204 return get_handle_member_id (room->host, &(room->key)); 157 return get_handle_member_id (room->host, get_room_key(room));
205} 158}
206 159
207void 160void
@@ -209,47 +162,17 @@ change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_
209{ 162{
210 GNUNET_assert(room); 163 GNUNET_assert(room);
211 164
212 change_handle_member_id (room->host, &(room->key), unique_id); 165 change_handle_member_id (room->host, get_room_key(room), unique_id);
213} 166}
214 167
215static int 168static int
216send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 169send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
217 struct GNUNET_MESSENGER_SrvTunnel *tunnel) 170 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
218{ 171{
219 if (!handle) 172 if ((!handle) || (!is_tunnel_connected (tunnel)))
220 return GNUNET_NO;
221
222 merge_room_last_messages (room, handle);
223
224 if (!is_tunnel_connected (tunnel))
225 return GNUNET_NO;
226
227 struct GNUNET_MESSENGER_Message *message = create_message_info (get_handle_ego(handle), room->members);
228
229 if (!message)
230 return GNUNET_NO; 173 return GNUNET_NO;
231 174
232 if ((tunnel->peer_message) && (tunnel->contact_id)) 175 return send_tunnel_message (tunnel, handle, create_message_info (get_handle_ego (handle)));
233 {
234 GNUNET_memcpy(&(message->body.info.unique_id), &(tunnel->contact_id), sizeof(struct GNUNET_ShortHashCode));
235 GNUNET_free(tunnel->contact_id);
236
237 tunnel->contact_id = NULL;
238 }
239
240 struct GNUNET_HashCode hash;
241
242 send_tunnel_message (tunnel, handle, message, &hash);
243 destroy_message (message);
244
245 if (tunnel->contact_id)
246 {
247 GNUNET_free(tunnel->contact_id);
248
249 tunnel->contact_id = NULL;
250 }
251
252 return GNUNET_YES;
253} 176}
254 177
255static void* 178static void*
@@ -257,63 +180,51 @@ callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const st
257{ 180{
258 struct GNUNET_MESSENGER_SrvRoom *room = cls; 181 struct GNUNET_MESSENGER_SrvRoom *room = cls;
259 182
260 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, source); 183 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
261 184
262 if (tunnel) 185 if ((tunnel) &&
186 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
263 { 188 {
264 if (GNUNET_YES == bind_tunnel (tunnel, channel)) 189 destroy_tunnel (tunnel);
265 { 190 tunnel = NULL;
266 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
267 return tunnel;
268 else
269 {
270 disconnect_tunnel (tunnel);
271 return NULL;
272 }
273 }
274 else
275 {
276 delayed_disconnect_channel (channel);
277 return NULL;
278 }
279 } 191 }
280 else 192
193 if (!tunnel)
281 { 194 {
282 tunnel = create_tunnel (room, source); 195 delayed_disconnect_channel (channel);
196 return NULL;
197 }
283 198
284 if ((GNUNET_YES == bind_tunnel (tunnel, channel)) && (GNUNET_OK 199 bind_tunnel(tunnel, channel);
285 == GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
286 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
287 {
288 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
289 return tunnel;
290 else
291 {
292 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel);
293 200
294 disconnect_tunnel (tunnel); 201 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
295 destroy_tunnel (tunnel); 202 GNUNET_h2s(get_room_key(room)), GNUNET_i2s (source));
296 return NULL;
297 }
298 }
299 else
300 {
301 tunnel->channel = NULL;
302 destroy_tunnel (tunnel);
303 203
304 delayed_disconnect_channel (channel); 204 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
305 return NULL; 205 return tunnel;
306 } 206
307 } 207 disconnect_tunnel (tunnel);
208
209 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
210 destroy_tunnel (tunnel);
211
212 return NULL;
308} 213}
309 214
310static int 215static int
311join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 216join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
312 const struct GNUNET_ShortHashCode *member_id) 217 struct GNUNET_MESSENGER_Member *member)
313{ 218{
314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s(get_room_key(room)), GNUNET_sh2s(member_id)); 219 GNUNET_assert((room) && (handle) && (member));
220
221 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_room_key (room)),
222 GNUNET_sh2s (get_member_id(member)));
223
224 if (GNUNET_OK != change_handle_member_id (handle, get_room_key(room), get_member_id(member)))
225 return GNUNET_NO;
315 226
316 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego(handle)); 227 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego (handle));
317 228
318 if (!message) 229 if (!message)
319 { 230 {
@@ -322,48 +233,74 @@ join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
322 return GNUNET_NO; 233 return GNUNET_NO;
323 } 234 }
324 235
325 struct GNUNET_HashCode hash; 236 return send_room_message (room, handle, message);
237}
326 238
327 send_room_message (room, handle, message, &hash); 239struct GNUNET_MESSENGER_MemberNotify
328 destroy_message (message); 240{
241 struct GNUNET_MESSENGER_SrvRoom *room;
242 struct GNUNET_MESSENGER_SrvHandle *handle;
243 struct GNUNET_MESSENGER_MemberSession *session;
244};
329 245
330 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo); 246static int
247iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
248 struct GNUNET_MESSENGER_MemberSession *session)
249{
250 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
331 251
332 info->access = GNUNET_MESSENGER_MEMBER_ALLOWED; 252 if (notify->session == session)
333 init_list_messages (&(info->session_messages)); 253 return GNUNET_YES;
334 254
335 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, member_id, info, 255 struct GNUNET_MESSENGER_ListMessage *element;
336 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
337 {
338 change_handle_member_id (handle, &(room->key), member_id);
339 256
340 add_to_list_messages (&(info->session_messages), &hash); 257 for (element = session->messages.head; element; element = element->next)
341 return GNUNET_YES;
342 }
343 else
344 { 258 {
345 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Your member information could not be registered!\n"); 259 const struct GNUNET_MESSENGER_Message *message = get_room_message (
260 notify->room, notify->handle, &(element->hash), GNUNET_NO
261 );
346 262
347 GNUNET_free(info); 263 if (message)
348 return GNUNET_NO; 264 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash));
349 } 265 }
266
267 return GNUNET_YES;
350} 268}
351 269
352static int 270static int
353join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 271join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
354{ 272{
355 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 273 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
274
275 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
276 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
277
278 if (GNUNET_NO == join_room (room, handle, member))
279 return GNUNET_NO;
356 280
357 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 281 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
282 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
358 283
359 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id))) 284 if (!session)
285 {
286 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
360 return GNUNET_NO; 287 return GNUNET_NO;
288 }
289
290 struct GNUNET_MESSENGER_MemberNotify notify;
291
292 notify.room = room;
293 notify.handle = handle;
294 notify.session = session;
295
296 iterate_store_members(get_room_member_store(room), iterate_notify_about_members, &notify);
361 297
362 return GNUNET_YES; 298 return GNUNET_YES;
363} 299}
364 300
365extern int 301extern int
366check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 302check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
303
367extern void 304extern void
368handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 305handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
369 306
@@ -373,24 +310,39 @@ callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channe
373int 310int
374open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 311open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
375{ 312{
313 GNUNET_assert((room) && (handle));
314
376 if (room->port) 315 if (room->port)
377 return join_room_locally (room, handle); 316 return join_room_locally (room, handle);
378 317
379 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room); 318 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
380 struct GNUNET_HashCode *key = get_room_key (room); 319 const struct GNUNET_HashCode *key = get_room_key (room);
381 320
382 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, 321 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
383 struct GNUNET_MessageHeader, NULL), 322 struct GNUNET_MessageHeader, NULL),
384 GNUNET_MQ_handler_end() }; 323 GNUNET_MQ_handler_end() };
385 324
386 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, 325 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, callback_tunnel_disconnect,
387 callback_tunnel_disconnect, handlers); 326 handlers);
388 327
389 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 328 if (room->port)
329 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
330 GNUNET_h2s(get_room_key(room)));
331 else
332 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
333 GNUNET_h2s(get_room_key(room)));
334
335 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
336
337 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
338 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
390 339
391 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 340 if (member)
341 goto exit_open_room;
392 342
393 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)) && (room->port)) 343 member = add_store_member(member_store, member_id);
344
345 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
394 { 346 {
395 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n"); 347 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
396 348
@@ -400,102 +352,57 @@ open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
400 return GNUNET_NO; 352 return GNUNET_NO;
401 } 353 }
402 354
403 struct GNUNET_MESSENGER_Message *message = create_message_peer (room->service); 355exit_open_room:
404 356 return (room->port ? send_room_message (room, handle, create_message_peer (room->service)) : GNUNET_NO);
405 if (message)
406 {
407 struct GNUNET_HashCode hash;
408
409 send_room_message (room, handle, message, &hash);
410 destroy_message (message);
411 }
412
413 return (room->port ? GNUNET_YES : GNUNET_NO);
414} 357}
415 358
416int 359int
417entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 360enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
418 const struct GNUNET_PeerIdentity *door) 361 const struct GNUNET_PeerIdentity *door)
419{ 362{
420 if (room->peer_message) 363 GNUNET_assert((room) && (handle) && (door));
421 {
422 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, handle, room->peer_message, GNUNET_NO);
423 364
424 if (0 == GNUNET_memcmp(&(msg->body.peer.peer), door)) 365 struct GNUNET_PeerIdentity peer;
425 return join_room_locally (room, handle); 366
426 } 367 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
368 (0 == GNUNET_memcmp(&peer, door)))
369 return join_room_locally (room, handle);
427 370
428 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door); 371 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
429 372
430 if (tunnel) 373 if (!tunnel)
431 { 374 {
432 switch (connect_tunnel (tunnel)) 375 tunnel = create_tunnel (room, door);
376
377 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
378 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
433 { 379 {
434 case GNUNET_YES: 380 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
435 return GNUNET_YES; 381 destroy_tunnel (tunnel);
436 case GNUNET_NO:
437 return join_room_locally (room, handle);
438 default:
439 return GNUNET_NO; 382 return GNUNET_NO;
440 } 383 }
441 } 384 }
442 385
443 tunnel = create_tunnel (room, door); 386 if (GNUNET_SYSERR == connect_tunnel (tunnel))
444
445 if ((GNUNET_YES == connect_tunnel (tunnel)) &&
446 (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
447 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
448 return GNUNET_YES;
449 else
450 { 387 {
451 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n"); 388 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
452 389 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
453 destroy_tunnel (tunnel); 390 destroy_tunnel (tunnel);
454 return GNUNET_NO; 391 return GNUNET_NO;
455 } 392 }
456}
457
458struct GNUNET_MESSENGER_SrvTunnelFinder
459{
460 const struct GNUNET_ShortHashCode *needle;
461 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
462};
463
464static int
465iterate_find_tunnel (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
466{
467 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
468 struct GNUNET_MESSENGER_SrvTunnelFinder *finder = cls;
469
470 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, finder->needle)))
471 {
472 finder->tunnel = tunnel;
473 return GNUNET_NO;
474 }
475
476 return GNUNET_YES;
477}
478
479struct GNUNET_MESSENGER_SrvTunnel*
480find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id)
481{
482 struct GNUNET_MESSENGER_SrvTunnelFinder finder;
483 393
484 finder.needle = contact_id; 394 return join_room_locally (room, handle);
485 finder.tunnel = NULL;
486
487 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_find_tunnel, &finder);
488
489 return finder.tunnel;
490} 395}
491 396
492struct GNUNET_MQ_Envelope* 397struct GNUNET_MQ_Envelope*
493pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 398pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
494 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode) 399 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode)
495{ 400{
401 GNUNET_assert((room) && (handle) && (message) && (hash));
402
496 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 403 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
497 404
498 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, &(room->key)); 405 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, get_room_key(room));
499 406
500 GNUNET_assert(id); 407 GNUNET_assert(id);
501 408
@@ -524,7 +431,8 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
524{ 431{
525 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; 432 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
526 433
527 if ((!is_tunnel_connected (tunnel)) || (!tunnel->contact_id)) 434 if ((!is_tunnel_connected (tunnel)) ||
435 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
528 return GNUNET_YES; 436 return GNUNET_YES;
529 437
530 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls; 438 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
@@ -540,80 +448,88 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
540 GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 448 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
541 449
542 if (env) 450 if (env)
543 {
544 closure->message = copy_message (closure->message);
545 closure->packed = GNUNET_YES; 451 closure->packed = GNUNET_YES;
546 }
547 } 452 }
548 else 453 else
549 { 454 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
550 env = pack_message (closure->message, NULL, NULL,
551 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
552 }
553 455
554 if (env) 456 if (env)
555 send_tunnel_envelope (tunnel, closure->handle, env, closure->message, closure->hash); 457 send_tunnel_envelope (tunnel, env, closure->hash);
556 458
557 return GNUNET_YES; 459 return GNUNET_YES;
558} 460}
559 461
560void 462int
561callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 463update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
562 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 464 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
563 465
564void 466void
467callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
468 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
469
470int
565send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 471send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
566 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 472 struct GNUNET_MESSENGER_Message *message)
567{ 473{
568 struct GNUNET_MESSENGER_ClosureSendRoom closure; 474 GNUNET_assert((room) && (handle));
569
570 closure.room = room;
571 closure.handle = handle;
572 closure.exclude = NULL;
573 closure.message = message;
574 closure.hash = hash;
575 closure.packed = GNUNET_NO;
576 475
577 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); 476 if (!message)
477 return GNUNET_NO;
578 478
579 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 479 if (GNUNET_YES == is_message_session_bound(message))
580 { 480 merge_room_last_messages(room, handle);
581 pack_room_message (room, handle, message, hash,
582 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
583 481
584 callback_room_sent (room, handle, NULL, copy_message (message), hash); 482 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
585 } 483 GNUNET_sh2s(get_handle_member_id(handle, get_room_key(room))));
586}
587 484
588void 485 struct GNUNET_HashCode hash;
589send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
590 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
591 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
592{
593 struct GNUNET_MESSENGER_ClosureSendRoom closure; 486 struct GNUNET_MESSENGER_ClosureSendRoom closure;
594 487
595 closure.room = room; 488 closure.room = room;
596 closure.handle = handle; 489 closure.handle = handle;
597 closure.exclude = tunnel; 490 closure.exclude = NULL;
598 closure.message = message; 491 closure.message = message;
599 closure.hash = hash; 492 closure.hash = &hash;
600 closure.packed = GNUNET_NO; 493 closure.packed = GNUNET_NO;
601 494
602 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); 495 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
603 496
604 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 497 if (GNUNET_NO == closure.packed)
605 { 498 pack_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
606 pack_room_message (room, handle, message, hash, 499
607 GNUNET_MESSENGER_PACK_MODE_UNKNOWN); 500 const int new_message = update_room_message (room, message, &hash);
608 501
609 callback_room_sent (room, handle, NULL, copy_message (message), hash); 502 if (GNUNET_YES != new_message)
503 return GNUNET_SYSERR;
504
505 switch (message->header.kind)
506 {
507 case GNUNET_MESSENGER_KIND_JOIN:
508 send_message_join (room, handle, message, &hash);
509 break;
510 case GNUNET_MESSENGER_KIND_PEER:
511 send_message_peer (room, handle, message, &hash);
512 break;
513 case GNUNET_MESSENGER_KIND_REQUEST:
514 send_message_request (room, handle, message, &hash);
515 break;
516 default:
517 break;
610 } 518 }
519
520 callback_room_handle_message (room, handle, message, &hash);
521 return GNUNET_YES;
611} 522}
612 523
613void 524void
614forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 525forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
615 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 526 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
616{ 527{
528 GNUNET_assert((room) && (tunnel));
529
530 if (!message)
531 return;
532
617 struct GNUNET_MESSENGER_ClosureSendRoom closure; 533 struct GNUNET_MESSENGER_ClosureSendRoom closure;
618 struct GNUNET_HashCode message_hash; 534 struct GNUNET_HashCode message_hash;
619 535
@@ -622,7 +538,7 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
622 closure.room = room; 538 closure.room = room;
623 closure.handle = NULL; 539 closure.handle = NULL;
624 closure.exclude = tunnel; 540 closure.exclude = tunnel;
625 closure.message = copy_message (message); 541 closure.message = message;
626 closure.hash = &message_hash; 542 closure.hash = &message_hash;
627 closure.packed = GNUNET_YES; 543 closure.packed = GNUNET_YES;
628 544
@@ -630,257 +546,241 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
630} 546}
631 547
632void 548void
633merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 549check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel)
634{ 550{
635 if (!handle) 551 if (!room->peer_message)
636 return; 552 return;
637 553
638 if (!room->last_messages.head) 554 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, room->peer_message, GNUNET_NO);
639 return;
640 555
641 while (room->last_messages.head != room->last_messages.tail) 556 if (!message)
642 { 557 {
643 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.tail; 558 GNUNET_free(room->peer_message);
559 room->peer_message = NULL;
560 return;
561 }
644 562
645 struct GNUNET_MESSENGER_Message *message = create_message_merge (&(element->hash)); 563 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
564 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
646 565
647 if (message) 566 if (!member)
648 { 567 goto resend_peer_message;
649 struct GNUNET_HashCode hash;
650 568
651 send_room_message (room, handle, message, &hash); 569 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
652 destroy_message (message);
653 }
654 570
655 if (element->prev) 571 if (GNUNET_YES == is_member_session_closed(session))
656 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, element); 572 goto resend_peer_message;
657 }
658}
659 573
660struct GNUNET_CADET_Handle* 574 if (tunnel)
661get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room) 575 forward_tunnel_message(tunnel, message, room->peer_message);
662{
663 return room->service->cadet;
664}
665 576
666struct GNUNET_HashCode* 577 return;
667get_room_key (struct GNUNET_MESSENGER_SrvRoom *room) 578
668{ 579resend_peer_message:
669 return &(room->key); 580 if (room->host)
581 send_room_message (room, room->host, create_message_peer (room->service));
670} 582}
671 583
672const struct GNUNET_MESSENGER_SrvTunnel* 584static void
673get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer) 585merge_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
586 const struct GNUNET_HashCode *hash)
674{ 587{
675 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer); 588 GNUNET_assert((room) && (handle) && (hash));
589
590 send_room_message (room, handle, create_message_merge (hash));
676} 591}
677 592
678const struct GNUNET_MESSENGER_Message* 593void
679get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 594merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
680 const struct GNUNET_HashCode *hash, int request)
681{ 595{
682 const struct GNUNET_MESSENGER_Message *message = get_store_message (&(room->store), hash); 596 GNUNET_assert(room);
683 597
684 if ((message) || (!handle) || (GNUNET_YES != request) 598 if (!handle)
685 || (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))) 599 return;
686 return message;
687 600
688 struct GNUNET_MESSENGER_Message *request_msg = create_message_request (hash); 601 if (!room->last_messages.head)
602 return;
689 603
690 if (request_msg) 604 while (room->last_messages.head != room->last_messages.tail)
691 { 605 merge_room_message (room, handle, &(room->last_messages.tail->hash));
692 if (GNUNET_CONTAINER_multihashmap_put (room->requested, hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) == GNUNET_OK) 606}
693 {
694 struct GNUNET_HashCode request_hash;
695 607
696 send_room_message (room, handle, request_msg, &request_hash); 608void
697 } 609callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
610{
611 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO);
698 612
699 destroy_message (request_msg); 613 if (message)
700 } 614 add_to_list_messages(&(room->last_messages), &(message->header.previous));
701 615
702 return message; 616 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
617 {
618 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
619 return;
620 }
703} 621}
704 622
705void 623void
706callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls) 624callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
707{ 625{
708 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
709
710 if (!room->host) 626 if (!room->host)
711 return; 627 return;
712 628
713 struct GNUNET_PeerIdentity identity; 629 merge_room_message (room, room->host, hash);
714
715 GNUNET_PEER_resolve (tunnel->peer, &identity);
716
717 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
718 {
719 struct GNUNET_MESSENGER_Message *message = create_message_miss (&identity);
720
721 if (message)
722 {
723 struct GNUNET_HashCode hash;
724
725 send_room_message (room, room->host, message, &hash);
726 destroy_message (message);
727 }
728 }
729} 630}
730 631
731int 632int
732callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, 633delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
733 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 634 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
734{ 635{
735 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind) 636 GNUNET_assert((room) && (session) && (hash));
736 return GNUNET_SYSERR;
737 637
738 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 638 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
739 &(message->header.sender_id));
740 639
741 if (!contact) 640 if (0 == GNUNET_memcmp(&forever, &delay))
742 { 641 {
743 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind) 642 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
744 contact = get_service_contact_by_pubkey (room->service, &(message->body.info.host_key)); 643 return GNUNET_SYSERR;
745 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
746 contact = get_service_contact_by_pubkey (room->service, &(message->body.join.key));
747 } 644 }
748 645
749 if ((!contact) || (GNUNET_SYSERR == verify_message (message, hash, get_contact_key (contact)))) 646 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO);
750 return GNUNET_SYSERR;
751 647
752 if (GNUNET_YES == room->strict_access) 648 if (!message)
649 return GNUNET_YES;
650
651 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
753 { 652 {
754 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, 653 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
755 &(message->header.sender_id)); 654 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
756 655
757 if ((info) && (GNUNET_MESSENGER_MEMBER_BLOCKED == info->access)) 656 return GNUNET_NO;
758 return GNUNET_SYSERR;
759 } 657 }
760 658
761 if (GNUNET_YES == contains_store_message (&(room->store), hash)) 659 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
762 return GNUNET_NO; 660
661 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
662 {
663 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
664 return GNUNET_SYSERR;
665 }
763 666
764 return GNUNET_YES; 667 return GNUNET_YES;
765} 668}
766 669
767static void 670struct GNUNET_CADET_Handle*
768search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) 671get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
769{ 672{
770 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, hash, GNUNET_YES); 673 GNUNET_assert(room);
771 674
772 if (!message) 675 return room->service->cadet;
773 return; 676}
774 677
775 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) 678const struct GNUNET_HashCode*
776 search_room_for_message (room, &(message->body.merge.previous)); 679get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
680{
681 GNUNET_assert(room);
777 682
778 search_room_for_message (room, &(message->header.previous)); 683 return &(room->key);
779} 684}
780 685
781static void 686const struct GNUNET_MESSENGER_SrvTunnel*
782idle_request_room_messages (void *cls) 687get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer)
783{ 688{
784 struct GNUNET_MESSENGER_SrvRoom *room = cls; 689 GNUNET_assert((room) && (peer));
785 690
786 room->idle = NULL; 691 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
692}
787 693
788 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 694const struct GNUNET_MESSENGER_Message*
695get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
696 const struct GNUNET_HashCode *hash, int request)
697{
698 GNUNET_assert((room) && (hash));
789 699
790 while (element) 700 const struct GNUNET_MESSENGER_Message *message = get_store_message (get_room_message_store(room), hash);
791 {
792 search_room_for_message (room, &(element->hash));
793 701
794 element = element->next; 702 if ((message) || (!handle) || (GNUNET_YES != request))
795 } 703 return message;
796 704
797 merge_room_last_messages (room, room->host); 705 struct GNUNET_MESSENGER_OperationStore* operation_store = get_room_operation_store(room);
798 706
799 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_second_ (), 707 if (GNUNET_OK == use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_REQUEST, GNUNET_MESSENGER_REQUEST_DELAY))
800 GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, 708 send_room_message (room, handle, create_message_request (hash));
801 cls); 709
710 return NULL;
802} 711}
803 712
804void 713void
805update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, 714callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls)
806 const struct GNUNET_HashCode *hash)
807{ 715{
808 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 716 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
809 struct GNUNET_MESSENGER_ListMessage *merging = NULL;
810
811 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
812 {
813 merging = room->last_messages.head;
814
815 while (merging)
816 {
817 if (0 == GNUNET_CRYPTO_hash_cmp (&(merging->hash), &(message->body.merge.previous)))
818 break;
819 717
820 merging = merging->next; 718 if (!room->host)
821 } 719 return;
822 720
823 if (merging) 721 struct GNUNET_PeerIdentity identity;
824 element = merging->next; 722 get_tunnel_peer_identity(tunnel, &identity);
825 }
826 723
827 while (element) 724 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
828 { 725 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
829 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), &(message->header.previous))) 726 return;
830 break;
831 727
832 element = element->next; 728 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
833 } 729 send_room_message (room, room->host, create_message_miss (&identity));
730}
834 731
835 if ((merging) && (!element)) 732int
733callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
734 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
735{
736 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
836 { 737 {
837 element = merging; 738 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
838 merging = NULL; 739 return GNUNET_SYSERR;
839 } 740 }
840 741
841 if (element) 742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
842 { 743 GNUNET_MESSENGER_name_of_kind(message->header.kind));
843 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
844 744
845 if (merging) 745 return GNUNET_OK;
846 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, merging);
847 }
848 else
849 add_to_list_messages (&(room->last_messages), hash);
850
851 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))
852 GNUNET_CONTAINER_multihashmap_remove_all (room->requested, hash);
853} 746}
854 747
855void 748static void
856switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, 749idle_request_room_messages (void *cls)
857 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash)
858{ 750{
859 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, old_id); 751 struct GNUNET_MESSENGER_SrvRoom *room = cls;
860
861 if ((contact) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (room->members, old_id, contact)))
862 GNUNET_CONTAINER_multishortmap_put (room->members, new_id, contact,
863 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
864
865 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, old_id);
866 752
867 if ((!info) || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->member_infos, old_id, contact)) 753 room->idle = NULL;
868 || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (room->member_infos, new_id, contact,
869 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
870 return;
871 754
872 if (hash) 755 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
873 add_to_list_messages (&(info->session_messages), hash); 756
757 if ((room->last_messages.head != room->last_messages.tail) &&
758 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, &(room->last_messages.tail->hash))))
759 use_store_operation(
760 operation_store,
761 &(room->last_messages.tail->hash),
762 GNUNET_MESSENGER_OP_MERGE,
763 GNUNET_MESSENGER_MERGE_DELAY
764 );
765
766 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
767 GNUNET_MESSENGER_IDLE_DELAY,
768 GNUNET_SCHEDULER_PRIORITY_IDLE,
769 idle_request_room_messages,
770 cls
771 );
874} 772}
875 773
876void 774void
877rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) 775rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
878{ 776{
777 GNUNET_assert(room);
778
879 struct GNUNET_PeerIdentity peer; 779 struct GNUNET_PeerIdentity peer;
880 size_t src; 780 size_t src;
881 781
882 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) || (!find_list_tunnels (&(room->basement), &peer, 782 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
883 &src))) 783 (!find_list_tunnels (&(room->basement), &peer, &src)))
884 return; 784 return;
885 785
886 size_t count = count_of_tunnels (&(room->basement)); 786 size_t count = count_of_tunnels (&(room->basement));
@@ -918,7 +818,7 @@ rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
918 } 818 }
919} 819}
920 820
921void 821static void
922handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) 822handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
923{ 823{
924 while (room->handling.head) 824 while (room->handling.head)
@@ -927,29 +827,159 @@ handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
927 827
928 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO); 828 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO);
929 829
930 if (msg) 830 if (!msg)
931 handle_service_message (room->service, room, msg, &(element->hash)); 831 goto finish_handling;
832
833 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
834 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, msg);
835
836 if (!member)
837 goto finish_handling;
838
839 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, msg, &(element->hash));
932 840
841 if (session)
842 handle_service_message (room->service, room, session, msg, &(element->hash));
843
844finish_handling:
933 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element); 845 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
934 GNUNET_free(element); 846 GNUNET_free(element);
935 } 847 }
936} 848}
937 849
938#include "gnunet-service-messenger_message_recv.h" 850static void
851remove_room_last_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
852{
853 remove_from_list_messages(&(room->last_messages), hash);
854
855 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
856
857 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, hash))
858 cancel_store_operation(operation_store, hash);
859}
860
861int
862update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
863 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
864{
865 GNUNET_assert((room) && (message) && (hash));
866
867 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
868
869 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
870 GNUNET_YES : GNUNET_NO
871 );
872
873 if (GNUNET_YES == requested)
874 cancel_store_operation(operation_store, hash);
875
876 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, NULL, hash, GNUNET_NO);
877
878 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
879
880 if ((old_message) || (GNUNET_OK != put_store_message (get_room_message_store(room), hash, message)))
881 {
882 if (old_message != message)
883 destroy_message(message);
884
885 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
886 return GNUNET_NO;
887 }
888
889 if ((GNUNET_YES == requested) ||
890 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
891 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
892 return GNUNET_YES;
893
894 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
895 remove_room_last_message(room, &(message->body.merge.previous));
896 remove_room_last_message(room, &(message->header.previous));
897
898 add_to_list_messages (&(room->last_messages), hash);
899
900 return GNUNET_YES;
901}
902
903struct GNUNET_MESSENGER_MemberSessionCompletion
904{
905 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
906 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
907
908 struct GNUNET_MESSENGER_MemberSession *session;
909};
910
911struct GNUNET_MESSENGER_MemberUpdate
912{
913 const struct GNUNET_MESSENGER_Message *message;
914 const struct GNUNET_HashCode *hash;
915
916 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
917 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
918};
919
920static int
921iterate_update_member_sessions (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
922 struct GNUNET_MESSENGER_MemberSession *session)
923{
924 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
925
926 update_member_session_history(session, update->message, update->hash);
927
928 if (GNUNET_YES == is_member_session_completed(session))
929 {
930 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
931 struct GNUNET_MESSENGER_MemberSessionCompletion
932 );
933
934 element->session = session;
935
936 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
937 }
938
939 return GNUNET_YES;
940}
939 941
940void 942void
941callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, 943callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
942 const struct GNUNET_HashCode *hash) 944 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
943{ 945{
944 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 946 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
947 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
948
949 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
950
951 if (!member)
952 {
953 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
954 return;
955 }
956
957 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
945 958
946 if (GNUNET_OK != put_store_message (&(room->store), hash, message)) 959 if (!session)
960 {
961 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
947 return; 962 return;
963 }
964
965 struct GNUNET_MESSENGER_MemberUpdate update;
966 update.message = message;
967 update.hash = hash;
968
969 update.head = NULL;
970 update.tail = NULL;
971
972 iterate_store_members(member_store, iterate_update_member_sessions, &update);
973
974 while (update.head)
975 {
976 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
948 977
949 update_room_last_messages (room, message, hash); 978 remove_member_session (element->session->member, element->session);
950 979
951 if (GNUNET_MESSENGER_KIND_INFO != message->header.kind) 980 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
952 forward_room_message (room, tunnel, message, hash); 981 GNUNET_free (element);
982 }
953 983
954 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 984 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
955 985
@@ -957,32 +987,29 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
957 987
958 switch (message->header.kind) 988 switch (message->header.kind)
959 { 989 {
960 case GNUNET_MESSENGER_KIND_INFO:
961 recv_message_info (room, tunnel, message, hash);
962 break;
963 case GNUNET_MESSENGER_KIND_JOIN: 990 case GNUNET_MESSENGER_KIND_JOIN:
964 recv_message_join (room, tunnel, message, hash); 991 handle_message_join (room, session, message, hash);
965 break; 992 break;
966 case GNUNET_MESSENGER_KIND_LEAVE: 993 case GNUNET_MESSENGER_KIND_LEAVE:
967 recv_message_leave (room, tunnel, message, hash); 994 handle_message_leave (room, session, message, hash);
968 break; 995 break;
969 case GNUNET_MESSENGER_KIND_NAME: 996 case GNUNET_MESSENGER_KIND_NAME:
970 recv_message_name (room, tunnel, message, hash); 997 handle_message_name (room, session, message, hash);
971 break; 998 break;
972 case GNUNET_MESSENGER_KIND_KEY: 999 case GNUNET_MESSENGER_KIND_KEY:
973 recv_message_key (room, tunnel, message, hash); 1000 handle_message_key (room, session, message, hash);
974 break; 1001 break;
975 case GNUNET_MESSENGER_KIND_PEER: 1002 case GNUNET_MESSENGER_KIND_PEER:
976 recv_message_peer (room, tunnel, message, hash); 1003 handle_message_peer (room, session, message, hash);
977 break; 1004 break;
978 case GNUNET_MESSENGER_KIND_ID: 1005 case GNUNET_MESSENGER_KIND_ID:
979 recv_message_id (room, tunnel, message, hash); 1006 handle_message_id (room, session, message, hash);
980 break; 1007 break;
981 case GNUNET_MESSENGER_KIND_MISS: 1008 case GNUNET_MESSENGER_KIND_MISS:
982 recv_message_miss (room, tunnel, message, hash); 1009 handle_message_miss (room, session, message, hash);
983 break; 1010 break;
984 case GNUNET_MESSENGER_KIND_REQUEST: 1011 case GNUNET_MESSENGER_KIND_DELETE:
985 recv_message_request (room, tunnel, message, hash); 1012 handle_message_delete (room, session, message, hash);
986 break; 1013 break;
987 default: 1014 default:
988 break; 1015 break;
@@ -992,60 +1019,71 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
992 handle_room_messages (room); 1019 handle_room_messages (room);
993} 1020}
994 1021
995#include "gnunet-service-messenger_message_send.h" 1022static void
1023get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
1024{
1025 GNUNET_assert((room) && (dir));
1026
1027 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_room_key(room)), DIR_SEPARATOR);
1028}
996 1029
997void 1030void
998callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 1031load_room (struct GNUNET_MESSENGER_SrvRoom *room)
999 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
1000{ 1032{
1001 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, handle, hash, GNUNET_NO); 1033 GNUNET_assert(room);
1002 1034
1003 if ((old_message) || (GNUNET_OK != put_store_message (&(room->store), hash, message))) 1035 char *room_dir;
1036 get_room_data_subdir (room, &room_dir);
1037
1038 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1004 { 1039 {
1005 if (old_message != message) 1040 load_member_store (get_room_member_store(room), room_dir);
1006 GNUNET_free(message); 1041 load_message_store (get_room_message_store(room), room_dir);
1042 load_operation_store(get_room_operation_store(room), room_dir);
1043
1044 char *basement_file;
1045 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1046
1047 load_list_tunnels(&(room->basement), basement_file);
1048 GNUNET_free(basement_file);
1049
1050 char *last_messages_file;
1051 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1052
1053 load_list_messages(&(room->last_messages), last_messages_file);
1054 GNUNET_free(last_messages_file);
1007 } 1055 }
1008 else
1009 {
1010 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; // may be NULL
1011 1056
1012 update_room_last_messages (room, message, hash); 1057 GNUNET_free(room_dir);
1058}
1059
1060void
1061save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1062{
1063 GNUNET_assert(room);
1064
1065 char *room_dir;
1066 get_room_data_subdir (room, &room_dir);
1013 1067
1014 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 1068 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1069 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1070 {
1071 save_member_store(get_room_member_store(room), room_dir);
1072 save_message_store (get_room_message_store(room), room_dir);
1073 save_operation_store(get_room_operation_store(room), room_dir);
1015 1074
1016 add_to_list_messages (&(room->handling), hash); 1075 char *basement_file;
1076 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1017 1077
1018 switch (message->header.kind) 1078 save_list_tunnels(&(room->basement), basement_file);
1019 { 1079 GNUNET_free(basement_file);
1020 case GNUNET_MESSENGER_KIND_INFO: 1080
1021 send_message_info (room, handle, tunnel, message, hash); 1081 char *last_messages_file;
1022 break; 1082 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1023 case GNUNET_MESSENGER_KIND_JOIN:
1024 send_message_join (room, handle, tunnel, message, hash);
1025 break;
1026 case GNUNET_MESSENGER_KIND_LEAVE:
1027 send_message_leave (room, handle, tunnel, message, hash);
1028 break;
1029 case GNUNET_MESSENGER_KIND_NAME:
1030 send_message_name (room, handle, tunnel, message, hash);
1031 break;
1032 case GNUNET_MESSENGER_KIND_KEY:
1033 send_message_key (room, handle, tunnel, message, hash);
1034 break;
1035 case GNUNET_MESSENGER_KIND_PEER:
1036 send_message_peer (room, handle, tunnel, message, hash);
1037 break;
1038 case GNUNET_MESSENGER_KIND_ID:
1039 send_message_id (room, handle, tunnel, message, hash);
1040 break;
1041 case GNUNET_MESSENGER_KIND_MISS:
1042 send_message_miss (room, handle, tunnel, message, hash);
1043 break;
1044 default:
1045 break;
1046 }
1047 1083
1048 if (GNUNET_YES == start_handle) 1084 save_list_messages(&(room->last_messages), last_messages_file);
1049 handle_room_messages (room); 1085 GNUNET_free(last_messages_file);
1050 } 1086 }
1087
1088 GNUNET_free(room_dir);
1051} 1089}
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
index 36c9e8cf5..a40961177 100644
--- a/src/messenger/gnunet-service-messenger_room.h
+++ b/src/messenger/gnunet-service-messenger_room.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -33,33 +33,29 @@
33#include "gnunet_identity_service.h" 33#include "gnunet_identity_service.h"
34#include "gnunet_mq_lib.h" 34#include "gnunet_mq_lib.h"
35 35
36#include "gnunet-service-messenger_contact.h"
37
38#include "gnunet_messenger_service.h" 36#include "gnunet_messenger_service.h"
39#include "gnunet-service-messenger_basement.h" 37#include "gnunet-service-messenger_basement.h"
40#include "gnunet-service-messenger_handle.h" 38#include "gnunet-service-messenger_handle.h"
41#include "gnunet-service-messenger_tunnel.h"
42
43#include "gnunet-service-messenger_list_messages.h" 39#include "gnunet-service-messenger_list_messages.h"
40
44#include "messenger_api_list_tunnels.h" 41#include "messenger_api_list_tunnels.h"
45 42
43#include "gnunet-service-messenger_member_store.h"
46#include "gnunet-service-messenger_message_store.h" 44#include "gnunet-service-messenger_message_store.h"
45#include "gnunet-service-messenger_operation_store.h"
47#include "messenger_api_ego.h" 46#include "messenger_api_ego.h"
48 47
49enum GNUNET_MESSENGER_MemberAccess 48#define GNUNET_MESSENGER_IDLE_DELAY GNUNET_TIME_relative_multiply \
50{ 49 (GNUNET_TIME_relative_get_second_ (), 5)
51 GNUNET_MESSENGER_MEMBER_ALLOWED = 1,
52 GNUNET_MESSENGER_MEMBER_BLOCKED = 1,
53 50
54 GNUNET_MESSENGER_MEMBER_UNKNOWN = 0 51#define GNUNET_MESSENGER_REQUEST_DELAY GNUNET_TIME_relative_multiply \
55}; 52 (GNUNET_TIME_relative_get_minute_ (), 5)
56 53
57struct GNUNET_MESSENGER_MemberInfo 54#define GNUNET_MESSENGER_MERGE_DELAY GNUNET_TIME_relative_multiply \
58{ 55 (GNUNET_TIME_relative_get_second_ (), 30)
59 enum GNUNET_MESSENGER_MemberAccess access;
60 56
61 struct GNUNET_MESSENGER_ListMessages session_messages; 57struct GNUNET_MESSENGER_SrvTunnel;
62}; 58struct GNUNET_MESSENGER_MemberSession;
63 59
64struct GNUNET_MESSENGER_SrvRoom 60struct GNUNET_MESSENGER_SrvRoom
65{ 61{
@@ -70,11 +66,10 @@ struct GNUNET_MESSENGER_SrvRoom
70 struct GNUNET_HashCode key; 66 struct GNUNET_HashCode key;
71 67
72 struct GNUNET_CONTAINER_MultiPeerMap *tunnels; 68 struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
73 struct GNUNET_CONTAINER_MultiShortmap *members;
74 struct GNUNET_CONTAINER_MultiShortmap *member_infos;
75 69
76 struct GNUNET_MESSENGER_MessageStore store; 70 struct GNUNET_MESSENGER_MemberStore member_store;
77 struct GNUNET_CONTAINER_MultiHashMap *requested; 71 struct GNUNET_MESSENGER_MessageStore message_store;
72 struct GNUNET_MESSENGER_OperationStore operation_store;
78 73
79 struct GNUNET_MESSENGER_ListTunnels basement; 74 struct GNUNET_MESSENGER_ListTunnels basement;
80 struct GNUNET_MESSENGER_ListMessages last_messages; 75 struct GNUNET_MESSENGER_ListMessages last_messages;
@@ -83,15 +78,13 @@ struct GNUNET_MESSENGER_SrvRoom
83 78
84 struct GNUNET_MESSENGER_ListMessages handling; 79 struct GNUNET_MESSENGER_ListMessages handling;
85 struct GNUNET_SCHEDULER_Task *idle; 80 struct GNUNET_SCHEDULER_Task *idle;
86
87 int strict_access;
88}; 81};
89 82
90/** 83/**
91 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>. 84 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>.
92 * 85 *
93 * @param handle Handle 86 * @param[in/out] handle Handle
94 * @param key Key of room 87 * @param[in] key Key of room
95 * @return New room 88 * @return New room
96 */ 89 */
97struct GNUNET_MESSENGER_SrvRoom* 90struct GNUNET_MESSENGER_SrvRoom*
@@ -100,58 +93,42 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
100/** 93/**
101 * Destroys a room and frees its memory fully. 94 * Destroys a room and frees its memory fully.
102 * 95 *
103 * @param room Room 96 * @param[in/out] room Room
104 */ 97 */
105void 98void
106destroy_room (struct GNUNET_MESSENGER_SrvRoom *room); 99destroy_room (struct GNUNET_MESSENGER_SrvRoom *room);
107 100
108/** 101/**
109 * Returns the contact of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i> 102 * Returns the used member store of a given <i>room</i>.
110 * does not contain a member with the given <i>id</i>, NULL gets returned.
111 *
112 * @param room Room
113 * @param id Member id
114 * @return Contact or NULL
115 */
116struct GNUNET_MESSENGER_SrvContact*
117get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id);
118
119/**
120 * Adds a contact from the service to a <i>room</i> under a specific <i>id</i> with a given public key.
121 * 103 *
122 * @param room Room 104 * @param[in/out] room Room
123 * @param id Member id 105 * @return Member store
124 * @param pubkey Public key of EGO
125 */ 106 */
126void 107struct GNUNET_MESSENGER_MemberStore*
127add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id, 108get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room);
128 const struct GNUNET_IDENTITY_PublicKey *pubkey);
129 109
130/** 110/**
131 * Returns the member information of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i> 111 * Returns the used message store of a given <i>room</i>.
132 * does not contain a member with the given <i>id</i>, NULL gets returned.
133 * 112 *
134 * @param room Room 113 * @param[in/out] room Room
135 * @param id Member id 114 * @return Message store
136 * @return Member information or NULL
137 */ 115 */
138struct GNUNET_MESSENGER_MemberInfo* 116struct GNUNET_MESSENGER_MessageStore*
139get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id); 117get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room);
140 118
141/** 119/**
142 * Tries to generate and allocate a new unique member id checking all current members for possible 120 * Returns the used operation store of a given <i>room</i>.
143 * duplicates. If the function fails, NULL gets returned.
144 * 121 *
145 * @param room Room 122 * @param[in/out] room Room
146 * @return New member id or NULL 123 * @return Operation store
147 */ 124 */
148struct GNUNET_ShortHashCode* 125struct GNUNET_MESSENGER_OperationStore*
149generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room); 126get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
150 127
151/** 128/**
152 * Returns the member id of the member representing the handle currently hosting this <i>room</i>. 129 * Returns the member id of the member representing the handle currently hosting this <i>room</i>.
153 * 130 *
154 * @param room Room 131 * @param[in] room Room
155 * @return Host member id or NULL 132 * @return Host member id or NULL
156 */ 133 */
157const struct GNUNET_ShortHashCode* 134const struct GNUNET_ShortHashCode*
@@ -160,8 +137,8 @@ get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room);
160/** 137/**
161 * Changes the member id of the member representing the handle currently hosting this <i>room</i>. 138 * Changes the member id of the member representing the handle currently hosting this <i>room</i>.
162 * 139 *
163 * @param room Room 140 * @param[in/out] room Room
164 * @param unique_id Unique member id 141 * @param[in] unique_id Unique member id
165 */ 142 */
166void 143void
167change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id); 144change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id);
@@ -172,11 +149,11 @@ change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_
172 * 149 *
173 * Calling this method should result in joining a room and sending a peer message as well for this peer. 150 * Calling this method should result in joining a room and sending a peer message as well for this peer.
174 * 151 *
175 * If the function returns GNUNET_YES the port for this room is guranteed to be open for incoming connections. 152 * If the function returns #GNUNET_YES the port for this room is guranteed to be open for incoming connections.
176 * 153 *
177 * @param room Room 154 * @param[in/out] room Room
178 * @param handle Handle 155 * @param[in/out] handle Handle
179 * @return GNUNET_YES on success, GNUNET_NO on failure. 156 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
180 */ 157 */
181int 158int
182open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); 159open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
@@ -186,45 +163,34 @@ open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
186 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for 163 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for
187 * an info message from the selected host. 164 * an info message from the selected host.
188 * 165 *
189 * @param room Room 166 * @param[in/out] room Room
190 * @param handle Handle 167 * @param[in/out] handle Handle
191 * @param door Peer identity 168 * @param[in] door Peer identity
192 * @return GNUNET_YES on success, GNUNET_NO on failure. 169 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
193 */ 170 */
194int 171int
195entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 172enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
196 const struct GNUNET_PeerIdentity *door); 173 const struct GNUNET_PeerIdentity *door);
197 174
198/** 175/**
199 * Returns a tunnel granting a direct connection to a specific member in a <i>room</i>. The member gets identified
200 * by an <i>id</i>. If no tunnel has been linked to the selected id, NULL gets returned.
201 *
202 * @param room Room
203 * @param contact_id Member id
204 * @return Tunnel to the member or NULL
205 */
206struct GNUNET_MESSENGER_SrvTunnel*
207find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id);
208
209/**
210 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the 176 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the
211 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message 177 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message
212 * will be signed by the handles EGO. 178 * will be signed by the handles EGO.
213 * 179 *
214 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overriden by the signed messages hash. 180 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overriden by the signed messages hash.
215 * 181 *
216 * If <i>mode</i> is set to GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send 182 * If <i>mode</i> is set to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send
217 * through a message queue, otherwise NULL. 183 * through a message queue, otherwise NULL.
218 * 184 *
219 * @param room Room 185 * @param[in] room Room
220 * @param handle Handle 186 * @param[in] handle Handle
221 * @param message Message 187 * @param[in/out] message Message
222 * @param[out] hash Hash of message 188 * @param[out] hash Hash of message
223 * @param mode Packing mode 189 * @param[in] mode Packing mode
224 * @return New envelope or NULL 190 * @return New envelope or NULL
225 */ 191 */
226struct GNUNET_MQ_Envelope* 192struct GNUNET_MQ_Envelope*
227pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 193pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
228 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode); 194 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode);
229 195
230/** 196/**
@@ -234,59 +200,69 @@ pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
234 * The function handles packing the message automatically and will call linked message-events locally even if 200 * The function handles packing the message automatically and will call linked message-events locally even if
235 * the message won't be sent to another peer. 201 * the message won't be sent to another peer.
236 * 202 *
237 * @param room Room 203 * The function returns #GNUNET_YES on success, #GNUNET_NO if message is null and
238 * @param handle Handle 204 * #GNUNET_SYSERR if the message was known already.
239 * @param message Message 205 *
240 * @param[out] hash Hash of message 206 * @param[in/out] room Room
207 * @param[in/out] handle Handle
208 * @param[in/out] message Message
209 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
241 */ 210 */
242void 211int
243send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 212send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
244 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash); 213 struct GNUNET_MESSENGER_Message *message);
245 214
246/** 215/**
247 * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i> excluding one specific <i>tunnel</i>. 216 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>.
248 * The <i>hash</i> parameter will be updated with the hash-value resulting from the sent message.
249 *
250 * The function handles packing the message automatically and will call linked message-events locally even if
251 * the message won't be sent to another peer.
252 * 217 *
253 * @param room Room 218 * @param[in/out] room Room
254 * @param handle Handle 219 * @param[in/out] tunnel Tunnel
255 * @param message Message 220 * @param[in/out] message Message
256 * @param[out] hash Hash of message 221 * @param[in] hash Hash of message
257 * @param tunnel Tunnel
258 */ 222 */
259void 223void
260send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 224forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
261 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 225 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
262 struct GNUNET_MESSENGER_SrvTunnel *tunnel);
263 226
264/** 227/**
265 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>. 228 * Checks the current state of opening a given <i>room</i> from this peer and re-publishes it
229 * if necessary to a selected <i>tunnel</i> or to all connected tunnels if necessary or if the
230 * selected tunnel is NULL.
266 * 231 *
267 * @param room Room 232 * @param[in/out] room Room
268 * @param tunnel Tunnel 233 * @param[in/out] tunnel Tunnel
269 * @param message Message
270 * @param hash Hash of message
271 */ 234 */
272void 235void
273forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 236check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel);
274 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
275 237
276/** 238/**
277 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message 239 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message
278 * by merging them down. All merge messages will be sent from a given <i>handle</i>. 240 * by merging them down. All merge messages will be sent from a given <i>handle</i>.
279 * 241 *
280 * @param room Room 242 * @param[in/out] room Room
281 * @param handle Handle 243 * @param[in/out] handle Handle
282 */ 244 */
283void 245void
284merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); 246merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
285 247
286/** 248/**
249 * Deletes a message from the <i>room</i> with a given <i>hash</i> in a specific <i>delay</i> if
250 * the provided member by its session is permitted to do so.
251 *
252 * @param[in/out] room Room
253 * @param[in/out] session Member session
254 * @param[in] hash Hash of message
255 * @param[in] delay Delay of deletion
256 * @return #GNUNET_YES on success, #GNUNET_NO if permission gets denied, #GNUNET_SYSERR on operation failure
257 */
258int
259delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
260 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
261
262/**
287 * Returns the CADET handle from a rooms service. 263 * Returns the CADET handle from a rooms service.
288 * 264 *
289 * @param room Room 265 * @param[in/out] room Room
290 * @return CADET handle 266 * @return CADET handle
291 */ 267 */
292struct GNUNET_CADET_Handle* 268struct GNUNET_CADET_Handle*
@@ -295,26 +271,26 @@ get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room);
295/** 271/**
296 * Returns the shared secret you need to access a <i>room</i>. 272 * Returns the shared secret you need to access a <i>room</i>.
297 * 273 *
298 * @param room Room 274 * @param[in] room Room
299 * @return Shared secret 275 * @return Shared secret
300 */ 276 */
301struct GNUNET_HashCode* 277const struct GNUNET_HashCode*
302get_room_key (struct GNUNET_MESSENGER_SrvRoom *room); 278get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room);
303 279
304/** 280/**
305 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists, 281 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists,
306 * otherwise NULL. 282 * otherwise NULL.
307 * 283 *
308 * @param room Room 284 * @param[in] room Room
309 * @param peer Peer identity 285 * @param[in] peer Peer identity
310 * @return Tunnel or NULL 286 * @return Tunnel or NULL
311 */ 287 */
312const struct GNUNET_MESSENGER_SrvTunnel* 288const struct GNUNET_MESSENGER_SrvTunnel*
313get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); 289get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer);
314 290
315/** 291/**
316 * Returns a message from a <i>room</i> identified by a given <i>hash</i>. If no matching message is 292 * Returns a message from a <i>room</i> identified by a given <i>hash</i>. If no matching message is
317 * found and <i>request</i> is set to GNUNET_YES, the <i>handle</i> will request the missing message 293 * found and <i>request</i> is set to #GNUNET_YES, the <i>handle</i> will request the missing message
318 * automatically. 294 * automatically.
319 * 295 *
320 * The function uses the optimized check for a message via its hash from the message store. 296 * The function uses the optimized check for a message via its hash from the message store.
@@ -323,10 +299,10 @@ get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_Peer
323 * If a message is missing independent of the following request, NULL gets returned instead of the 299 * If a message is missing independent of the following request, NULL gets returned instead of the
324 * matching message. 300 * matching message.
325 * 301 *
326 * @param room Room 302 * @param[in/out] room Room
327 * @param handle Handle 303 * @param[in/out] handle Handle
328 * @param hash Hash of message 304 * @param[in] hash Hash of message
329 * @param request Flag to request a message 305 * @param[in] request Flag to request a message
330 * @return Message or NULL 306 * @return Message or NULL
331 */ 307 */
332const struct GNUNET_MESSENGER_Message* 308const struct GNUNET_MESSENGER_Message*
@@ -334,45 +310,30 @@ get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER
334 const struct GNUNET_HashCode *hash, int request); 310 const struct GNUNET_HashCode *hash, int request);
335 311
336/** 312/**
337 * Updates the last messages of a <i>room</i> by replacing them if the previous hash of a given <i>message</i> 313 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
338 * matches with one of the latest messages. 314 * depending on the amount of peers and this peers index in the list of them.
339 *
340 * @param room Room
341 * @param message Message
342 * @param hash Hash of message
343 */
344void
345update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message,
346 const struct GNUNET_HashCode *hash);
347
348/**
349 * Changes an id of a current member from an old id to a new one and adds optionally the <i>hash</i> of an
350 * id message to the members information.
351 * 315 *
352 * @param room Room 316 * @param[in/out] room Room
353 * @param old_id Old member id
354 * @param new_id New member id
355 * @param hash Hash of id message
356 */ 317 */
357void 318void
358switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, 319rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room);
359 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash);
360 320
361/** 321/**
362 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made 322 * Loads the local configuration for a given <i>room</i> of a service which contains the last messages hash
363 * depending on the amount of peers and this peers index in the list of them. 323 * and the ruleset for general access of new members.
364 * 324 *
365 * @param room Room 325 * @param[out] room Room
366 */ 326 */
367void 327void
368rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room); 328load_room (struct GNUNET_MESSENGER_SrvRoom *room);
369 329
370/** 330/**
371 * Handles all queued up messages of a room to handle in correct order. 331 * Saves the configuration for a given <i>room</i> of a service which contains the last messages hash
332 * and the ruleset for general access of new members locally.
372 * 333 *
373 * @param room Room 334 * @param[in] room Room
374 */ 335 */
375void 336void
376handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room); 337save_room (struct GNUNET_MESSENGER_SrvRoom *room);
377 338
378#endif //GNUNET_SERVICE_MESSENGER_ROOM_H 339#endif //GNUNET_SERVICE_MESSENGER_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_service.c b/src/messenger/gnunet-service-messenger_service.c
index 963314fd8..8c63e9bf4 100644
--- a/src/messenger/gnunet-service-messenger_service.c
+++ b/src/messenger/gnunet-service-messenger_service.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -24,11 +24,8 @@
24 */ 24 */
25 25
26#include "gnunet-service-messenger_service.h" 26#include "gnunet-service-messenger_service.h"
27
28#include "gnunet-service-messenger_message_kind.h" 27#include "gnunet-service-messenger_message_kind.h"
29
30#include "gnunet-service-messenger.h" 28#include "gnunet-service-messenger.h"
31#include "gnunet-service-messenger_util.h"
32 29
33static void 30static void
34callback_shutdown_service (void *cls) 31callback_shutdown_service (void *cls)
@@ -43,23 +40,11 @@ callback_shutdown_service (void *cls)
43 } 40 }
44} 41}
45 42
46static void
47callback_update_ego (void *cls,
48 struct GNUNET_IDENTITY_Ego *ego,
49 void **ctx,
50 const char *identifier)
51{
52 if ((!ego) || (!identifier))
53 return;
54
55 struct GNUNET_MESSENGER_Service *service = cls;
56
57 update_service_ego(service, identifier, GNUNET_IDENTITY_ego_get_private_key(ego));
58}
59
60struct GNUNET_MESSENGER_Service* 43struct GNUNET_MESSENGER_Service*
61create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle) 44create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle)
62{ 45{
46 GNUNET_assert((config) && (service_handle));
47
63 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service); 48 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service);
64 49
65 service->config = config; 50 service->config = config;
@@ -90,24 +75,16 @@ create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_
90 } 75 }
91 76
92 service->cadet = GNUNET_CADET_connect (service->config); 77 service->cadet = GNUNET_CADET_connect (service->config);
93 service->identity = GNUNET_IDENTITY_connect (service->config, &callback_update_ego, service);
94 78
95 service->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 79 init_ego_store(get_service_ego_store(service), service->config);
96 80
97 init_list_handles (&(service->handles)); 81 init_list_handles (&(service->handles));
98 82
99 service->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
100 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 83 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
101 84
102 return service; 85 init_contact_store(get_service_contact_store(service));
103}
104 86
105static int 87 return service;
106iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
107{
108 struct GNUNET_MESSENGER_Ego *ego = value;
109 GNUNET_free(ego);
110 return GNUNET_YES;
111} 88}
112 89
113static int 90static int
@@ -118,17 +95,11 @@ iterate_destroy_rooms (void *cls, const struct GNUNET_HashCode *key, void *value
118 return GNUNET_YES; 95 return GNUNET_YES;
119} 96}
120 97
121static int
122iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
123{
124 struct GNUNET_MESSENGER_SrvContact *contact = value;
125 destroy_contact (contact);
126 return GNUNET_YES;
127}
128
129void 98void
130destroy_service (struct GNUNET_MESSENGER_Service *service) 99destroy_service (struct GNUNET_MESSENGER_Service *service)
131{ 100{
101 GNUNET_assert(service);
102
132 if (service->shutdown) 103 if (service->shutdown)
133 { 104 {
134 GNUNET_SCHEDULER_cancel (service->shutdown); 105 GNUNET_SCHEDULER_cancel (service->shutdown);
@@ -136,16 +107,13 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
136 service->shutdown = NULL; 107 service->shutdown = NULL;
137 } 108 }
138 109
139 GNUNET_CONTAINER_multihashmap_iterate (service->egos, iterate_destroy_egos, NULL); 110 clear_ego_store(get_service_ego_store(service));
140
141 clear_list_handles (&(service->handles)); 111 clear_list_handles (&(service->handles));
142 112
143 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL); 113 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL);
144 GNUNET_CONTAINER_multihashmap_iterate (service->contacts, iterate_destroy_contacts, NULL);
145
146 GNUNET_CONTAINER_multihashmap_destroy (service->egos);
147 GNUNET_CONTAINER_multihashmap_destroy (service->rooms); 114 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
148 GNUNET_CONTAINER_multihashmap_destroy (service->contacts); 115
116 clear_contact_store(get_service_contact_store(service));
149 117
150 if (service->cadet) 118 if (service->cadet)
151 { 119 {
@@ -154,13 +122,6 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
154 service->cadet = NULL; 122 service->cadet = NULL;
155 } 123 }
156 124
157 if (service->identity)
158 {
159 GNUNET_IDENTITY_disconnect (service->identity);
160
161 service->identity = NULL;
162 }
163
164 if (service->dir) 125 if (service->dir)
165 { 126 {
166 GNUNET_free(service->dir); 127 GNUNET_free(service->dir);
@@ -173,44 +134,27 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
173 GNUNET_free(service); 134 GNUNET_free(service);
174} 135}
175 136
176struct GNUNET_MESSENGER_Ego* 137struct GNUNET_MESSENGER_EgoStore*
177lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier) 138get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
178{ 139{
179 GNUNET_assert(identifier); 140 GNUNET_assert(service);
180 141
181 struct GNUNET_HashCode hash; 142 return &(service->ego_store);
182
183 GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash);
184 return GNUNET_CONTAINER_multihashmap_get(service->egos, &hash);
185} 143}
186 144
187void 145struct GNUNET_MESSENGER_ContactStore*
188update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, 146get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
189 const struct GNUNET_IDENTITY_PrivateKey* key)
190{ 147{
191 GNUNET_assert((identifier) && (key)); 148 GNUNET_assert(service);
192
193 struct GNUNET_HashCode hash;
194
195 GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash);
196 149
197 struct GNUNET_MESSENGER_Ego* ego = GNUNET_CONTAINER_multihashmap_get(service->egos, &hash); 150 return &(service->contact_store);
198
199 if (!ego)
200 {
201 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
202 GNUNET_CONTAINER_multihashmap_put(service->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
203 }
204
205 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
206
207 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public(key, &(ego->pub)))
208 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
209} 151}
210 152
211struct GNUNET_MESSENGER_SrvHandle* 153struct GNUNET_MESSENGER_SrvHandle*
212add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) 154add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
213{ 155{
156 GNUNET_assert((service) && (mq));
157
214 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq); 158 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq);
215 159
216 if (handle) 160 if (handle)
@@ -224,6 +168,8 @@ add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_H
224void 168void
225remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle) 169remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle)
226{ 170{
171 GNUNET_assert((service) && (handle));
172
227 if (!handle) 173 if (!handle)
228 return; 174 return;
229 175
@@ -234,68 +180,16 @@ remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_M
234int 180int
235get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer) 181get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer)
236{ 182{
237 return GNUNET_CRYPTO_get_peer_identity (service->config, peer); 183 GNUNET_assert((service) && (peer));
238}
239 184
240struct GNUNET_MESSENGER_SrvContact* 185 return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
241get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey)
242{
243 struct GNUNET_HashCode hash;
244
245 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
246
247 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multihashmap_get (service->contacts, &hash);
248
249 if (contact)
250 return contact;
251
252 contact = create_contact (pubkey);
253
254 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->contacts, &hash, contact,
255 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
256 return contact;
257
258 destroy_contact (contact);
259 return NULL;
260}
261
262void
263swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact,
264 const struct GNUNET_IDENTITY_PublicKey *pubkey)
265{
266 const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact);
267
268 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (service->contacts, hash, contact))
269 {
270 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
271
272 hash = get_contact_id_from_key (contact);
273
274 GNUNET_CONTAINER_multihashmap_put (service->contacts, hash, contact,
275 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
276 }
277}
278
279struct GNUNET_ShortHashCode*
280generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key)
281{
282 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
283
284 if (room)
285 {
286 return generate_room_member_id (room);
287 }
288 else
289 {
290 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
291 generate_free_member_id (random_id, NULL);
292 return random_id;
293 }
294} 186}
295 187
296struct GNUNET_MESSENGER_SrvRoom* 188struct GNUNET_MESSENGER_SrvRoom*
297get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key) 189get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key)
298{ 190{
191 GNUNET_assert((service) && (key));
192
299 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key); 193 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
300} 194}
301 195
@@ -303,6 +197,8 @@ int
303open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 197open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
304 const struct GNUNET_HashCode *key) 198 const struct GNUNET_HashCode *key)
305{ 199{
200 GNUNET_assert((service) && (handle) && (key));
201
306 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 202 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
307 203
308 if (room) 204 if (room)
@@ -310,8 +206,10 @@ open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSE
310 206
311 room = create_room (handle, key); 207 room = create_room (handle, key);
312 208
313 if ((GNUNET_YES == open_room (room, handle)) && (GNUNET_OK 209 if ((GNUNET_YES == open_room (room, handle)) &&
314 == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 210 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
211 key, room,
212 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
315 return GNUNET_YES; 213 return GNUNET_YES;
316 214
317 destroy_room (room); 215 destroy_room (room);
@@ -322,11 +220,13 @@ int
322entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 220entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
323 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) 221 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
324{ 222{
223 GNUNET_assert((service) && (handle) && (door) && (key));
224
325 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 225 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
326 226
327 if (room) 227 if (room)
328 { 228 {
329 if (GNUNET_YES == entry_room_at (room, handle, door)) 229 if (GNUNET_YES == enter_room_at (room, handle, door))
330 return GNUNET_YES; 230 return GNUNET_YES;
331 else 231 else
332 return GNUNET_NO; 232 return GNUNET_NO;
@@ -334,8 +234,10 @@ entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
334 234
335 room = create_room (handle, key); 235 room = create_room (handle, key);
336 236
337 if ((GNUNET_YES == entry_room_at (room, handle, door)) && (GNUNET_OK 237 if ((GNUNET_YES == enter_room_at (room, handle, door)) &&
338 == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 238 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
239 key, room,
240 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
339 { 241 {
340 return GNUNET_YES; 242 return GNUNET_YES;
341 } 243 }
@@ -351,20 +253,14 @@ int
351close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 253close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
352 const struct GNUNET_HashCode *key) 254 const struct GNUNET_HashCode *key)
353{ 255{
256 GNUNET_assert((service) && (handle) && (key));
257
354 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); 258 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
355 259
356 if (!room) 260 if (!room)
357 return GNUNET_NO; 261 return GNUNET_NO;
358 262
359 struct GNUNET_MESSENGER_Message *message = create_message_leave (); 263 send_room_message (room, handle, create_message_leave ());
360
361 if (message)
362 {
363 struct GNUNET_HashCode hash;
364
365 send_room_message (room, handle, message, &hash);
366 destroy_message (message);
367 }
368 264
369 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); 265 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
370 266
@@ -393,124 +289,18 @@ close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
393 return GNUNET_YES; 289 return GNUNET_YES;
394} 290}
395 291
396static void
397get_room_data_subdir (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
398{
399 GNUNET_asprintf (dir, "%s%s%c%s%c", service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (&(room->key)), DIR_SEPARATOR);
400}
401
402void
403load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room)
404{
405 char *room_dir;
406 get_room_data_subdir (service, room, &room_dir);
407
408 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
409 {
410 load_message_store (&room->store, room_dir);
411
412 char *config_file;
413 GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg");
414
415 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
416
417 if ((GNUNET_YES == GNUNET_DISK_file_test (config_file)) && (GNUNET_OK
418 == GNUNET_CONFIGURATION_parse (cfg, config_file)))
419 {
420 unsigned long long access;
421
422 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "room", "access-rule", &access))
423 room->strict_access = (int) (access);
424
425 char *message_string;
426
427 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "room", "last-message", &message_string)) && (message_string))
428 {
429 struct GNUNET_HashCode hash;
430
431 GNUNET_CRYPTO_hash_from_string(message_string, &hash);
432
433 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, &hash, GNUNET_NO);
434
435 if (message)
436 update_room_last_messages (room, message, &hash);
437
438 GNUNET_free(message_string);
439 }
440 }
441
442 GNUNET_CONFIGURATION_destroy (cfg);
443
444 GNUNET_free(config_file);
445 }
446
447 GNUNET_free(room_dir);
448}
449
450void
451save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room)
452{
453 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (service->rooms, &(room->key)))
454 {
455 return;
456 }
457
458 char *room_dir;
459 get_room_data_subdir (service, room, &room_dir);
460
461 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) || (GNUNET_OK
462 == GNUNET_DISK_directory_create (room_dir)))
463 {
464 save_message_store (&room->store, room_dir);
465
466 char *config_file;
467 GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg");
468
469 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
470
471 GNUNET_CONFIGURATION_set_value_number (cfg, "room", "access-rule", room->strict_access);
472
473 if (room->last_messages.head)
474 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "last-message",
475 GNUNET_h2s_full (&(room->last_messages.head->hash)));
476
477 GNUNET_CONFIGURATION_write (cfg, config_file);
478 GNUNET_CONFIGURATION_destroy (cfg);
479
480 GNUNET_free(config_file);
481 }
482
483 GNUNET_free(room_dir);
484}
485
486void 292void
487handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, 293handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
294 const struct GNUNET_MESSENGER_MemberSession *session,
488 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 295 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
489{ 296{
490 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head; 297 GNUNET_assert((service) && (room) && (session) && (message) && (hash));
491 298
492 const uint16_t length = get_message_size (message); 299 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
493 300
494 while (element) 301 while (element)
495 { 302 {
496 struct GNUNET_MESSENGER_SrvHandle *handle = (struct GNUNET_MESSENGER_SrvHandle*) element->handle; 303 notify_handle_message (element->handle, get_room_key(room), session, message, hash);
497
498 if ((handle->mq) && (get_handle_member_id (handle, &(room->key))))
499 {
500 struct GNUNET_MESSENGER_RecvMessage *msg;
501 struct GNUNET_MQ_Envelope *env;
502
503 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
504
505 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key));
506 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
507
508 char *buffer = ((char*) msg) + sizeof(*msg);
509 encode_message (message, length, buffer);
510
511 GNUNET_MQ_send (handle->mq, env);
512 }
513
514 element = element->next; 304 element = element->next;
515 } 305 }
516} 306}
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h
index 246c74771..aa43fa457 100644
--- a/src/messenger/gnunet-service-messenger_service.h
+++ b/src/messenger/gnunet-service-messenger_service.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -33,13 +33,14 @@
33#include "gnunet_disk_lib.h" 33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h" 34#include "gnunet_identity_service.h"
35 35
36#include "messenger_api_ego.h" 36#include "gnunet-service-messenger_ego_store.h"
37
38#include "gnunet-service-messenger_list_handles.h" 37#include "gnunet-service-messenger_list_handles.h"
39 38
40#include "gnunet-service-messenger_contact.h" 39#include "messenger_api_contact_store.h"
41#include "gnunet-service-messenger_room.h" 40#include "gnunet-service-messenger_room.h"
42 41
42#include "gnunet-service-messenger_member_session.h"
43
43struct GNUNET_MESSENGER_Service 44struct GNUNET_MESSENGER_Service
44{ 45{
45 const struct GNUNET_CONFIGURATION_Handle *config; 46 const struct GNUNET_CONFIGURATION_Handle *config;
@@ -50,21 +51,20 @@ struct GNUNET_MESSENGER_Service
50 char *dir; 51 char *dir;
51 52
52 struct GNUNET_CADET_Handle *cadet; 53 struct GNUNET_CADET_Handle *cadet;
53 struct GNUNET_IDENTITY_Handle *identity;
54 54
55 struct GNUNET_CONTAINER_MultiHashMap *egos; 55 struct GNUNET_MESSENGER_EgoStore ego_store;
56 struct GNUNET_MESSENGER_ContactStore contact_store;
56 57
57 struct GNUNET_MESSENGER_ListHandles handles; 58 struct GNUNET_MESSENGER_ListHandles handles;
58 59
59 struct GNUNET_CONTAINER_MultiHashMap *contacts;
60 struct GNUNET_CONTAINER_MultiHashMap *rooms; 60 struct GNUNET_CONTAINER_MultiHashMap *rooms;
61}; 61};
62 62
63/** 63/**
64 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle. 64 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle.
65 * 65 *
66 * @param config Configuration 66 * @param[in] config Configuration
67 * @param service_handle GNUnet service handle 67 * @param[in/out] service_handle GNUnet service handle
68 * @return New service 68 * @return New service
69 */ 69 */
70struct GNUNET_MESSENGER_Service* 70struct GNUNET_MESSENGER_Service*
@@ -73,39 +73,34 @@ create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_
73/** 73/**
74 * Destroys a <i>service</i> and frees its memory fully. 74 * Destroys a <i>service</i> and frees its memory fully.
75 * 75 *
76 * @param service Service 76 * @param[in/out] service Service
77 */ 77 */
78void 78void
79destroy_service (struct GNUNET_MESSENGER_Service *service); 79destroy_service (struct GNUNET_MESSENGER_Service *service);
80 80
81/** 81/**
82 * Lookups an EGO which was registered to a <i>service</i> under 82 * Returns the used EGO-store of a given <i>service</i>.
83 * a specific <i>identifier</i>.
84 * 83 *
85 * @param service Service 84 * @param[in/out] service Service
86 * @param identifier Identifier string 85 * @return EGO-store
87 * @return EGO or NULL
88 */ 86 */
89struct GNUNET_MESSENGER_Ego* 87struct GNUNET_MESSENGER_EgoStore*
90lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier); 88get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
91 89
92/** 90/**
93 * Updates the registration of an EGO to a <i>service</i> under 91 * Returns the used contact store of a given <i>service</i>.
94 * a specific <i>identifier</i> with a new <i>key</i>.
95 * 92 *
96 * @param service Service 93 * @param[in/out] service Service
97 * @param identifier Identifier string 94 * @return Contact store
98 * @param key Private EGO key
99 */ 95 */
100void 96struct GNUNET_MESSENGER_ContactStore*
101update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, 97get_service_contact_store (struct GNUNET_MESSENGER_Service *service);
102 const struct GNUNET_IDENTITY_PrivateKey* key);
103 98
104/** 99/**
105 * Creates and adds a new handle to a <i>service</i> using a given message queue. 100 * Creates and adds a new handle to a <i>service</i> using a given message queue.
106 * 101 *
107 * @param service Service 102 * @param[in/out] service Service
108 * @param mq Message queue 103 * @param[in/out] mq Message queue
109 * @return New handle 104 * @return New handle
110 */ 105 */
111struct GNUNET_MESSENGER_SrvHandle* 106struct GNUNET_MESSENGER_SrvHandle*
@@ -114,77 +109,42 @@ add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_H
114/** 109/**
115 * Removes a <i>handle</i> from a <i>service</i> and destroys it. 110 * Removes a <i>handle</i> from a <i>service</i> and destroys it.
116 * 111 *
117 * @param service Service 112 * @param[in/out] service Service
118 * @param handle Handle 113 * @param[in/out] handle Handle
119 */ 114 */
120void 115void
121remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle); 116remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle);
122 117
123/** 118/**
124 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i> 119 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i>
125 * parameter. The functions returns GNUNET_OK on success, otherwise GNUNET_SYSERR. 120 * parameter. The functions returns #GNUNET_OK on success, otherwise #GNUNET_SYSERR.
126 * 121 *
127 * @param service Service 122 * @param[in] service Service
128 * @param[out] peer Peer identity 123 * @param[out] peer Peer identity
129 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR 124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
130 */ 125 */
131int 126int
132get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer); 127get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer);
133 128
134/** 129/**
135 * Returns a contact of a <i>service</i> identified by a given public key. If no matching contact exists,
136 * it will tried to create one with the specific public key. If the function still fails to do so,
137 * NULL gets returned.
138 *
139 * @param service Service
140 * @param pubkey Public key of EGO
141 * @return Contact
142 */
143struct GNUNET_MESSENGER_SrvContact*
144get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey);
145
146/**
147 * Changes the public key for a <i>contact</i> known to a <i>service</i> to a specific public key and
148 * updates local map entries to access the contact by its updated key.
149 *
150 * @param service Service
151 * @param contact Contact
152 * @param pubkey Public key of EGO
153 */
154void
155swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact,
156 const struct GNUNET_IDENTITY_PublicKey *pubkey);
157
158/**
159 * Tries to generate and allocate a new unique member id for a given room of a service identified by its <i>key</i>.
160 * If the generation fails caused by too many tries of duplicates, it returns NULL.
161 *
162 * @param service Service
163 * @param key Key of room
164 * @return Newly generated member id or NULL
165 */
166struct GNUNET_ShortHashCode*
167generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key);
168
169/**
170 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room 130 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room
171 * using the given key, NULL gets returned. 131 * using the given key, NULL gets returned.
172 * 132 *
173 * @param service Service 133 * @param[in] service Service
174 * @param key Key of room 134 * @param[in] key Key of room
175 * @return Room or NULL 135 * @return Room or NULL
176 */ 136 */
177struct GNUNET_MESSENGER_SrvRoom* 137struct GNUNET_MESSENGER_SrvRoom*
178get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key); 138get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key);
179 139
180/** 140/**
181 * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be 141 * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be
182 * created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 142 * created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
183 * 143 *
184 * @param service Service 144 * @param[in/out] service Service
185 * @param handle Handle 145 * @param[in/out] handle Handle
186 * @param key Key of room 146 * @param[in] key Key of room
187 * @return GNUNET_YES on success, otherwise GNUNET_NO 147 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
188 */ 148 */
189int 149int
190open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 150open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
@@ -192,16 +152,16 @@ open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSE
192 152
193/** 153/**
194 * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will 154 * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
195 * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 155 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
196 * 156 *
197 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and 157 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and
198 * a new connection will be made. 158 * a new connection will be made.
199 * 159 *
200 * @param service Service 160 * @param[in/out] service Service
201 * @param handle Handle 161 * @param[in/out] handle Handle
202 * @param door Peer identity 162 * @param[in] door Peer identity
203 * @param key Key of room 163 * @param[in] key Key of room
204 * @return GNUNET_YES on success, otherwise GNUNET_NO 164 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
205 */ 165 */
206int 166int
207entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 167entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
@@ -209,51 +169,33 @@ entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESS
209 169
210/** 170/**
211 * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will 171 * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
212 * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. 172 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
213 * 173 *
214 * If the specific handle is currently the host of the room for this service, a new handle which is a member will 174 * If the specific handle is currently the host of the room for this service, a new handle which is a member will
215 * take its place. Otherwise the room will be destroyed for this service. 175 * take its place. Otherwise the room will be destroyed for this service.
216 * 176 *
217 * @param service Service 177 * @param[in/out] service Service
218 * @param handle Handle 178 * @param[in/out] handle Handle
219 * @param key Key of room 179 * @param[in] key Key of room
220 * @return GNUNET_YES on success, otherwise GNUNET_NO 180 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
221 */ 181 */
222int 182int
223close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, 183close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
224 const struct GNUNET_HashCode *key); 184 const struct GNUNET_HashCode *key);
225 185
226/** 186/**
227 * Loads the local configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash
228 * and the ruleset for general access of new members.
229 *
230 * @param service Service
231 * @param room Room
232 */
233void
234load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room);
235
236/**
237 * Saves the configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash
238 * and the ruleset for general access of new members locally.
239 *
240 * @param service Service
241 * @param room Room
242 */
243void
244save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room);
245
246/**
247 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which 187 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which
248 * is currently member of a specific <i>room</i> for handling it in the client API. 188 * is currently member of a specific <i>room</i> for handling it in the client API.
249 * 189 *
250 * @param service Service 190 * @param[in/out] service Service
251 * @param room Room 191 * @param[in/out] room Room
252 * @param message Message 192 * @param[in] session Member session
253 * @param hash Hash of message 193 * @param[in] message Message
194 * @param[in] hash Hash of message
254 */ 195 */
255void 196void
256handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, 197handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
198 const struct GNUNET_MESSENGER_MemberSession *session,
257 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 199 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
258 200
259#endif //GNUNET_SERVICE_MESSENGER_SERVICE_H 201#endif //GNUNET_SERVICE_MESSENGER_SERVICE_H
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c
index df9e5c4c7..f7e8713c6 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ b/src/messenger/gnunet-service-messenger_tunnel.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -26,7 +26,8 @@
26#include "gnunet-service-messenger_tunnel.h" 26#include "gnunet-service-messenger_tunnel.h"
27 27
28#include "gnunet-service-messenger_handle.h" 28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_util.h" 29#include "gnunet-service-messenger_message_recv.h"
30#include "messenger_api_util.h"
30 31
31struct GNUNET_MESSENGER_SrvTunnel* 32struct GNUNET_MESSENGER_SrvTunnel*
32create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door) 33create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door)
@@ -39,7 +40,8 @@ create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerId
39 tunnel->channel = NULL; 40 tunnel->channel = NULL;
40 41
41 tunnel->peer = GNUNET_PEER_intern (door); 42 tunnel->peer = GNUNET_PEER_intern (door);
42 tunnel->contact_id = NULL; 43
44 tunnel->messenger_version = 0;
43 45
44 tunnel->peer_message = NULL; 46 tunnel->peer_message = NULL;
45 tunnel->last_message = NULL; 47 tunnel->last_message = NULL;
@@ -57,9 +59,6 @@ destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
57 59
58 GNUNET_PEER_change_rc (tunnel->peer, -1); 60 GNUNET_PEER_change_rc (tunnel->peer, -1);
59 61
60 if (tunnel->contact_id)
61 GNUNET_free(tunnel->contact_id);
62
63 if (tunnel->peer_message) 62 if (tunnel->peer_message)
64 GNUNET_free(tunnel->peer_message); 63 GNUNET_free(tunnel->peer_message);
65 64
@@ -69,22 +68,15 @@ destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
69 GNUNET_free(tunnel); 68 GNUNET_free(tunnel);
70} 69}
71 70
72int 71void
73bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel) 72bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel)
74{ 73{
75 GNUNET_assert(tunnel); 74 GNUNET_assert(tunnel);
76 75
77 if (tunnel->channel) 76 if (tunnel->channel)
78 {
79 if (tunnel->contact_id)
80 return GNUNET_NO;
81
82 delayed_disconnect_channel (tunnel->channel); 77 delayed_disconnect_channel (tunnel->channel);
83 }
84 78
85 tunnel->channel = channel; 79 tunnel->channel = channel;
86
87 return GNUNET_YES;
88} 80}
89 81
90extern void 82extern void
@@ -113,52 +105,49 @@ check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
113 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 105 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
114 106
115 if (!tunnel) 107 if (!tunnel)
116 return GNUNET_NO; 108 return GNUNET_SYSERR;
117 109
118 const uint16_t length = ntohs (header->size) - sizeof(*header); 110 const uint16_t length = ntohs (header->size) - sizeof(*header);
119 const char *buffer = (const char*) &header[1]; 111 const char *buffer = (const char*) &header[1];
120 112
121 struct GNUNET_MESSENGER_Message message; 113 struct GNUNET_MESSENGER_Message message;
122 114
123 if (length < sizeof(message.header)) 115 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
124 return GNUNET_NO; 116 {
125 117 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Message too short! (%d)\n", length);
126 if (GNUNET_YES != decode_message (&message, length, buffer)) 118 return GNUNET_SYSERR;
127 return GNUNET_NO; 119 }
128
129 struct GNUNET_HashCode hash;
130 hash_message (length, buffer, &hash);
131 120
132 int result = callback_verify_room_message (tunnel->room, cls, &message, &hash); 121 uint16_t padding = 0;
133 122
134 if (GNUNET_MESSENGER_KIND_PEER == message.header.kind) 123 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, &padding))
135 { 124 {
136 struct GNUNET_PeerIdentity identity; 125 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
137 126 return GNUNET_SYSERR;
138 GNUNET_PEER_resolve (tunnel->peer, &identity);
139
140 if (0 == GNUNET_memcmp(&(message.body.peer.peer), &(identity)))
141 {
142 if (tunnel->contact_id)
143 {
144 if (0 != GNUNET_memcmp(tunnel->contact_id, &(message.header.sender_id)))
145 result = GNUNET_SYSERR;
146 }
147 else
148 {
149 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
150
151 GNUNET_memcpy(tunnel->contact_id, &(message.header.sender_id), sizeof(struct GNUNET_ShortHashCode));
152 }
153 }
154 } 127 }
155 128
156 return (result == GNUNET_YES ? GNUNET_OK : GNUNET_NO); 129 struct GNUNET_HashCode hash;
130 hash_message (&message, length - padding, buffer, &hash);
131
132 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
157} 133}
158 134
135extern int
136update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
137 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
138
159extern void 139extern void
160callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, 140callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
161 const struct GNUNET_HashCode *hash); 141 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
142
143static void
144update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash)
145{
146 if (!tunnel->last_message)
147 tunnel->last_message = GNUNET_new(struct GNUNET_HashCode);
148
149 GNUNET_memcpy(tunnel->last_message, hash, sizeof(*hash));
150}
162 151
163void 152void
164handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header) 153handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
@@ -171,19 +160,48 @@ handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
171 struct GNUNET_MESSENGER_Message message; 160 struct GNUNET_MESSENGER_Message message;
172 struct GNUNET_HashCode hash; 161 struct GNUNET_HashCode hash;
173 162
174 decode_message (&message, length, buffer); 163 uint16_t padding = 0;
175 hash_message (length, buffer, &hash);
176 164
177 if (tunnel) 165 decode_message (&message, length, buffer, GNUNET_YES, &padding);
178 { 166 hash_message (&message, length - padding, buffer, &hash);
179 if (!tunnel->last_message) 167
180 tunnel->last_message = GNUNET_new(struct GNUNET_HashCode); 168 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
169 GNUNET_MESSENGER_name_of_kind(message.header.kind));
170
171 if (!tunnel)
172 return;
173
174 const int new_message = update_room_message (tunnel->room, copy_message (&message), &hash);
175
176 if (GNUNET_YES != new_message)
177 goto receive_done;
181 178
182 GNUNET_memcpy(tunnel->last_message, &hash, sizeof(struct GNUNET_HashCode)); 179 update_tunnel_last_message (tunnel, &hash);
183 180
184 callback_room_recv (tunnel->room, cls, copy_message (&message), &hash); 181 int forward_message = GNUNET_YES;
182
183 switch (message.header.kind)
184 {
185 case GNUNET_MESSENGER_KIND_INFO:
186 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
187 break;
188 case GNUNET_MESSENGER_KIND_PEER:
189 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
190 break;
191 case GNUNET_MESSENGER_KIND_REQUEST:
192 forward_message = recv_message_request (tunnel->room, tunnel, &message, &hash);
193 break;
194 default:
195 break;
196 }
197
198 if (GNUNET_YES == forward_message)
199 {
200 forward_room_message (tunnel->room, tunnel, &message, &hash);
201 callback_room_handle_message (tunnel->room, NULL, &message, &hash);
185 } 202 }
186 203
204receive_done:
187 GNUNET_CADET_receive_done (tunnel->channel); 205 GNUNET_CADET_receive_done (tunnel->channel);
188} 206}
189 207
@@ -198,7 +216,7 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
198 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer); 216 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
199 217
200 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room); 218 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room);
201 struct GNUNET_HashCode *key = get_room_key (tunnel->room); 219 const struct GNUNET_HashCode *key = get_room_key (tunnel->room);
202 220
203 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, 221 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
204 struct GNUNET_MessageHeader, NULL), 222 struct GNUNET_MessageHeader, NULL),
@@ -212,6 +230,8 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
212void 230void
213disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) 231disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
214{ 232{
233 GNUNET_assert(tunnel);
234
215 if (tunnel->channel) 235 if (tunnel->channel)
216 { 236 {
217 delayed_disconnect_channel (tunnel->channel); 237 delayed_disconnect_channel (tunnel->channel);
@@ -223,6 +243,8 @@ disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
223int 243int
224is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) 244is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
225{ 245{
246 GNUNET_assert(tunnel);
247
226 return (tunnel->channel ? GNUNET_YES : GNUNET_NO); 248 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
227} 249}
228 250
@@ -232,30 +254,23 @@ struct GNUNET_MESSENGER_MessageSent
232 struct GNUNET_HashCode hash; 254 struct GNUNET_HashCode hash;
233}; 255};
234 256
235extern void
236callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls,
237 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
238
239static void 257static void
240callback_tunnel_sent (void *cls) 258callback_tunnel_sent (void *cls)
241{ 259{
242 struct GNUNET_MESSENGER_MessageSent *sent = cls; 260 struct GNUNET_MESSENGER_MessageSent *sent = cls;
243 261
244 if (sent->tunnel) 262 if (sent->tunnel)
245 { 263 update_tunnel_last_message (sent->tunnel, &(sent->hash));
246 if (!sent->tunnel->last_message)
247 sent->tunnel->last_message = GNUNET_new(struct GNUNET_HashCode);
248
249 GNUNET_memcpy(sent->tunnel->last_message, &(sent->hash), sizeof(struct GNUNET_HashCode));
250 }
251 264
252 GNUNET_free(sent); 265 GNUNET_free(sent);
253} 266}
254 267
255void 268void
256send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, 269send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
257 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 270 const struct GNUNET_HashCode *hash)
258{ 271{
272 GNUNET_assert((tunnel) && (env) && (hash));
273
259 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel); 274 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
260 275
261 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent); 276 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
@@ -266,35 +281,91 @@ send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, s
266 281
267 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent); 282 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
268 GNUNET_MQ_send (mq, env); 283 GNUNET_MQ_send (mq, env);
269
270 callback_room_sent (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, tunnel, message, hash);
271} 284}
272 285
273void 286int
274send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, 287send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message)
275 struct GNUNET_HashCode *hash)
276{ 288{
277 struct GNUNET_MQ_Envelope *env = pack_room_message (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, 289 GNUNET_assert((tunnel) && (handle));
278 message, hash, 290
279 GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 291 if (!message)
292 return GNUNET_NO;
293
294 struct GNUNET_HashCode hash;
295 struct GNUNET_MQ_Envelope *env = pack_room_message (
296 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
297 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
298 );
299
300 destroy_message(message);
301
302 if (!env)
303 return GNUNET_NO;
304
305 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
306 GNUNET_h2s(&hash));
280 307
281 if (env) 308 send_tunnel_envelope (tunnel, env, &hash);
282 send_tunnel_envelope (tunnel, handle, env, copy_message (message), hash); 309 return GNUNET_YES;
283} 310}
284 311
285void 312void
286forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, 313forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
287 const struct GNUNET_HashCode *hash) 314 const struct GNUNET_HashCode *hash)
288{ 315{
289 struct GNUNET_MESSENGER_Message *clone = copy_message (message); 316 if (!message)
290 struct GNUNET_MQ_Envelope *env = pack_message (clone, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 317 return;
318
319 GNUNET_assert((tunnel) && (message) && (hash));
320
321 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
322 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
323
324 destroy_message(copy);
325
326 if (!env)
327 return;
328
329 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
330 GNUNET_h2s(hash));
291 331
292 if (env) 332 send_tunnel_envelope (tunnel, env, hash);
293 send_tunnel_envelope (tunnel, NULL, env, clone, hash);
294} 333}
295 334
296const struct GNUNET_HashCode* 335const struct GNUNET_HashCode*
297get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) 336get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
298{ 337{
338 GNUNET_assert(tunnel);
339
299 return tunnel->peer_message; 340 return tunnel->peer_message;
300} 341}
342
343void
344get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer)
345{
346 GNUNET_assert(tunnel);
347
348 GNUNET_PEER_resolve(tunnel->peer, peer);
349}
350
351uint32_t
352get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
353{
354 GNUNET_assert(tunnel);
355
356 return tunnel->messenger_version;
357}
358
359int
360update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version)
361{
362 GNUNET_assert(tunnel);
363
364 if (version != GNUNET_MESSENGER_VERSION)
365 return GNUNET_SYSERR;
366
367 if (version > tunnel->messenger_version)
368 tunnel->messenger_version = version;
369
370 return GNUNET_OK;
371}
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
index e6efb226d..51c5d32c1 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ b/src/messenger/gnunet-service-messenger_tunnel.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -39,17 +39,18 @@ struct GNUNET_MESSENGER_SrvTunnel
39 struct GNUNET_CADET_Channel *channel; 39 struct GNUNET_CADET_Channel *channel;
40 40
41 GNUNET_PEER_Id peer; 41 GNUNET_PEER_Id peer;
42 struct GNUNET_ShortHashCode *contact_id; 42
43 uint32_t messenger_version;
43 44
44 struct GNUNET_HashCode *peer_message; 45 struct GNUNET_HashCode *peer_message;
45 struct GNUNET_HashCode *last_message; 46 struct GNUNET_HashCode *last_message;
46}; 47};
47 48
48/** 49/**
49 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity. 50 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity (called <i>door</i>).
50 * 51 *
51 * @param room Room 52 * @param[in/out] room Room
52 * @param door Peer identity 53 * @param[in] door Peer identity
53 * @return New tunnel 54 * @return New tunnel
54 */ 55 */
55struct GNUNET_MESSENGER_SrvTunnel* 56struct GNUNET_MESSENGER_SrvTunnel*
@@ -58,28 +59,27 @@ create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerId
58/** 59/**
59 * Destroys a <i>tunnel</i> and frees its memory fully. 60 * Destroys a <i>tunnel</i> and frees its memory fully.
60 * 61 *
61 * @param tunnel 62 * @param[in/out] tunnel
62 */ 63 */
63void 64void
64destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 65destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
65 66
66/** 67/**
67 * Binds a CADET <i>channel</i> to a <i>tunnel</i> on returns GNUNET_YES only if 68 * Binds a CADET <i>channel</i> to a <i>tunnel</i> and replaces its channel
68 * the bounds channel was replaced successfully, otherwise GNUNET_NO gets returned. 69 * the tunnel is currently bound to if necessary.
69 * 70 *
70 * @param tunnel Tunnel 71 * @param[in/out] tunnel Tunnel
71 * @param channel CADET channel 72 * @param[in/out] channel CADET channel
72 * @return GNUNET_YES on success, otherwise GNUNET_NO
73 */ 73 */
74int 74void
75bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel); 75bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel);
76 76
77/** 77/**
78 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it. 78 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it.
79 * The function returns GNUNET_YES on success, otherwise GNUNET_NO. 79 * The function returns #GNUNET_YES on success, otherwise #GNUNET_NO.
80 * 80 *
81 * @param tunnel Tunnel 81 * @param[in/out] tunnel Tunnel
82 * @return GNUNET_YES on success, otherwise GNUNET_NO 82 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
83 */ 83 */
84int 84int
85connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 85connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
@@ -88,7 +88,7 @@ connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
88 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection 88 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection
89 * will be asynchronous. 89 * will be asynchronous.
90 * 90 *
91 * @param tunnel Tunnel 91 * @param[in/out] tunnel Tunnel
92 */ 92 */
93void 93void
94disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); 94disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
@@ -96,46 +96,43 @@ disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
96/** 96/**
97 * Returns the status of a currently bound channel of a <i>tunnel</i>. 97 * Returns the status of a currently bound channel of a <i>tunnel</i>.
98 * 98 *
99 * @param tunnel Tunnel 99 * @param[in] tunnel Tunnel
100 * @return GNUNET_YES or GNUNET_NO 100 * @return #GNUNET_YES or #GNUNET_NO
101 */ 101 */
102int 102int
103is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); 103is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
104 104
105/** 105/**
106 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through 106 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through
107 * a <i>tunnel</i> by a given <i>handle</i>. 107 * a <i>tunnel</i>.
108 * 108 *
109 * @param tunnel Tunnel 109 * @param[in/out] tunnel Tunnel
110 * @param handle Handle 110 * @param[in/out] env Envelope
111 * @param env Envelope 111 * @param[in] hash Hash of message
112 * @param message Message
113 * @param hash Hash of message
114 */ 112 */
115void 113void
116send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, 114send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
117 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 115 const struct GNUNET_HashCode *hash);
118 116
119/** 117/**
120 * Sends a <i>message</i> by packing it automatically into an envelope and passing it 118 * Sends a <i>message</i> by packing it automatically into an envelope and passing it
121 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and 119 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and
122 * the <i>hash</i> will be calculated and stored. 120 * the <i>hash</i> will be calculated and stored.
123 * 121 *
124 * @param tunnel Tunnel 122 * @param[in/out] tunnel Tunnel
125 * @param handle Handle 123 * @param[in/out] handle Handle
126 * @param[out] message Message 124 * @param[in/out] message Message
127 * @param[out] hash Hash of message 125 * @return #GNUNET_YES on success, GNUNET_NO otherwise
128 */ 126 */
129void 127int
130send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, 128send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message);
131 struct GNUNET_HashCode *hash);
132 129
133/** 130/**
134 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>. 131 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>.
135 * 132 *
136 * @param tunnel Tunnel 133 * @param[in/out] tunnel Tunnel
137 * @param message Message 134 * @param[in] message Message
138 * @param hash Hash of message 135 * @param[in] hash Hash of message
139 */ 136 */
140void 137void
141forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, 138forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
@@ -146,10 +143,43 @@ forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct
146 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel 143 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel
147 * yet, NULL gets returned. 144 * yet, NULL gets returned.
148 * 145 *
149 * @param tunnel Tunnel 146 * @param[in] tunnel Tunnel
150 * @return Hash of peer message or NULL 147 * @return Hash of peer message or NULL
151 */ 148 */
152const struct GNUNET_HashCode* 149const struct GNUNET_HashCode*
153get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); 150get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
154 151
152/**
153 * Writes the peer identity of the peer connected via <i>tunnel</i> to this peer into
154 * the <i>peer</i> parameter.
155 *
156 * @param[in] tunnel Tunnel
157 * @param[out] peer Peer identity
158 */
159void
160get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer);
161
162/**
163 * Returns the current messenger version the peer connected via a given <i>tunnel</i>
164 * has reported to be using if it was compatible during updating.
165 *
166 * @see update_tunnel_messenger_version
167 *
168 * @param[in] tunnel Tunnel
169 * @return Version of messenger
170 */
171uint32_t
172get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
173
174/**
175 * Updates the messenger version of the <i>tunnel</i> to a given <i>version</i> if
176 * it is compatible to the running peer of the service. Depending on success it
177 * returns #GNUNET_OK or #GNUNET_SYSERR on failure.
178 *
179 * @param[in/out] tunnel Tunnel
180 * @param[in] version Version of messenger
181 */
182int
183update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version);
184
155#endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H 185#endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
index 6401b18d7..dc6d11aaf 100644
--- a/src/messenger/messenger_api.c
+++ b/src/messenger/messenger_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
29 29
30#include "messenger_api_handle.h" 30#include "messenger_api_handle.h"
31#include "messenger_api_message.h" 31#include "messenger_api_message.h"
32#include "messenger_api_util.h"
32 33
33const char* 34const char*
34GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind) 35GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
@@ -61,6 +62,8 @@ GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
61 return "TEXT"; 62 return "TEXT";
62 case GNUNET_MESSENGER_KIND_FILE: 63 case GNUNET_MESSENGER_KIND_FILE:
63 return "FILE"; 64 return "FILE";
65 case GNUNET_MESSENGER_KIND_PRIVATE:
66 return "PRIVATE";
64 default: 67 default:
65 return "UNKNOWN"; 68 return "UNKNOWN";
66 } 69 }
@@ -82,7 +85,25 @@ handle_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
82 85
83 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name); 86 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
84 87
85 set_handle_name (handle, strlen(name) > 0? name : NULL); 88 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
89}
90
91static int
92check_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
93{
94 const uint16_t full_length = ntohs (msg->header.size);
95
96 if (full_length < sizeof(*msg))
97 return GNUNET_NO;
98
99 const uint16_t length = full_length - sizeof(*msg);
100 const char *buffer = ((const char*) msg) + sizeof(*msg);
101
102 struct GNUNET_IDENTITY_PublicKey pubkey;
103 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
104 return GNUNET_NO;
105
106 return GNUNET_OK;
86} 107}
87 108
88static void 109static void
@@ -90,11 +111,18 @@ handle_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
90{ 111{
91 struct GNUNET_MESSENGER_Handle *handle = cls; 112 struct GNUNET_MESSENGER_Handle *handle = cls;
92 113
93 const struct GNUNET_IDENTITY_PublicKey *pubkey = &(msg->pubkey); 114 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
115 const char *buffer = ((const char*) msg) + sizeof(*msg);
116
117 struct GNUNET_IDENTITY_PublicKey pubkey;
118 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
119 return;
94 120
95 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", GNUNET_IDENTITY_public_key_to_string (pubkey)); 121 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
122 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
123 GNUNET_free(str);
96 124
97 set_handle_key (handle, pubkey); 125 set_handle_key (handle, &pubkey);
98 126
99 if (handle->identity_callback) 127 if (handle->identity_callback)
100 handle->identity_callback (handle->identity_cls, handle); 128 handle->identity_callback (handle->identity_cls, handle);
@@ -161,12 +189,12 @@ handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
161static int 189static int
162check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) 190check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
163{ 191{
164 const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); 192 const uint16_t full_length = ntohs (msg->header.size);
165 193
166 if (full_length < sizeof(msg->hash)) 194 if (full_length < sizeof(*msg))
167 return GNUNET_NO; 195 return GNUNET_NO;
168 196
169 const uint16_t length = full_length - sizeof(msg->hash); 197 const uint16_t length = full_length - sizeof(*msg);
170 const char *buffer = ((const char*) msg) + sizeof(*msg); 198 const char *buffer = ((const char*) msg) + sizeof(*msg);
171 199
172 struct GNUNET_MESSENGER_Message message; 200 struct GNUNET_MESSENGER_Message message;
@@ -174,7 +202,7 @@ check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
174 if (length < sizeof(message.header)) 202 if (length < sizeof(message.header))
175 return GNUNET_NO; 203 return GNUNET_NO;
176 204
177 if (GNUNET_YES != decode_message (&message, length, buffer)) 205 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
178 return GNUNET_NO; 206 return GNUNET_NO;
179 207
180 return GNUNET_OK; 208 return GNUNET_OK;
@@ -186,14 +214,18 @@ handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
186 struct GNUNET_MESSENGER_Handle *handle = cls; 214 struct GNUNET_MESSENGER_Handle *handle = cls;
187 215
188 const struct GNUNET_HashCode *key = &(msg->key); 216 const struct GNUNET_HashCode *key = &(msg->key);
217 const struct GNUNET_HashCode *sender = &(msg->sender);
218 const struct GNUNET_HashCode *context = &(msg->context);
189 const struct GNUNET_HashCode *hash = &(msg->hash); 219 const struct GNUNET_HashCode *hash = &(msg->hash);
190 220 const enum GNUNET_MESSENGER_MessageFlags flags = (
191 const char *buffer = ((const char*) msg) + sizeof(*msg); 221 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
222 );
192 223
193 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); 224 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
225 const char *buffer = ((const char*) msg) + sizeof(*msg);
194 226
195 struct GNUNET_MESSENGER_Message message; 227 struct GNUNET_MESSENGER_Message message;
196 decode_message (&message, length, buffer); 228 decode_message (&message, length, buffer, GNUNET_YES, NULL);
197 229
198 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind)); 230 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
199 231
@@ -201,13 +233,22 @@ handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
201 233
202 if (room) 234 if (room)
203 { 235 {
204 handle_room_message (room, &message, hash); 236 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
237
238 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
239 GNUNET_h2s(sender), GNUNET_h2s_full(context));
240
241 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
242 store, context, sender
243 );
244
245 handle_room_message (room, contact, &message, hash);
205 246
206 if (handle->msg_callback) 247 if (handle->msg_callback)
207 handle->msg_callback (handle->msg_cls, room, &message, hash); 248 handle->msg_callback (handle->msg_cls, room, contact, &message, hash, flags);
208 } 249 }
209 else 250 else
210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESSENGER ERROR: Room not found\n"); 251 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found\n");
211} 252}
212 253
213static void 254static void
@@ -220,12 +261,12 @@ send_open_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_
220 struct GNUNET_MQ_Envelope *env; 261 struct GNUNET_MQ_Envelope *env;
221 262
222 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN); 263 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
223 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 264 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
224 GNUNET_MQ_send (handle->mq, env); 265 GNUNET_MQ_send (handle->mq, env);
225} 266}
226 267
227static void 268static void
228send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room, 269send_enter_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room,
229 const struct GNUNET_PeerIdentity *door) 270 const struct GNUNET_PeerIdentity *door)
230{ 271{
231 struct GNUNET_MESSENGER_RoomMessage *msg; 272 struct GNUNET_MESSENGER_RoomMessage *msg;
@@ -233,7 +274,7 @@ send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER
233 274
234 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY); 275 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
235 GNUNET_memcpy(&(msg->door), door, sizeof(*door)); 276 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
236 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 277 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
237 GNUNET_MQ_send (handle->mq, env); 278 GNUNET_MQ_send (handle->mq, env);
238} 279}
239 280
@@ -244,7 +285,7 @@ send_close_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER
244 struct GNUNET_MQ_Envelope *env; 285 struct GNUNET_MQ_Envelope *env;
245 286
246 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE); 287 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
247 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 288 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
248 GNUNET_MQ_send (handle->mq, env); 289 GNUNET_MQ_send (handle->mq, env);
249} 290}
250 291
@@ -265,7 +306,7 @@ iterate_reset_room (void *cls, const struct GNUNET_HashCode *key, void *value)
265 { 306 {
266 GNUNET_PEER_resolve (entry->peer, &door); 307 GNUNET_PEER_resolve (entry->peer, &door);
267 308
268 send_entry_room (handle, room, &door); 309 send_enter_room (handle, room, &door);
269 310
270 entry = entry->next; 311 entry = entry->next;
271 } 312 }
@@ -303,7 +344,7 @@ callback_mq_error (void *cls, enum GNUNET_MQ_Error error)
303{ 344{
304 struct GNUNET_MESSENGER_Handle *handle = cls; 345 struct GNUNET_MESSENGER_Handle *handle = cls;
305 346
306 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); 347 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
307 348
308 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle); 349 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
309 350
@@ -319,36 +360,45 @@ callback_mq_error (void *cls, enum GNUNET_MQ_Error error)
319static void 360static void
320reconnect (struct GNUNET_MESSENGER_Handle *handle) 361reconnect (struct GNUNET_MESSENGER_Handle *handle)
321{ 362{
322 const struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size( 363 const struct GNUNET_MQ_MessageHandler handlers[] =
323 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME, struct GNUNET_MESSENGER_NameMessage, handle), 364 {
324 GNUNET_MQ_hd_fixed_size( 365 GNUNET_MQ_hd_var_size(
325 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY, 366 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
326 struct GNUNET_MESSENGER_KeyMessage, handle), 367 struct GNUNET_MESSENGER_NameMessage, handle
327 GNUNET_MQ_hd_fixed_size( 368 ),
328 member_id, 369 GNUNET_MQ_hd_var_size(
329 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID, 370 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
330 struct GNUNET_MESSENGER_MemberMessage, handle), 371 struct GNUNET_MESSENGER_KeyMessage, handle
331 GNUNET_MQ_hd_fixed_size(room_open, 372 ),
332 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, 373 GNUNET_MQ_hd_fixed_size(
333 struct GNUNET_MESSENGER_RoomMessage, 374 member_id,
334 handle), 375 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
335 GNUNET_MQ_hd_fixed_size(room_entry, 376 struct GNUNET_MESSENGER_MemberMessage, handle
336 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, 377 ),
337 struct GNUNET_MESSENGER_RoomMessage, 378 GNUNET_MQ_hd_fixed_size(
338 handle), 379 room_open,
339 GNUNET_MQ_hd_fixed_size(room_close, 380 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
340 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, 381 struct GNUNET_MESSENGER_RoomMessage, handle
341 struct GNUNET_MESSENGER_RoomMessage, 382 ),
342 handle), 383 GNUNET_MQ_hd_fixed_size(
343 GNUNET_MQ_hd_var_size( 384 room_entry,
344 recv_message, 385 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
345 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE, 386 struct GNUNET_MESSENGER_RoomMessage, handle
346 struct GNUNET_MESSENGER_RecvMessage, handle), 387 ),
347 GNUNET_MQ_handler_end() }; 388 GNUNET_MQ_hd_fixed_size(
348 389 room_close,
349 handle->mq = GNUNET_CLIENT_connect (handle->cfg, 390 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
350 GNUNET_MESSENGER_SERVICE_NAME, 391 struct GNUNET_MESSENGER_RoomMessage, handle
351 handlers, &callback_mq_error, handle); 392 ),
393 GNUNET_MQ_hd_var_size(
394 recv_message,
395 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
396 struct GNUNET_MESSENGER_RecvMessage, handle
397 ),
398 GNUNET_MQ_handler_end()
399 };
400
401 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
352} 402}
353 403
354struct GNUNET_MESSENGER_Handle* 404struct GNUNET_MESSENGER_Handle*
@@ -389,7 +439,7 @@ GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const c
389int 439int
390GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle) 440GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
391{ 441{
392 if ((!handle) || (!get_handle_name(handle))) 442 if ((!handle) || (!get_handle_name (handle)))
393 return GNUNET_SYSERR; 443 return GNUNET_SYSERR;
394 444
395 struct GNUNET_MESSENGER_UpdateMessage *msg; 445 struct GNUNET_MESSENGER_UpdateMessage *msg;
@@ -448,18 +498,30 @@ GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *n
448 return GNUNET_YES; 498 return GNUNET_YES;
449} 499}
450 500
501static const struct GNUNET_IDENTITY_PublicKey*
502get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
503{
504 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
505 return NULL;
506
507 return public_key;
508}
509
451const struct GNUNET_IDENTITY_PublicKey* 510const struct GNUNET_IDENTITY_PublicKey*
452GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle) 511GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
453{ 512{
454 if (!handle) 513 if (!handle)
455 return NULL; 514 return NULL;
456 515
457 return get_handle_key (handle); 516 return get_non_anonymous_key (get_handle_key (handle));
458} 517}
459 518
460struct GNUNET_MESSENGER_Room* 519struct GNUNET_MESSENGER_Room*
461GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 520GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
462{ 521{
522 if ((!handle) || (!key))
523 return NULL;
524
463 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 525 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
464 526
465 if (!room) 527 if (!room)
@@ -479,9 +541,12 @@ GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct
479} 541}
480 542
481struct GNUNET_MESSENGER_Room* 543struct GNUNET_MESSENGER_Room*
482GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 544GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
483 const struct GNUNET_HashCode *key) 545 const struct GNUNET_HashCode *key)
484{ 546{
547 if ((!handle) || (!door) || (!key))
548 return NULL;
549
485 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 550 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
486 551
487 if (!room) 552 if (!room)
@@ -496,20 +561,26 @@ GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struc
496 } 561 }
497 } 562 }
498 563
499 send_entry_room (handle, room, door); 564 send_enter_room (handle, room, door);
500 return room; 565 return room;
501} 566}
502 567
503void 568void
504GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room) 569GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
505{ 570{
571 if (!room)
572 return;
573
506 send_close_room (room->handle, room); 574 send_close_room (room->handle, room);
507} 575}
508 576
509struct GNUNET_MESSENGER_Contact* 577struct GNUNET_MESSENGER_Contact*
510GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id) 578GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
511{ 579{
512 return GNUNET_CONTAINER_multishortmap_get (room->members, id); 580 if ((!room) || (!hash))
581 return NULL;
582
583 return get_room_sender(room, hash);
513} 584}
514 585
515const char* 586const char*
@@ -527,23 +598,73 @@ GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact
527 if (!contact) 598 if (!contact)
528 return NULL; 599 return NULL;
529 600
530 return get_contact_key (contact); 601 return get_non_anonymous_key (get_contact_key (contact));
531} 602}
532 603
533void 604void
534GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message) 605GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
606 const struct GNUNET_MESSENGER_Contact *contact)
535{ 607{
536 const uint16_t length = get_message_size (message); 608 if ((!room) || (!message))
609 return;
610
611 switch (filter_message_sending (message))
612 {
613 case GNUNET_SYSERR:
614 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
615 return;
616 case GNUNET_NO:
617 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
618 return;
619 default:
620 break;
621 }
622
623 ssize_t key_length = 0;
624
625 if (contact)
626 {
627 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
628 get_contact_key(contact)
629 );
630
631 if (public_key)
632 key_length = GNUNET_IDENTITY_key_get_length(public_key);
633 else
634 key_length = -1;
635 }
636
637 if (key_length < 0)
638 {
639 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
640 return;
641 }
642
643 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
537 644
538 struct GNUNET_MESSENGER_SendMessage *msg; 645 struct GNUNET_MESSENGER_SendMessage *msg;
539 struct GNUNET_MQ_Envelope *env; 646 struct GNUNET_MQ_Envelope *env;
540 647
541 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE); 648 const uint16_t length = (uint16_t) key_length + msg_length;
649
650 env = GNUNET_MQ_msg_extra(
651 msg, length,
652 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
653 );
542 654
543 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 655 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
656
657 msg->flags = (uint32_t) (
658 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
659 );
544 660
545 char *buffer = ((char*) msg) + sizeof(*msg); 661 char *buffer = ((char*) msg) + sizeof(*msg);
546 encode_message (message, length, buffer); 662 char *msg_buffer = buffer + key_length;
663
664 if (key_length > 0)
665 GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
666
667 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
547 668
548 GNUNET_MQ_send (room->handle->mq, env); 669 GNUNET_MQ_send (room->handle->mq, env);
549} 670}
@@ -551,18 +672,31 @@ GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct
551const struct GNUNET_MESSENGER_Message* 672const struct GNUNET_MESSENGER_Message*
552GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) 673GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
553{ 674{
675 if ((!room) || (!hash))
676 return NULL;
677
554 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash); 678 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
555 679
556 if (!message) 680 if (!message)
557 { 681 {
558 struct GNUNET_MESSENGER_RecvMessage *msg; 682 struct GNUNET_MESSENGER_GetMessage *msg;
559 struct GNUNET_MQ_Envelope *env; 683 struct GNUNET_MQ_Envelope *env;
560 684
561 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE); 685 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
562 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); 686 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
563 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash)); 687 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
564 GNUNET_MQ_send (room->handle->mq, env); 688 GNUNET_MQ_send (room->handle->mq, env);
565 } 689 }
566 690
567 return message; 691 return message;
568} 692}
693
694int
695GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
696 void* cls)
697{
698 if (!room)
699 return GNUNET_SYSERR;
700
701 return iterate_room_members(room, callback, cls);
702}
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c
index 9a242aa00..04e1f60c1 100644
--- a/src/messenger/messenger_api_contact.c
+++ b/src/messenger/messenger_api_contact.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -28,9 +28,12 @@
28struct GNUNET_MESSENGER_Contact* 28struct GNUNET_MESSENGER_Contact*
29create_contact (const struct GNUNET_IDENTITY_PublicKey *key) 29create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
30{ 30{
31 GNUNET_assert(key);
32
31 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact); 33 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact);
32 34
33 contact->name = NULL; 35 contact->name = NULL;
36 contact->rc = 0;
34 37
35 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key)); 38 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
36 39
@@ -40,6 +43,8 @@ create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
40void 43void
41destroy_contact (struct GNUNET_MESSENGER_Contact *contact) 44destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
42{ 45{
46 GNUNET_assert(contact);
47
43 if (contact->name) 48 if (contact->name)
44 GNUNET_free(contact->name); 49 GNUNET_free(contact->name);
45 50
@@ -49,30 +54,55 @@ destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
49const char* 54const char*
50get_contact_name (const struct GNUNET_MESSENGER_Contact *contact) 55get_contact_name (const struct GNUNET_MESSENGER_Contact *contact)
51{ 56{
57 GNUNET_assert(contact);
58
52 return contact->name; 59 return contact->name;
53} 60}
54 61
55void 62void
56set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name) 63set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name)
57{ 64{
65 GNUNET_assert(contact);
66
58 if (contact->name) 67 if (contact->name)
59 GNUNET_free(contact->name); 68 GNUNET_free(contact->name);
60 69
61 contact->name = name? GNUNET_strdup(name) : NULL; 70 contact->name = name ? GNUNET_strdup(name) : NULL;
62} 71}
63 72
64const struct GNUNET_IDENTITY_PublicKey* 73const struct GNUNET_IDENTITY_PublicKey*
65get_contact_key (const struct GNUNET_MESSENGER_Contact *contact) 74get_contact_key (const struct GNUNET_MESSENGER_Contact *contact)
66{ 75{
76 GNUNET_assert(contact);
77
67 return &(contact->public_key); 78 return &(contact->public_key);
68} 79}
69 80
70const struct GNUNET_HashCode* 81void
71get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact) 82increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
72{ 83{
73 static struct GNUNET_HashCode id; 84 GNUNET_assert(contact);
85
86 contact->rc++;
87}
74 88
75 GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id); 89int
90decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
91{
92 GNUNET_assert(contact);
93
94 if (contact->rc > 0)
95 contact->rc--;
96
97 return contact->rc ? GNUNET_NO : GNUNET_YES;
98}
99
100void
101get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
102 struct GNUNET_HashCode *context)
103{
104 GNUNET_assert((key) && (id) && (context));
76 105
77 return &id; 106 GNUNET_CRYPTO_hash (id, sizeof(*id), context);
107 GNUNET_CRYPTO_hash_xor (key, context, context);
78} 108}
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h
index 0673b9b85..e94d1fcd0 100644
--- a/src/messenger/messenger_api_contact.h
+++ b/src/messenger/messenger_api_contact.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -33,6 +33,7 @@
33struct GNUNET_MESSENGER_Contact 33struct GNUNET_MESSENGER_Contact
34{ 34{
35 char *name; 35 char *name;
36 size_t rc;
36 37
37 struct GNUNET_IDENTITY_PublicKey public_key; 38 struct GNUNET_IDENTITY_PublicKey public_key;
38}; 39};
@@ -40,7 +41,7 @@ struct GNUNET_MESSENGER_Contact
40/** 41/**
41 * Creates and allocates a new contact with a given public <i>key</i> from an EGO. 42 * Creates and allocates a new contact with a given public <i>key</i> from an EGO.
42 * 43 *
43 * @param key Public key 44 * @param[in] key Public key
44 * @return New contact 45 * @return New contact
45 */ 46 */
46struct GNUNET_MESSENGER_Contact* 47struct GNUNET_MESSENGER_Contact*
@@ -49,7 +50,7 @@ create_contact (const struct GNUNET_IDENTITY_PublicKey *key);
49/** 50/**
50 * Destroys a contact and frees its memory fully. 51 * Destroys a contact and frees its memory fully.
51 * 52 *
52 * @param contact Contact 53 * @param[in/out] contact Contact
53 */ 54 */
54void 55void
55destroy_contact (struct GNUNET_MESSENGER_Contact *contact); 56destroy_contact (struct GNUNET_MESSENGER_Contact *contact);
@@ -57,7 +58,7 @@ destroy_contact (struct GNUNET_MESSENGER_Contact *contact);
57/** 58/**
58 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet. 59 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet.
59 * 60 *
60 * @param contact Contact 61 * @param[in] contact Contact
61 * @return Name of the contact or NULL 62 * @return Name of the contact or NULL
62 */ 63 */
63const char* 64const char*
@@ -66,8 +67,8 @@ get_contact_name (const struct GNUNET_MESSENGER_Contact *contact);
66/** 67/**
67 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>. 68 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>.
68 * 69 *
69 * @param contact Contact 70 * @param[in/out] contact Contact
70 * @param name Valid name (may not be NULL!) 71 * @param[in] name Name
71 */ 72 */
72void 73void
73set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name); 74set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name);
@@ -75,19 +76,39 @@ set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name);
75/** 76/**
76 * Returns the public key of a given <i>contact</i>. 77 * Returns the public key of a given <i>contact</i>.
77 * 78 *
78 * @param contact Contact 79 * @param[in] contact Contact
79 * @return Public key of the contact 80 * @return Public key of the contact
80 */ 81 */
81const struct GNUNET_IDENTITY_PublicKey* 82const struct GNUNET_IDENTITY_PublicKey*
82get_contact_key (const struct GNUNET_MESSENGER_Contact *contact); 83get_contact_key (const struct GNUNET_MESSENGER_Contact *contact);
83 84
84/** 85/**
85 * Returns the resulting hashcode of the public key from a given <i>contact</i>. 86 * Increases the reference counter of a given <i>contact</i> which is zero as default.
86 * 87 *
87 * @param contact Contact 88 * @param[in/out] contact Contact
88 * @return Hash of the contacts public key
89 */ 89 */
90const struct GNUNET_HashCode* 90void
91get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact); 91increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
92
93/**
94 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
95 * and returns #GNUNET_YES if the counter is equal to zero, otherwise #GNUNET_NO.
96 *
97 * @param[in/out] contact Contact
98 * @return #GNUNET_YES or #GNUNET_NO depending on the reference counter
99 */
100int
101decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
102
103/**
104 * Calculates the context <i>hash</i> of a member in a room and returns it.
105 *
106 * @param[in] key Key of room
107 * @param[in] id Member id
108 * @param[out] hash Member context
109 */
110void
111get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
112 struct GNUNET_HashCode *context);
92 113
93#endif //GNUNET_MESSENGER_API_CONTACT_H 114#endif //GNUNET_MESSENGER_API_CONTACT_H
diff --git a/src/messenger/messenger_api_contact_store.c b/src/messenger/messenger_api_contact_store.c
new file mode 100644
index 000000000..5238b2c58
--- /dev/null
+++ b/src/messenger/messenger_api_contact_store.c
@@ -0,0 +1,182 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/messenger_api_contact_store.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_contact_store.h"
27
28#include "messenger_api_contact.h"
29#include "messenger_api_util.h"
30
31void
32init_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
33{
34 GNUNET_assert (store);
35
36 store->anonymous = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
37 store->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Contact *contact = value;
44 destroy_contact (contact);
45 return GNUNET_YES;
46}
47
48void
49clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
50{
51 GNUNET_assert ((store) && (store->contacts));
52
53 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
54 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
55
56 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
57 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
58}
59
60static struct GNUNET_CONTAINER_MultiHashMap*
61select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
62 struct GNUNET_HashCode *hash)
63{
64 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
65
66 struct GNUNET_HashCode anonHash;
67 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
68
69 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
70 {
71 GNUNET_memcpy(hash, context, sizeof(*context));
72 return store->anonymous;
73 }
74 else
75 return store->contacts;
76}
77
78struct GNUNET_MESSENGER_Contact*
79get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
80 const struct GNUNET_HashCode *key_hash)
81{
82 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
83
84 struct GNUNET_HashCode hash;
85 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
86
87 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
88 store, context, &hash
89 );
90
91 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
92}
93
94struct GNUNET_MESSENGER_Contact*
95get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
96 const struct GNUNET_IDENTITY_PublicKey *pubkey)
97{
98 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
99
100 struct GNUNET_HashCode hash;
101 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
102
103 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
104 store, context, &hash
105 );
106
107 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
108
109 if (contact)
110 {
111 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
112 {
113 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
114 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
115 GNUNET_free (str);
116 return NULL;
117 }
118
119 return contact;
120 }
121
122 contact = create_contact (pubkey);
123
124 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
126 return contact;
127
128 destroy_contact (contact);
129 return NULL;
130}
131
132void
133update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
134 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
135 const struct GNUNET_IDENTITY_PublicKey *pubkey)
136{
137 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
138
139 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
140
141 struct GNUNET_HashCode hash;
142 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
143
144 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
145 store, context, &hash
146 );
147
148 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
149 {
150 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
151
152 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
153
154 map = select_store_contact_map (
155 store, next_context, &hash
156 );
157
158 GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
159 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
160 }
161}
162
163void
164remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
165 const struct GNUNET_HashCode *context)
166{
167 GNUNET_assert ((store) && (store->contacts) && (contact));
168
169 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
170
171 struct GNUNET_HashCode hash;
172 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
173
174 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
175 store, context, &hash
176 );
177
178 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
179 return;
180
181 destroy_contact (contact);
182}
diff --git a/src/messenger/messenger_api_contact_store.h b/src/messenger/messenger_api_contact_store.h
new file mode 100644
index 000000000..966f6d962
--- /dev/null
+++ b/src/messenger/messenger_api_contact_store.h
@@ -0,0 +1,122 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 src/messenger/messenger_api_contact_store.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_CONTACT_STORE_H
27#define GNUNET_MESSENGER_API_CONTACT_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h"
33
34struct GNUNET_MESSENGER_Contact;
35
36struct GNUNET_MESSENGER_ContactStore
37{
38 struct GNUNET_CONTAINER_MultiHashMap *anonymous;
39 struct GNUNET_CONTAINER_MultiHashMap *contacts;
40};
41
42/**
43 * Initializes a contact store as fully empty.
44 *
45 * @param[out] store Contact store
46 */
47void
48init_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
49
50/**
51 * Clears a contact store, wipes its content and deallocates its memory.
52 *
53 * @param[in/out] store Contact store
54 */
55void
56clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
57
58/**
59 * Returns a contact using the hash of a specific public key. In case the anonymous
60 * key gets used by the requested contact, it will use its provided member
61 * <i>context</i> to select the matching contact from the <i>store</i>.
62 *
63 * In case there is no contact stored which uses the given key or context,
64 * NULL gets returned.
65 *
66 * @param[in/out] store Contact store
67 * @param[in] context Member context
68 * @param[in] key_hash Hash of public key
69 */
70struct GNUNET_MESSENGER_Contact*
71get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
72 const struct GNUNET_HashCode *key_hash);
73
74/**
75 * Returns a contact using a specific public key. In case the anonymous
76 * key gets used by the requested contact, it will use its provided member
77 * <i>context</i> to select the matching contact from the <i>store</i>.
78 *
79 * In case there is no contact stored which uses the given key or context,
80 * a new contact will be created automatically.
81 *
82 * The function returns NULL if an error occures during allocation
83 * or validation of the contacts key.
84 *
85 * @param[in/out] store Contact store
86 * @param[in] context Member context
87 * @param[in] pubkey Public key of EGO
88 */
89struct GNUNET_MESSENGER_Contact*
90get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
91 const struct GNUNET_IDENTITY_PublicKey *pubkey);
92
93/**
94 * Moves a <i>contact</i> from the <i>store</i> to another location
95 * matching a given public key and member <i>context</i>.
96 *
97 * This function allows changes of keys or changes of member contexts!
98 *
99 * @param[in/out] store Contact store
100 * @param[in/out] contact Contact
101 * @param[in] context Member context
102 * @param[in] next_context Member context
103 * @param[in] pubkey Public key of EGO
104 */
105void
106update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
107 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
108 const struct GNUNET_IDENTITY_PublicKey *pubkey);
109
110/**
111 * Removes a <i>contact</i> from the <i>store</i> which uses
112 * a given member <i>context</i>.
113 *
114 * @param[in/out] store Contact store
115 * @param[in/out] contact Contact
116 * @param[in] context Member context
117 */
118void
119remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
120 const struct GNUNET_HashCode *context);
121
122#endif //GNUNET_MESSENGER_API_CONTACT_STORE_H
diff --git a/src/messenger/messenger_api_ego.h b/src/messenger/messenger_api_ego.h
index c60eeac50..b52b895f2 100644
--- a/src/messenger/messenger_api_ego.h
+++ b/src/messenger/messenger_api_ego.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
diff --git a/src/messenger/messenger_api_handle.c b/src/messenger/messenger_api_handle.c
index 20ef77254..ab57f82cc 100644
--- a/src/messenger/messenger_api_handle.c
+++ b/src/messenger/messenger_api_handle.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -25,10 +25,14 @@
25 25
26#include "messenger_api_handle.h" 26#include "messenger_api_handle.h"
27 27
28#include "messenger_api_util.h"
29
28struct GNUNET_MESSENGER_Handle* 30struct GNUNET_MESSENGER_Handle*
29create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback, 31create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback,
30 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls) 32 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls)
31{ 33{
34 GNUNET_assert(cfg);
35
32 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle); 36 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle);
33 37
34 handle->cfg = cfg; 38 handle->cfg = cfg;
@@ -47,7 +51,8 @@ create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_I
47 handle->reconnect_task = NULL; 51 handle->reconnect_task = NULL;
48 52
49 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 53 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
50 handle->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 54
55 init_contact_store(get_handle_contact_store(handle));
51 56
52 return handle; 57 return handle;
53} 58}
@@ -62,19 +67,11 @@ iterate_destroy_room (void *cls, const struct GNUNET_HashCode *key, void *value)
62 return GNUNET_YES; 67 return GNUNET_YES;
63} 68}
64 69
65static int
66iterate_destroy_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
67{
68 struct GNUNET_MESSENGER_Contact *contact = value;
69
70 destroy_contact (contact);
71
72 return GNUNET_YES;
73}
74
75void 70void
76destroy_handle (struct GNUNET_MESSENGER_Handle *handle) 71destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
77{ 72{
73 GNUNET_assert(handle);
74
78 if (handle->reconnect_task) 75 if (handle->reconnect_task)
79 GNUNET_SCHEDULER_cancel (handle->reconnect_task); 76 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
80 77
@@ -94,12 +91,7 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
94 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms); 91 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms);
95 } 92 }
96 93
97 if (handle->contacts) 94 clear_contact_store(get_handle_contact_store(handle));
98 {
99 GNUNET_CONTAINER_multihashmap_iterate (handle->contacts, iterate_destroy_contact, NULL);
100
101 GNUNET_CONTAINER_multihashmap_destroy (handle->contacts);
102 }
103 95
104 GNUNET_free(handle->name); 96 GNUNET_free(handle->name);
105} 97}
@@ -107,21 +99,27 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
107void 99void
108set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name) 100set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name)
109{ 101{
102 GNUNET_assert(handle);
103
110 if (handle->name) 104 if (handle->name)
111 GNUNET_free(handle->name); 105 GNUNET_free(handle->name);
112 106
113 handle->name = name? GNUNET_strdup(name) : NULL; 107 handle->name = name ? GNUNET_strdup(name) : NULL;
114} 108}
115 109
116const char* 110const char*
117get_handle_name (const struct GNUNET_MESSENGER_Handle *handle) 111get_handle_name (const struct GNUNET_MESSENGER_Handle *handle)
118{ 112{
113 GNUNET_assert(handle);
114
119 return handle->name; 115 return handle->name;
120} 116}
121 117
122void 118void
123set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey) 119set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey)
124{ 120{
121 GNUNET_assert(handle);
122
125 if (!handle->pubkey) 123 if (!handle->pubkey)
126 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey); 124 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
127 125
@@ -131,62 +129,43 @@ set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDEN
131const struct GNUNET_IDENTITY_PublicKey* 129const struct GNUNET_IDENTITY_PublicKey*
132get_handle_key (const struct GNUNET_MESSENGER_Handle *handle) 130get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
133{ 131{
134 if (!handle->pubkey) 132 GNUNET_assert(handle);
135 {
136 struct GNUNET_IDENTITY_Ego *anonymous = GNUNET_IDENTITY_ego_get_anonymous ();
137 static struct GNUNET_IDENTITY_PublicKey pubkey;
138 133
139 GNUNET_IDENTITY_ego_get_public_key (anonymous, &pubkey); 134 if (handle->pubkey)
140 135 return handle->pubkey;
141 return &pubkey;
142 }
143 136
144 return handle->pubkey; 137 return get_anonymous_public_key ();
145} 138}
146 139
147struct GNUNET_MESSENGER_Contact* 140struct GNUNET_MESSENGER_ContactStore*
148get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, 141get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle)
149 const struct GNUNET_IDENTITY_PublicKey *pubkey)
150{ 142{
151 struct GNUNET_HashCode hash; 143 GNUNET_assert(handle);
152
153 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
154
155 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (handle->contacts, &hash);
156
157 if (contact)
158 return contact;
159
160 contact = create_contact (pubkey);
161
162 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (handle->contacts, &hash, contact,
163 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
164 return contact;
165 144
166 destroy_contact (contact); 145 return &(handle->contact_store);
167 return NULL;
168} 146}
169 147
170void 148struct GNUNET_MESSENGER_Contact*
171swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, 149get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
172 const struct GNUNET_IDENTITY_PublicKey *pubkey)
173{ 150{
174 const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact); 151 GNUNET_assert((handle) && (key));
175 152
176 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->contacts, hash, contact)) 153 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
177 {
178 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
179 154
180 hash = get_contact_id_from_key (contact); 155 if ((!room) || (!(room->contact_id)))
156 return NULL;
181 157
182 GNUNET_CONTAINER_multihashmap_put (handle->contacts, hash, contact, 158 struct GNUNET_HashCode context;
183 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 159 get_context_from_member (key, room->contact_id, &context);
184 } 160
161 return get_store_contact(get_handle_contact_store(handle), &context, get_handle_key(handle));
185} 162}
186 163
187void 164void
188open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 165open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
189{ 166{
167 GNUNET_assert((handle) && (key));
168
190 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 169 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
191 170
192 if (room) 171 if (room)
@@ -197,6 +176,8 @@ void
197entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 176entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
198 const struct GNUNET_HashCode *key) 177 const struct GNUNET_HashCode *key)
199{ 178{
179 GNUNET_assert((handle) && (door) && (key));
180
200 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 181 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
201 182
202 if (room) 183 if (room)
@@ -206,6 +187,8 @@ entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNE
206void 187void
207close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 188close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
208{ 189{
190 GNUNET_assert((handle) && (key));
191
209 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); 192 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
210 193
211 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room))) 194 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room)))
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h
index d6cde0106..e6ca474f2 100644
--- a/src/messenger/messenger_api_handle.h
+++ b/src/messenger/messenger_api_handle.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -35,7 +35,7 @@
35 35
36#include "gnunet_messenger_service.h" 36#include "gnunet_messenger_service.h"
37 37
38#include "messenger_api_contact.h" 38#include "messenger_api_contact_store.h"
39#include "messenger_api_room.h" 39#include "messenger_api_room.h"
40 40
41struct GNUNET_MESSENGER_Handle 41struct GNUNET_MESSENGER_Handle
@@ -56,17 +56,18 @@ struct GNUNET_MESSENGER_Handle
56 struct GNUNET_TIME_Relative reconnect_time; 56 struct GNUNET_TIME_Relative reconnect_time;
57 struct GNUNET_SCHEDULER_Task *reconnect_task; 57 struct GNUNET_SCHEDULER_Task *reconnect_task;
58 58
59 struct GNUNET_MESSENGER_ContactStore contact_store;
60
59 struct GNUNET_CONTAINER_MultiHashMap *rooms; 61 struct GNUNET_CONTAINER_MultiHashMap *rooms;
60 struct GNUNET_CONTAINER_MultiHashMap *contacts;
61}; 62};
62 63
63/** 64/**
64 * Creates and allocates a new handle using a given configuration and a custom message callback 65 * Creates and allocates a new handle using a given configuration and a custom message callback
65 * with a given closure for the client API. 66 * with a given closure for the client API.
66 * 67 *
67 * @param cfg Configuration 68 * @param[in] cfg Configuration
68 * @param msg_callback Message callback 69 * @param[in] msg_callback Message callback
69 * @param msg_cls Closure 70 * @param[in/out] msg_cls Closure
70 * @return New handle 71 * @return New handle
71 */ 72 */
72struct GNUNET_MESSENGER_Handle* 73struct GNUNET_MESSENGER_Handle*
@@ -76,7 +77,7 @@ create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_I
76/** 77/**
77 * Destroys a <i>handle</i> and frees its memory fully from the client API. 78 * Destroys a <i>handle</i> and frees its memory fully from the client API.
78 * 79 *
79 * @param handle Handle 80 * @param[in/out] handle Handle
80 */ 81 */
81void 82void
82destroy_handle (struct GNUNET_MESSENGER_Handle *handle); 83destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
@@ -84,8 +85,8 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
84/** 85/**
85 * Sets the name of a <i>handle</i> to a specific <i>name</i>. 86 * Sets the name of a <i>handle</i> to a specific <i>name</i>.
86 * 87 *
87 * @param handle Handle 88 * @param[in/out] handle Handle
88 * @param name New name 89 * @param[in] name New name
89 */ 90 */
90void 91void
91set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); 92set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
@@ -93,7 +94,7 @@ set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
93/** 94/**
94 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet. 95 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet.
95 * 96 *
96 * @param handle Handle 97 * @param[in] handle Handle
97 * @return Name of the handle or NULL 98 * @return Name of the handle or NULL
98 */ 99 */
99const char* 100const char*
@@ -102,8 +103,8 @@ get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
102/** 103/**
103 * Sets the public key of a given <i>handle</i> to a specific public key. 104 * Sets the public key of a given <i>handle</i> to a specific public key.
104 * 105 *
105 * @param handle Handle 106 * @param[in/out] handle Handle
106 * @param pubkey Public key 107 * @param[in] pubkey Public key
107 */ 108 */
108void 109void
109set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey); 110set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey);
@@ -111,41 +112,37 @@ set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDEN
111/** 112/**
112 * Returns the public key of a given <i>handle</i>. 113 * Returns the public key of a given <i>handle</i>.
113 * 114 *
114 * @param handle Handle 115 * @param[in] handle Handle
115 * @return Public key of the handle 116 * @return Public key of the handle
116 */ 117 */
117const struct GNUNET_IDENTITY_PublicKey* 118const struct GNUNET_IDENTITY_PublicKey*
118get_handle_key (const struct GNUNET_MESSENGER_Handle *handle); 119get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
119 120
120/** 121/**
121 * Returns a contact known to a <i>handle</i> identified by a given public key. If not matching 122 * Returns the used contact store of a given <i>handle</i>.
122 * contact is found, NULL gets returned.
123 * 123 *
124 * @param handle Handle 124 * @param[in/out] handle Handle
125 * @param pubkey Public key of EGO 125 * @return Contact store
126 * @return Contact or NULL
127 */ 126 */
128struct GNUNET_MESSENGER_Contact* 127struct GNUNET_MESSENGER_ContactStore*
129get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, 128get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle);
130 const struct GNUNET_IDENTITY_PublicKey *pubkey);
131 129
132/** 130/**
133 * Changes the public key for a <i>contact</i> known to a <i>handle</i> to a specific public key and 131 * Returns the contact of a given <i>handle</i> in a room identified by a
134 * updates local map entries to access the contact by its updated key. 132 * given <i>key</i>.
135 * 133 *
136 * @param handle Handle 134 * @param[in/out] handle Handle
137 * @param contact Contact 135 * @param[in] key Key of room
138 * @param pubkey Public key of EGO 136 * @return Contact
139 */ 137 */
140void 138struct GNUNET_MESSENGER_Contact*
141swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, 139get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
142 const struct GNUNET_IDENTITY_PublicKey *pubkey);
143 140
144/** 141/**
145 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open. 142 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open.
146 * 143 *
147 * @param handle Handle 144 * @param[in/out] handle Handle
148 * @param key Key of room 145 * @param[in] key Key of room
149 */ 146 */
150void 147void
151open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 148open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
@@ -154,9 +151,9 @@ open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_Ha
154 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a 151 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a
155 * list of opened connections. 152 * list of opened connections.
156 * 153 *
157 * @param handle Handle 154 * @param[in/out] handle Handle
158 * @param door Peer identity 155 * @param[in] door Peer identity
159 * @param key Key of room 156 * @param[in] key Key of room
160 */ 157 */
161void 158void
162entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, 159entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
@@ -165,8 +162,8 @@ entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNE
165/** 162/**
166 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>. 163 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>.
167 * 164 *
168 * @param handle Handle 165 * @param[in/out] handle Handle
169 * @param key Key of room 166 * @param[in] key Key of room
170 */ 167 */
171void 168void
172close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); 169close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
diff --git a/src/messenger/messenger_api_list_tunnels.c b/src/messenger/messenger_api_list_tunnels.c
index 13d8c1906..990e36878 100644
--- a/src/messenger/messenger_api_list_tunnels.c
+++ b/src/messenger/messenger_api_list_tunnels.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -62,6 +62,8 @@ compare_list_tunnels (void *cls, struct GNUNET_MESSENGER_ListTunnel *element0,
62void 62void
63add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) 63add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
64{ 64{
65 GNUNET_assert((tunnels) && (peer));
66
65 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel); 67 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel);
66 68
67 element->peer = GNUNET_PEER_intern (peer); 69 element->peer = GNUNET_PEER_intern (peer);
@@ -73,6 +75,8 @@ add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct
73struct GNUNET_MESSENGER_ListTunnel* 75struct GNUNET_MESSENGER_ListTunnel*
74find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index) 76find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index)
75{ 77{
78 GNUNET_assert((tunnels) && (peer));
79
76 struct GNUNET_MESSENGER_ListTunnel *element; 80 struct GNUNET_MESSENGER_ListTunnel *element;
77 struct GNUNET_PeerIdentity pid; 81 struct GNUNET_PeerIdentity pid;
78 82
@@ -96,12 +100,16 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GN
96int 100int
97contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) 101contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
98{ 102{
103 GNUNET_assert((tunnels) && (peer));
104
99 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO; 105 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO;
100} 106}
101 107
102struct GNUNET_MESSENGER_ListTunnel* 108struct GNUNET_MESSENGER_ListTunnel*
103remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element) 109remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element)
104{ 110{
111 GNUNET_assert((tunnels) && (element));
112
105 struct GNUNET_MESSENGER_ListTunnel *next = element->next; 113 struct GNUNET_MESSENGER_ListTunnel *next = element->next;
106 114
107 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element); 115 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
@@ -110,3 +118,67 @@ remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct G
110 118
111 return next; 119 return next;
112} 120}
121
122void
123load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
124{
125 GNUNET_assert((tunnels) && (path));
126
127 if (GNUNET_YES != GNUNET_DISK_file_test (path))
128 return;
129
130 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
131
132 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
133 path, GNUNET_DISK_OPEN_READ, permission
134 );
135
136 if (!handle)
137 return;
138
139 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
140
141 struct GNUNET_PeerIdentity peer;
142 ssize_t len;
143
144 do {
145 len = GNUNET_DISK_file_read(handle, &peer, sizeof(peer));
146
147 if (len != sizeof(peer))
148 break;
149
150 add_to_list_tunnels(tunnels, &peer);
151 } while (len == sizeof(peer));
152
153 GNUNET_DISK_file_close(handle);
154}
155
156void
157save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
158{
159 GNUNET_assert((tunnels) && (path));
160
161 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
162
163 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
164 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
165 );
166
167 if (!handle)
168 return;
169
170 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
171
172 struct GNUNET_MESSENGER_ListTunnel *element;
173 struct GNUNET_PeerIdentity pid;
174
175 for (element = tunnels->head; element; element = element->next)
176 {
177 GNUNET_PEER_resolve (element->peer, &pid);
178
179 GNUNET_DISK_file_write(handle, &pid, sizeof(pid));
180 }
181
182 GNUNET_DISK_file_sync(handle);
183 GNUNET_DISK_file_close(handle);
184}
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h
index 0240fceb8..bd0a42e41 100644
--- a/src/messenger/messenger_api_list_tunnels.h
+++ b/src/messenger/messenger_api_list_tunnels.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -47,7 +47,7 @@ struct GNUNET_MESSENGER_ListTunnels
47/** 47/**
48 * Initializes list of tunnels peer identities as empty list. 48 * Initializes list of tunnels peer identities as empty list.
49 * 49 *
50 * @param tunnels List of peer identities 50 * @param[out] tunnels List of peer identities
51 */ 51 */
52void 52void
53init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); 53init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
@@ -55,7 +55,7 @@ init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
55/** 55/**
56 * Clears the list of tunnels peer identities. 56 * Clears the list of tunnels peer identities.
57 * 57 *
58 * @param tunnels List of peer identities 58 * @param[in/out] tunnels List of peer identities
59 */ 59 */
60void 60void
61clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); 61clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
@@ -63,8 +63,8 @@ clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
63/** 63/**
64 * Adds a specific <i>peer</i> from a tunnel to the end of the list. 64 * Adds a specific <i>peer</i> from a tunnel to the end of the list.
65 * 65 *
66 * @param tunnels List of peer identities 66 * @param[in/out] tunnels List of peer identities
67 * @param peer Peer identity of tunnel 67 * @param[in] peer Peer identity of tunnel
68 */ 68 */
69void 69void
70add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); 70add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
@@ -79,8 +79,8 @@ add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct
79 * the found element in the list. If no matching element is found, <i>index</i> will 79 * the found element in the list. If no matching element is found, <i>index</i> will
80 * contain the total amount of elements in the list. 80 * contain the total amount of elements in the list.
81 * 81 *
82 * @param tunnels List of peer identities 82 * @param[in/out] tunnels List of peer identities
83 * @param peer Peer identity of tunnel 83 * @param[in] peer Peer identity of tunnel
84 * @param[out] index Index of found element (optional) 84 * @param[out] index Index of found element (optional)
85 * @return Element in the list with matching peer identity 85 * @return Element in the list with matching peer identity
86 */ 86 */
@@ -89,11 +89,11 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GN
89 89
90/** 90/**
91 * Tests linearly if the list of tunnels peer identities contains a specific 91 * Tests linearly if the list of tunnels peer identities contains a specific
92 * <i>peer</i> identity and returns GNUNET_YES on success, otherwise GNUNET_NO. 92 * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise #GNUNET_NO.
93 * 93 *
94 * @param tunnels List of peer identities 94 * @param[in/out] tunnels List of peer identities
95 * @param peer Peer identity of tunnel 95 * @param[in] peer Peer identity of tunnel
96 * @return GNUNET_YES on success, otherwise GNUNET_NO 96 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
97 */ 97 */
98int 98int
99contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); 99contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
@@ -102,11 +102,29 @@ contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struc
102 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns 102 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns
103 * the next element in the list. 103 * the next element in the list.
104 * 104 *
105 * @param tunnels List of peer identities 105 * @param[in/out] tunnels List of peer identities
106 * @param element Element of the list 106 * @param[in/out] element Element of the list
107 * @return Next element in the list 107 * @return Next element in the list
108 */ 108 */
109struct GNUNET_MESSENGER_ListTunnel* 109struct GNUNET_MESSENGER_ListTunnel*
110remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element); 110remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element);
111 111
112/**
113 * Loads the list of tunnels peer identities from a file under a given <i>path</i>.
114 *
115 * @param[out] messages List of hashes
116 * @param[in] path Path of file
117 */
118void
119load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
120
121/**
122 * Saves the list of tunnels peer identities to a file under a given <i>path</i>.
123 *
124 * @param[in] messages List of hashes
125 * @param[in] path Path of file
126 */
127void
128save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
129
112#endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H 130#endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
index fdab60eef..d88859186 100644
--- a/src/messenger/messenger_api_message.c
+++ b/src/messenger/messenger_api_message.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -69,6 +69,8 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind)
69struct GNUNET_MESSENGER_Message* 69struct GNUNET_MESSENGER_Message*
70copy_message (const struct GNUNET_MESSENGER_Message *message) 70copy_message (const struct GNUNET_MESSENGER_Message *message)
71{ 71{
72 GNUNET_assert(message);
73
72 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); 74 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
73 75
74 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); 76 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
@@ -125,11 +127,28 @@ destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESS
125void 127void
126destroy_message (struct GNUNET_MESSENGER_Message *message) 128destroy_message (struct GNUNET_MESSENGER_Message *message)
127{ 129{
130 GNUNET_assert(message);
131
128 destroy_message_body (message->header.kind, &(message->body)); 132 destroy_message_body (message->header.kind, &(message->body));
129 133
130 GNUNET_free(message); 134 GNUNET_free(message);
131} 135}
132 136
137int
138is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
139{
140 GNUNET_assert(message);
141
142 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
143 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
144 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
145 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
146 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
147 return GNUNET_YES;
148 else
149 return GNUNET_NO;
150}
151
133static void 152static void
134fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) 153fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened)
135{ 154{
@@ -158,18 +177,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
158 switch (kind) 177 switch (kind)
159 { 178 {
160 case GNUNET_MESSENGER_KIND_INFO: 179 case GNUNET_MESSENGER_KIND_INFO:
161 length += member_size(struct GNUNET_MESSENGER_Message, body.info.host_key); 180 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
162 length += member_size(struct GNUNET_MESSENGER_Message, body.info.unique_id);
163 break;
164 case GNUNET_MESSENGER_KIND_JOIN:
165 length += member_size(struct GNUNET_MESSENGER_Message, body.join.key);
166 break;
167 case GNUNET_MESSENGER_KIND_LEAVE:
168 break;
169 case GNUNET_MESSENGER_KIND_NAME:
170 break;
171 case GNUNET_MESSENGER_KIND_KEY:
172 length += member_size(struct GNUNET_MESSENGER_Message, body.key.key);
173 break; 181 break;
174 case GNUNET_MESSENGER_KIND_PEER: 182 case GNUNET_MESSENGER_KIND_PEER:
175 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); 183 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
@@ -195,7 +203,7 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
195 case GNUNET_MESSENGER_KIND_FILE: 203 case GNUNET_MESSENGER_KIND_FILE:
196 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); 204 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
197 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); 205 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
198 length += NAME_MAX; 206 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
199 break; 207 break;
200 case GNUNET_MESSENGER_KIND_PRIVATE: 208 case GNUNET_MESSENGER_KIND_PRIVATE:
201 length += member_size(struct GNUNET_MESSENGER_Message, body.private.key); 209 length += member_size(struct GNUNET_MESSENGER_Message, body.private.key);
@@ -207,16 +215,17 @@ get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
207 return length; 215 return length;
208} 216}
209 217
218typedef uint32_t kind_t;
219
210uint16_t 220uint16_t
211get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) 221get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
212{ 222{
213 uint16_t length = 0; 223 uint16_t length = 0;
214 224
215 length += member_size(struct GNUNET_MESSENGER_Message, header.signature);
216 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); 225 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
217 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); 226 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
218 length += member_size(struct GNUNET_MESSENGER_Message, header.previous); 227 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
219 length += member_size(struct GNUNET_MESSENGER_Message, header.kind); 228 length += sizeof(kind_t);
220 229
221 return length + get_message_body_kind_size (kind); 230 return length + get_message_body_kind_size (kind);
222} 231}
@@ -228,8 +237,17 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN
228 237
229 switch (kind) 238 switch (kind)
230 { 239 {
240 case GNUNET_MESSENGER_KIND_INFO:
241 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
242 break;
243 case GNUNET_MESSENGER_KIND_JOIN:
244 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
245 break;
231 case GNUNET_MESSENGER_KIND_NAME: 246 case GNUNET_MESSENGER_KIND_NAME:
232 length += (body->name.name? strlen (body->name.name) : 0); 247 length += (body->name.name ? strlen (body->name.name) : 0);
248 break;
249 case GNUNET_MESSENGER_KIND_KEY:
250 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
233 break; 251 break;
234 case GNUNET_MESSENGER_KIND_TEXT: 252 case GNUNET_MESSENGER_KIND_TEXT:
235 length += strlen (body->text.text); 253 length += strlen (body->text.text);
@@ -248,19 +266,76 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUN
248} 266}
249 267
250uint16_t 268uint16_t
251get_message_size (const struct GNUNET_MESSENGER_Message *message) 269get_message_size (const struct GNUNET_MESSENGER_Message *message,
270 int include_signature)
252{ 271{
253 return get_message_kind_size (message->header.kind) + get_message_body_size (message->header.kind, &(message->body)); 272 GNUNET_assert(message);
273
274 uint16_t length = 0;
275
276 if (GNUNET_YES == include_signature)
277 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
278
279 length += get_message_kind_size (message->header.kind);
280 length += get_message_body_size (message->header.kind, &(message->body));
281
282 return length;
254} 283}
255 284
256static uint16_t 285static uint16_t
257get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) 286get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message, int include_body)
258{ 287{
288 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
289
259 if (message) 290 if (message)
260 return sizeof(message->kind) + get_message_body_kind_size (message->kind) 291 return minimum_size + get_message_body_kind_size (message->kind)
261 + get_message_body_size (message->kind, &(message->body)); 292 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
262 else 293 else
263 return sizeof(message->kind); 294 return minimum_size;
295}
296
297static uint16_t
298calc_usual_padding ()
299{
300 uint16_t padding = 0;
301 uint16_t kind_size;
302
303 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
304 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i);
305
306 if (kind_size > padding)
307 padding = kind_size;
308 }
309
310 return padding + GNUNET_MESSENGER_PADDING_MIN;
311}
312
313#define max(x, y) (x > y? x : y)
314
315static uint16_t
316calc_padded_length (uint16_t length)
317{
318 static uint16_t usual_padding = 0;
319
320 if (!usual_padding)
321 usual_padding = calc_usual_padding();
322
323 const uint16_t padded_length = max(
324 length + GNUNET_MESSENGER_PADDING_MIN,
325 usual_padding
326 );
327
328 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
329 return GNUNET_MESSENGER_PADDING_LEVEL0;
330
331 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
332 return GNUNET_MESSENGER_PADDING_LEVEL1;
333
334 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
335 return GNUNET_MESSENGER_PADDING_LEVEL2;
336
337 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
338
264} 339}
265 340
266#define min(x, y) (x < y? x : y) 341#define min(x, y) (x < y? x : y)
@@ -272,7 +347,27 @@ get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message)
272 347
273#define encode_step(dst, offset, src) do { \ 348#define encode_step(dst, offset, src) do { \
274 encode_step_ext(dst, offset, src, sizeof(*src)); \ 349 encode_step_ext(dst, offset, src, sizeof(*src)); \
275} while(0) 350} while (0)
351
352#define encode_step_key(dst, offset, src, length) do { \
353 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
354 src, dst + offset, length - offset \
355 ); \
356 if (result < 0) \
357 GNUNET_break (0); \
358 else \
359 offset += result; \
360} while (0)
361
362#define encode_step_signature(dst, offset, src, length) do { \
363 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
364 src, dst + offset, length - offset \
365 ); \
366 if (result < 0) \
367 GNUNET_break (0); \
368 else \
369 offset += result; \
370} while (0)
276 371
277static void 372static void
278encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, 373encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body,
@@ -281,20 +376,18 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
281 switch (kind) 376 switch (kind)
282 { 377 {
283 case GNUNET_MESSENGER_KIND_INFO: 378 case GNUNET_MESSENGER_KIND_INFO:
284 encode_step(buffer, offset, &(body->info.host_key)); 379 encode_step_key(buffer, offset, &(body->info.host_key), length);
285 encode_step(buffer, offset, &(body->info.unique_id)); 380 encode_step(buffer, offset, &(body->info.messenger_version));
286 break; 381 break;
287 case GNUNET_MESSENGER_KIND_JOIN: 382 case GNUNET_MESSENGER_KIND_JOIN:
288 encode_step(buffer, offset, &(body->join.key)); 383 encode_step_key(buffer, offset, &(body->join.key), length);
289 break;
290 case GNUNET_MESSENGER_KIND_LEAVE:
291 break; 384 break;
292 case GNUNET_MESSENGER_KIND_NAME: 385 case GNUNET_MESSENGER_KIND_NAME:
293 if (body->name.name) 386 if (body->name.name)
294 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); 387 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
295 break; 388 break;
296 case GNUNET_MESSENGER_KIND_KEY: 389 case GNUNET_MESSENGER_KIND_KEY:
297 encode_step(buffer, offset, &(body->key.key)); 390 encode_step_key(buffer, offset, &(body->key.key), length);
298 break; 391 break;
299 case GNUNET_MESSENGER_KIND_PEER: 392 case GNUNET_MESSENGER_KIND_PEER:
300 encode_step(buffer, offset, &(body->peer.peer)); 393 encode_step(buffer, offset, &(body->peer.peer));
@@ -321,7 +414,7 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
321 case GNUNET_MESSENGER_KIND_FILE: 414 case GNUNET_MESSENGER_KIND_FILE:
322 encode_step(buffer, offset, &(body->file.key)); 415 encode_step(buffer, offset, &(body->file.key));
323 encode_step(buffer, offset, &(body->file.hash)); 416 encode_step(buffer, offset, &(body->file.hash));
324 encode_step_ext(buffer, offset, body->file.name, NAME_MAX); 417 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
325 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); 418 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
326 break; 419 break;
327 case GNUNET_MESSENGER_KIND_PRIVATE: 420 case GNUNET_MESSENGER_KIND_PRIVATE:
@@ -331,18 +424,40 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET
331 default: 424 default:
332 break; 425 break;
333 } 426 }
427
428 if (offset >= length)
429 return;
430
431 const uint16_t padding = length - offset;
432 const uint16_t used_padding = sizeof(padding) + sizeof(char);
433
434 GNUNET_assert(padding >= used_padding);
435
436 buffer[offset++] = '\0';
437
438 if (padding > used_padding)
439 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
440
441 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
334} 442}
335 443
336void 444void
337encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer) 445encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
446 int include_signature)
338{ 447{
448 GNUNET_assert((message) && (buffer));
449
339 uint16_t offset = 0; 450 uint16_t offset = 0;
340 451
341 encode_step(buffer, offset, &(message->header.signature)); 452 if (GNUNET_YES == include_signature)
453 encode_step_signature(buffer, offset, &(message->header.signature), length);
454
455 const kind_t kind = (kind_t) message->header.kind;
456
342 encode_step(buffer, offset, &(message->header.timestamp)); 457 encode_step(buffer, offset, &(message->header.timestamp));
343 encode_step(buffer, offset, &(message->header.sender_id)); 458 encode_step(buffer, offset, &(message->header.sender_id));
344 encode_step(buffer, offset, &(message->header.previous)); 459 encode_step(buffer, offset, &(message->header.previous));
345 encode_step(buffer, offset, &(message->header.kind)); 460 encode_step(buffer, offset, &kind);
346 461
347 encode_message_body (message->header.kind, &(message->body), length, buffer, offset); 462 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
348} 463}
@@ -350,11 +465,22 @@ encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length,
350static void 465static void
351encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) 466encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer)
352{ 467{
353 uint16_t offset = 0; 468 struct GNUNET_HashCode hash;
469 uint16_t offset = sizeof(hash);
354 470
355 encode_step(buffer, offset, &(message->kind)); 471 const kind_t kind = (kind_t) message->kind;
472
473 encode_step(buffer, offset, &kind);
356 474
357 encode_message_body (message->kind, &(message->body), length, buffer, offset); 475 encode_message_body (message->kind, &(message->body), length, buffer, offset);
476
477 GNUNET_CRYPTO_hash(
478 buffer + sizeof(hash),
479 length - sizeof(hash),
480 &hash
481 );
482
483 GNUNET_memcpy(buffer, &hash, sizeof(hash));
358} 484}
359 485
360#define decode_step_ext(src, offset, dst, size) do { \ 486#define decode_step_ext(src, offset, dst, size) do { \
@@ -372,29 +498,51 @@ encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint1
372 decode_step_ext(src, offset, dst, size); \ 498 decode_step_ext(src, offset, dst, size); \
373} while (0) 499} while (0)
374 500
375static void 501#define decode_step_key(src, offset, dst, length) do { \
502 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
503 dst, src + offset, length - offset \
504 ); \
505 if (result < 0) \
506 GNUNET_break(0); \
507 else \
508 offset += result; \
509} while (0)
510
511static uint16_t
376decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, 512decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body,
377 uint16_t length, const char *buffer, uint16_t offset) 513 uint16_t length, const char *buffer, uint16_t offset)
378{ 514{
515 uint16_t padding = 0;
516
517 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
518
519 if (padding > length - offset)
520 padding = 0;
521
522 const uint16_t end_zero = length - padding;
523
524 if ((padding) && (buffer[end_zero] != '\0'))
525 padding = 0;
526
527 length -= padding;
528
379 switch (*kind) 529 switch (*kind)
380 { 530 {
381 case GNUNET_MESSENGER_KIND_INFO: 531 case GNUNET_MESSENGER_KIND_INFO: {
382 decode_step(buffer, offset, &(body->info.host_key)); 532 decode_step_key(buffer, offset, &(body->info.host_key), length);
383 decode_step(buffer, offset, &(body->info.unique_id)); 533 decode_step(buffer, offset, &(body->info.messenger_version));
384 break; 534 break;
385 case GNUNET_MESSENGER_KIND_JOIN: 535 } case GNUNET_MESSENGER_KIND_JOIN: {
386 decode_step(buffer, offset, &(body->join.key)); 536 decode_step_key(buffer, offset, &(body->join.key), length);
387 break;
388 case GNUNET_MESSENGER_KIND_LEAVE:
389 break; 537 break;
390 case GNUNET_MESSENGER_KIND_NAME: 538 } case GNUNET_MESSENGER_KIND_NAME:
391 if (length - offset > 0) 539 if (length - offset > 0)
392 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); 540 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
393 else 541 else
394 body->name.name = NULL; 542 body->name.name = NULL;
395 break; 543 break;
396 case GNUNET_MESSENGER_KIND_KEY: 544 case GNUNET_MESSENGER_KIND_KEY:
397 decode_step(buffer, offset, &(body->key.key)); 545 decode_step_key(buffer, offset, &(body->key.key), length);
398 break; 546 break;
399 case GNUNET_MESSENGER_KIND_PEER: 547 case GNUNET_MESSENGER_KIND_PEER:
400 decode_step(buffer, offset, &(body->peer.peer)); 548 decode_step(buffer, offset, &(body->peer.peer));
@@ -421,7 +569,7 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS
421 case GNUNET_MESSENGER_KIND_FILE: 569 case GNUNET_MESSENGER_KIND_FILE:
422 decode_step(buffer, offset, &(body->file.key)); 570 decode_step(buffer, offset, &(body->file.key));
423 decode_step(buffer, offset, &(body->file.hash)); 571 decode_step(buffer, offset, &(body->file.hash));
424 decode_step_ext(buffer, offset, body->file.name, NAME_MAX); 572 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
425 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); 573 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
426 break; 574 break;
427 case GNUNET_MESSENGER_KIND_PRIVATE: 575 case GNUNET_MESSENGER_KIND_PRIVATE:
@@ -434,26 +582,51 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESS
434 *kind = GNUNET_MESSENGER_KIND_UNKNOWN; 582 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
435 break; 583 break;
436 } 584 }
585
586 return padding;
437} 587}
438 588
439int 589int
440decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer) 590decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
591 int include_signature, uint16_t *padding)
441{ 592{
593 GNUNET_assert((message) && (buffer));
594
442 uint16_t offset = 0; 595 uint16_t offset = 0;
443 596
444 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN)) 597 if (GNUNET_YES == include_signature)
598 {
599 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
600 &(message->header.signature), buffer, length - offset
601 );
602
603 if (result < 0)
604 return GNUNET_NO;
605 else
606 offset += result;
607 }
608
609 const uint16_t count = length - offset;
610
611 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN))
445 return GNUNET_NO; 612 return GNUNET_NO;
446 613
447 decode_step(buffer, offset, &(message->header.signature)); 614 kind_t kind;
615
448 decode_step(buffer, offset, &(message->header.timestamp)); 616 decode_step(buffer, offset, &(message->header.timestamp));
449 decode_step(buffer, offset, &(message->header.sender_id)); 617 decode_step(buffer, offset, &(message->header.sender_id));
450 decode_step(buffer, offset, &(message->header.previous)); 618 decode_step(buffer, offset, &(message->header.previous));
451 decode_step(buffer, offset, &(message->header.kind)); 619 decode_step(buffer, offset, &kind);
452 620
453 if (length < get_message_kind_size (message->header.kind)) 621 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) kind;
622
623 if (count < get_message_kind_size (message->header.kind))
454 return GNUNET_NO; 624 return GNUNET_NO;
455 625
456 decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); 626 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
627
628 if (padding)
629 *padding = result;
457 630
458 return GNUNET_YES; 631 return GNUNET_YES;
459} 632}
@@ -461,47 +634,80 @@ decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const
461static int 634static int
462decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) 635decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer)
463{ 636{
464 uint16_t offset = 0; 637 struct GNUNET_HashCode expected, hash;
638 uint16_t offset = sizeof(hash);
639
640 if (length < get_short_message_size (NULL, GNUNET_NO))
641 return GNUNET_NO;
642
643 GNUNET_memcpy(&hash, buffer, sizeof(hash));
644
645 GNUNET_CRYPTO_hash(
646 buffer + sizeof(hash),
647 length - sizeof(hash),
648 &expected
649 );
465 650
466 if (length < get_short_message_size (NULL)) 651 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
467 return GNUNET_NO; 652 return GNUNET_NO;
468 653
469 decode_step(buffer, offset, &(message->kind)); 654 kind_t kind;
470 655
471 if (length < get_short_message_size (message)) 656 decode_step(buffer, offset, &kind);
657
658 message->kind = (enum GNUNET_MESSENGER_MessageKind) kind;
659
660 if (length < get_short_message_size (message, GNUNET_NO))
472 return GNUNET_NO; 661 return GNUNET_NO;
473 662
474 decode_message_body (&(message->kind), &(message->body), length, buffer, offset); 663 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
475 664
665 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
666 return GNUNET_NO;
667
476 return GNUNET_YES; 668 return GNUNET_YES;
477} 669}
478 670
479void 671void
480hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash) 672hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
673 struct GNUNET_HashCode *hash)
481{ 674{
482 GNUNET_CRYPTO_hash (buffer + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), 675 GNUNET_assert((message) && (buffer) && (hash));
483 length - sizeof(struct GNUNET_CRYPTO_EcdsaSignature), hash); 676
677 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
678 &(message->header.signature)
679 );
680
681 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
484} 682}
485 683
486void 684void
487sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, 685sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
488 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego) 686 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego)
489{ 687{
688 GNUNET_assert((message) && (buffer) && (hash) && (ego));
689
490 struct GNUNET_MESSENGER_MessageSignature signature; 690 struct GNUNET_MESSENGER_MessageSignature signature;
491 691
492 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); 692 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
493 signature.purpose.size = htonl (sizeof(signature)); 693 signature.purpose.size = htonl (sizeof(signature));
494 694
495 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); 695 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
496
497 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); 696 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
498 GNUNET_memcpy(buffer, &(message->header.signature), sizeof(struct GNUNET_CRYPTO_EcdsaSignature)); 697
698 uint16_t offset = 0;
699 encode_step_signature(buffer, offset, &(message->header.signature), length);
499} 700}
500 701
501int 702int
502verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, 703verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
503 const struct GNUNET_IDENTITY_PublicKey *key) 704 const struct GNUNET_IDENTITY_PublicKey *key)
504{ 705{
706 GNUNET_assert((message) && (hash) && (key));
707
708 if (ntohl (key->type) != ntohl (message->header.signature.type))
709 return GNUNET_SYSERR;
710
505 struct GNUNET_MESSENGER_MessageSignature signature; 711 struct GNUNET_MESSENGER_MessageSignature signature;
506 712
507 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); 713 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
@@ -516,26 +722,32 @@ verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNU
516int 722int
517encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) 723encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key)
518{ 724{
725 GNUNET_assert((message) && (key));
726
519 struct GNUNET_MESSENGER_ShortMessage shortened; 727 struct GNUNET_MESSENGER_ShortMessage shortened;
520 728
521 fold_short_message (message, &shortened); 729 fold_short_message (message, &shortened);
522 730
523 const uint16_t length = get_short_message_size (&shortened); 731 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
732 const uint16_t padded_length = calc_padded_length(length);
524 733
525 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; 734 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
526 message->body.private.data = GNUNET_malloc(length); 735 message->body.private.data = GNUNET_malloc(padded_length);
736 message->body.private.length = padded_length;
527 737
528 encode_short_message (&shortened, length, message->body.private.data); 738 encode_short_message (&shortened, padded_length, message->body.private.data);
529 739
530 if (GNUNET_IDENTITY_encrypt (message->body.private.data, length, key, &(message->body.private.key), 740 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.private.data, padded_length, key,
531 message->body.private.data) 741 &(message->body.private.key),
532 == length) 742 message->body.private.data))
533 { 743 {
534 destroy_message_body (shortened.kind, &(shortened.body)); 744 destroy_message_body (shortened.kind, &(shortened.body));
535 return GNUNET_YES; 745 return GNUNET_YES;
536 } 746 }
537 else 747 else
538 { 748 {
749 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
750
539 unfold_short_message (&shortened, message); 751 unfold_short_message (&shortened, message);
540 return GNUNET_NO; 752 return GNUNET_NO;
541 } 753 }
@@ -544,18 +756,28 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_I
544int 756int
545decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) 757decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key)
546{ 758{
547 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, 759 GNUNET_assert((message) && (key));
548 message->body.private.length, key, 760
549 &(message->body.private.key), 761 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, message->body.private.length,
762 key, &(message->body.private.key),
550 message->body.private.data)) 763 message->body.private.data))
764 {
765 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
766
551 return GNUNET_NO; 767 return GNUNET_NO;
768 }
552 769
553 struct GNUNET_MESSENGER_ShortMessage shortened; 770 struct GNUNET_MESSENGER_ShortMessage shortened;
554 771
555 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data)) 772 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data))
773 {
774 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
775
556 return GNUNET_NO; 776 return GNUNET_NO;
777 }
557 778
558 unfold_short_message (&shortened, message); 779 unfold_short_message (&shortened, message);
780
559 return GNUNET_YES; 781 return GNUNET_YES;
560} 782}
561 783
@@ -563,18 +785,25 @@ struct GNUNET_MQ_Envelope*
563pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 785pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
564 const struct GNUNET_MESSENGER_Ego *ego, int mode) 786 const struct GNUNET_MESSENGER_Ego *ego, int mode)
565{ 787{
566 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message: %u\n", message->header.kind); 788 GNUNET_assert(message);
789
790 if (ego)
791 message->header.signature.type = ego->priv.type;
792
793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
794 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
567 795
568 struct GNUNET_MessageHeader *header; 796 struct GNUNET_MessageHeader *header;
569 797
570 uint16_t length = get_message_size (message); 798 const uint16_t length = get_message_size (message, GNUNET_YES);
799 const uint16_t padded_length = calc_padded_length(length);
571 800
572 struct GNUNET_MQ_Envelope *env; 801 struct GNUNET_MQ_Envelope *env;
573 char *buffer; 802 char *buffer;
574 803
575 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) 804 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
576 { 805 {
577 env = GNUNET_MQ_msg_extra(header, length, GNUNET_MESSAGE_TYPE_CADET_CLI); 806 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
578 807
579 buffer = (char*) &(header[1]); 808 buffer = (char*) &(header[1]);
580 } 809 }
@@ -582,14 +811,14 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *
582 { 811 {
583 env = NULL; 812 env = NULL;
584 813
585 buffer = GNUNET_malloc(length); 814 buffer = GNUNET_malloc(padded_length);
586 } 815 }
587 816
588 encode_message (message, length, buffer); 817 encode_message (message, padded_length, buffer, GNUNET_YES);
589 818
590 if (hash) 819 if (hash)
591 { 820 {
592 hash_message (length, buffer, hash); 821 hash_message (message, length, buffer, hash);
593 822
594 if (ego) 823 if (ego)
595 sign_message (message, length, buffer, hash, ego); 824 sign_message (message, length, buffer, hash, ego);
@@ -600,3 +829,43 @@ pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *
600 829
601 return env; 830 return env;
602} 831}
832
833int
834filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
835{
836 switch (message->header.kind)
837 {
838 case GNUNET_MESSENGER_KIND_INFO:
839 return GNUNET_SYSERR; // Reserved for connection handling only!
840 case GNUNET_MESSENGER_KIND_JOIN:
841 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
842 case GNUNET_MESSENGER_KIND_LEAVE:
843 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
844 case GNUNET_MESSENGER_KIND_NAME:
845 return GNUNET_YES;
846 case GNUNET_MESSENGER_KIND_KEY:
847 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
848 case GNUNET_MESSENGER_KIND_PEER:
849 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
850 case GNUNET_MESSENGER_KIND_ID:
851 return GNUNET_SYSERR; // Reserved for member id handling only!
852 case GNUNET_MESSENGER_KIND_MISS:
853 return GNUNET_SYSERR; // Reserved for connection handling only!
854 case GNUNET_MESSENGER_KIND_MERGE:
855 return GNUNET_YES;
856 case GNUNET_MESSENGER_KIND_REQUEST:
857 return GNUNET_YES;
858 case GNUNET_MESSENGER_KIND_INVITE:
859 return GNUNET_YES;
860 case GNUNET_MESSENGER_KIND_TEXT:
861 return GNUNET_YES;
862 case GNUNET_MESSENGER_KIND_FILE:
863 return GNUNET_YES;
864 case GNUNET_MESSENGER_KIND_PRIVATE:
865 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
866 case GNUNET_MESSENGER_KIND_DELETE:
867 return GNUNET_YES;
868 default:
869 return GNUNET_SYSERR;
870 }
871}
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h
index 0f0a97e9c..7ce30dc92 100644
--- a/src/messenger/messenger_api_message.h
+++ b/src/messenger/messenger_api_message.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -36,10 +36,17 @@
36 36
37#include "messenger_api_ego.h" 37#include "messenger_api_ego.h"
38 38
39#define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - GNUNET_MIN_MESSAGE_SIZE)
40
41#define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
42#define GNUNET_MESSENGER_PADDING_LEVEL0 (512)
43#define GNUNET_MESSENGER_PADDING_LEVEL1 (4096)
44#define GNUNET_MESSENGER_PADDING_LEVEL2 (32768)
45
39/** 46/**
40 * Creates and allocates a new message with a specific <i>kind</i>. 47 * Creates and allocates a new message with a specific <i>kind</i>.
41 * 48 *
42 * @param kind Kind of message 49 * @param[in] kind Kind of message
43 * @return New message 50 * @return New message
44 */ 51 */
45struct GNUNET_MESSENGER_Message* 52struct GNUNET_MESSENGER_Message*
@@ -48,7 +55,7 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind);
48/** 55/**
49 * Creates and allocates a copy of a given <i>message</i>. 56 * Creates and allocates a copy of a given <i>message</i>.
50 * 57 *
51 * @param message Message 58 * @param[in] message Message
52 * @return New message 59 * @return New message
53 */ 60 */
54struct GNUNET_MESSENGER_Message* 61struct GNUNET_MESSENGER_Message*
@@ -57,15 +64,24 @@ copy_message (const struct GNUNET_MESSENGER_Message *message);
57/** 64/**
58 * Destroys a message and frees its memory fully. 65 * Destroys a message and frees its memory fully.
59 * 66 *
60 * @param message Message 67 * @param[in/out] message Message
61 */ 68 */
62void 69void
63destroy_message (struct GNUNET_MESSENGER_Message *message); 70destroy_message (struct GNUNET_MESSENGER_Message *message);
64 71
65/** 72/**
73 * Returns if the message should be bound to a member session.
74 *
75 * @param[in] message Message
76 * @return #GNUNET_YES or #GNUNET_NO
77 */
78int
79is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
80
81/**
66 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>. 82 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>.
67 * 83 *
68 * @param kind Kind of message 84 * @param[in] kind Kind of message
69 * @return Minimal size to encode 85 * @return Minimal size to encode
70 */ 86 */
71uint16_t 87uint16_t
@@ -74,57 +90,66 @@ get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind);
74/** 90/**
75 * Returns the exact size in bytes to encode a given <i>message</i>. 91 * Returns the exact size in bytes to encode a given <i>message</i>.
76 * 92 *
77 * @param message Message 93 * @param[in] message Message
94 * @param[in] encode_signature Flag to include signature
78 * @return Size to encode 95 * @return Size to encode
79 */ 96 */
80uint16_t 97uint16_t
81get_message_size (const struct GNUNET_MESSENGER_Message *message); 98get_message_size (const struct GNUNET_MESSENGER_Message *message,
99 int include_signature);
82 100
83/** 101/**
84 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes. 102 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes.
85 * 103 *
86 * @param message Message 104 * @param[in] message Message
87 * @param length Maximal length to encode 105 * @param[in] length Maximal length to encode
88 * @param[out] buffer Buffer 106 * @param[out] buffer Buffer
107 * @param[in] encode_signature Flag to include signature
89 */ 108 */
90void 109void
91encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer); 110encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
111 int include_signature);
92 112
93/** 113/**
94 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes. 114 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes.
95 * 115 *
96 * If the buffer is too small for a message of its decoded kind the function fails with 116 * If the buffer is too small for a message of its decoded kind the function fails with
97 * resulting GNUNET_NO after decoding only the messages header. 117 * resulting #GNUNET_NO after decoding only the messages header.
98 * 118 *
99 * On success the function returns GNUNET_YES. 119 * On success the function returns #GNUNET_YES.
100 * 120 *
101 * @param[out] message Message 121 * @param[out] message Message
102 * @param length Maximal length to decode 122 * @param[in] length Maximal length to decode
103 * @param buffer Buffer 123 * @param[in] buffer Buffer
104 * @return GNUNET_YES on success, otherwise GNUNET_NO 124 * @param[out] padding Padding
125 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
105 */ 126 */
106int 127int
107decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer); 128decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
129 int include_signature, uint16_t *padding);
108 130
109/** 131/**
110 * Calculates a <i>hash</i> of a given <i>buffer</i> of a <i>length</i> in bytes. 132 * Calculates a <i>hash</i> of a given <i>buffer</i> with a <i>length</i> in bytes
133 * from a <i>message</i>.
111 * 134 *
112 * @param length Length of buffer 135 * @param[in] message Message
113 * @param buffer Buffer 136 * @param[in] length Length of buffer
137 * @param[in] buffer Buffer
114 * @param[out] hash Hash 138 * @param[out] hash Hash
115 */ 139 */
116void 140void
117hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash); 141hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
142 struct GNUNET_HashCode *hash);
118 143
119/** 144/**
120 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature 145 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature
121 * into the <i>buffer</i> as well. 146 * into the <i>buffer</i> as well.
122 * 147 *
123 * @param[out] message Message 148 * @param[in/out] message Message
124 * @param length Length of buffer 149 * @param[in] length Length of buffer
125 * @param[out] buffer Buffer 150 * @param[out] buffer Buffer
126 * @param hash Hash of message 151 * @param[in] hash Hash of message
127 * @param ego EGO 152 * @param[in] ego EGO
128 */ 153 */
129void 154void
130sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, 155sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
@@ -132,13 +157,13 @@ sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *b
132 157
133/** 158/**
134 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific 159 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific
135 * public key. The function returns GNUNET_OK if the signature was valid, otherwise 160 * public key. The function returns #GNUNET_OK if the signature was valid, otherwise
136 * GNUNET_SYSERR. 161 * #GNUNET_SYSERR.
137 * 162 *
138 * @param message Message 163 * @param[in] message Message
139 * @param hash Hash of message 164 * @param[in] hash Hash of message
140 * @param key Public key of EGO 165 * @param[in] key Public key of EGO
141 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR 166 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
142 */ 167 */
143int 168int
144verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, 169verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
@@ -147,23 +172,23 @@ verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNU
147/** 172/**
148 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body 173 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body
149 * and kind with the now private encrypted <i>message</i>. The function returns 174 * and kind with the now private encrypted <i>message</i>. The function returns
150 * GNUNET_YES if the operation succeeded, otherwise GNUNET_NO. 175 * #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
151 * 176 *
152 * @param message Message 177 * @param[in/out] message Message
153 * @param key Public key of EGO 178 * @param[in] key Public key of EGO
154 * @return GNUNET_YES on success, otherwise GNUNET_NO 179 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
155 */ 180 */
156int 181int
157encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key); 182encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key);
158 183
159/** 184/**
160 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body 185 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body
161 * and kind with the inner encrypted message. The function returns GNUNET_YES if the 186 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
162 * operation succeeded, otherwise GNUNET_NO. 187 * operation succeeded, otherwise #GNUNET_NO.
163 * 188 *
164 * @param message Message 189 * @param[in/out] message Message
165 * @param key Private key of EGO 190 * @param[in] key Private key of EGO
166 * @return GNUNET_YES on success, otherwise GNUNET_NO 191 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
167 */ 192 */
168int 193int
169decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key); 194decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key);
@@ -173,18 +198,28 @@ decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_I
173 198
174/** 199/**
175 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i> 200 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i>
176 * is equal to GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message 201 * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
177 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is 202 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is
178 * not NULL. 203 * not NULL.
179 * 204 *
180 * @param[out] message Message 205 * @param[out] message Message
181 * @param[out] hash Hash of message 206 * @param[out] hash Hash of message
182 * @param ego EGO to sign 207 * @param[in] ego EGO to sign
183 * @param mode Mode of packing 208 * @param[in] mode Mode of packing
184 * @return Envelope or NULL 209 * @return Envelope or NULL
185 */ 210 */
186struct GNUNET_MQ_Envelope* 211struct GNUNET_MQ_Envelope*
187pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, 212pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
188 const struct GNUNET_MESSENGER_Ego *ego, int mode); 213 const struct GNUNET_MESSENGER_Ego *ego, int mode);
189 214
215/**
216 * Returns if a specific kind of message should be sent by a client. The function returns
217 * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
218 * of messages which should not be sent manually at all.
219 *
220 * @param[in] message Message
221 */
222int
223filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
224
190#endif //GNUNET_MESSENGER_API_MESSAGE_H 225#endif //GNUNET_MESSENGER_API_MESSAGE_H
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c
index 5fedf1a78..df141ca12 100644
--- a/src/messenger/messenger_api_room.c
+++ b/src/messenger/messenger_api_room.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -30,6 +30,8 @@
30struct GNUNET_MESSENGER_Room* 30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) 31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
32{ 32{
33 GNUNET_assert((handle) && (key));
34
33 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room); 35 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
34 36
35 room->handle = handle; 37 room->handle = handle;
@@ -38,11 +40,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
38 room->opened = GNUNET_NO; 40 room->opened = GNUNET_NO;
39 room->contact_id = NULL; 41 room->contact_id = NULL;
40 42
41 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
42
43 init_list_tunnels (&(room->entries)); 43 init_list_tunnels (&(room->entries));
44 44
45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
46 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
46 47
47 return room; 48 return room;
48} 49}
@@ -50,9 +51,10 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
50static int 51static int
51iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) 52iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value)
52{ 53{
53 struct GNUNET_MESSENGER_Message *message = value; 54 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
54 55
55 destroy_message (message); 56 destroy_message (entry->message);
57 GNUNET_free(entry);
56 58
57 return GNUNET_YES; 59 return GNUNET_YES;
58} 60}
@@ -60,8 +62,7 @@ iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *val
60void 62void
61destroy_room (struct GNUNET_MESSENGER_Room *room) 63destroy_room (struct GNUNET_MESSENGER_Room *room)
62{ 64{
63 if (room->members) 65 GNUNET_assert(room);
64 GNUNET_CONTAINER_multishortmap_destroy (room->members);
65 66
66 clear_list_tunnels (&(room->entries)); 67 clear_list_tunnels (&(room->entries));
67 68
@@ -72,6 +73,9 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
72 GNUNET_CONTAINER_multihashmap_destroy (room->messages); 73 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
73 } 74 }
74 75
76 if (room->members)
77 GNUNET_CONTAINER_multishortmap_destroy (room->members);
78
75 if (room->contact_id) 79 if (room->contact_id)
76 GNUNET_free(room->contact_id); 80 GNUNET_free(room->contact_id);
77 81
@@ -81,65 +85,111 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
81const struct GNUNET_MESSENGER_Message* 85const struct GNUNET_MESSENGER_Message*
82get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) 86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
83{ 87{
84 return GNUNET_CONTAINER_multihashmap_get (room->messages, hash); 88 GNUNET_assert((room) && (hash));
89
90 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
91 room->messages, hash
92 );
93
94 return (entry? entry->message : NULL);
95}
96
97struct GNUNET_MESSENGER_Contact*
98get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
99{
100 GNUNET_assert((room) && (hash));
101
102 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
103 room->messages, hash
104 );
105
106 return (entry? entry->sender : NULL);
85} 107}
86 108
87static void 109static void
88handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 110handle_join_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
89 const struct GNUNET_HashCode *hash) 111 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
90{ 112{
91 struct GNUNET_MESSENGER_Contact *contact = get_handle_contact_by_pubkey (room->handle, &(message->body.join.key)); 113 if (!sender)
114 {
115 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
116 struct GNUNET_HashCode context;
117
118 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
119
120 sender = get_store_contact(store, &context, &(message->body.join.key));
121 }
92 122
93 if (contact) 123 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
94 GNUNET_CONTAINER_multishortmap_put (room->members, &(message->header.sender_id), contact, 124 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
126 increase_contact_rc(sender);
96} 127}
97 128
98static void 129static void
99handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 130handle_leave_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
100 const struct GNUNET_HashCode *hash) 131 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
101{ 132{
102 GNUNET_CONTAINER_multishortmap_remove_all (room->members, &(message->header.sender_id)); 133 if ((!sender) ||
134 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
135 return;
136
137 struct GNUNET_HashCode context;
138 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
139
140 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
141
142 if (GNUNET_YES == decrease_contact_rc(sender))
143 remove_store_contact(store, sender, &context);
103} 144}
104 145
105static void 146static void
106handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 147handle_name_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
107 const struct GNUNET_HashCode *hash) 148 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
108{ 149{
109 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 150 if (!sender)
110 &(message->header.sender_id)); 151 return;
111 152
112 if (contact) 153 set_contact_name (sender, message->body.name.name);
113 set_contact_name (contact, message->body.name.name);
114} 154}
115 155
116static void 156static void
117handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 157handle_key_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
118 const struct GNUNET_HashCode *hash) 158 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
119{ 159{
120 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 160 if (!sender)
121 &(message->header.sender_id)); 161 return;
162
163 struct GNUNET_HashCode context;
164 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
122 165
123 if (contact) 166 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
124 swap_handle_contact_by_pubkey (room->handle, contact, &(message->body.key.key)); 167
168 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
125} 169}
126 170
127static void 171static void
128handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 172handle_id_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
129 const struct GNUNET_HashCode *hash) 173 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
130{ 174{
131 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 175 if ((!sender) ||
132 &(message->header.sender_id)); 176 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
177 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
178 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
179 return;
180
181 struct GNUNET_HashCode context, next_context;
182 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
183 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
133 184
134 if ((contact) && (GNUNET_OK 185 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
135 == GNUNET_CONTAINER_multishortmap_put (room->members, &(message->body.id.id), contact, 186
136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) 187 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
137 GNUNET_CONTAINER_multishortmap_remove (room->members, &(message->header.sender_id), contact);
138} 188}
139 189
140static void 190static void
141handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 191handle_miss_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
142 const struct GNUNET_HashCode *hash) 192 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
143{ 193{
144 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id))) 194 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
145 { 195 {
@@ -150,9 +200,25 @@ handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MES
150 } 200 }
151} 201}
152 202
203static void
204handle_delete_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
205 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
206{
207 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
208 room->messages, &(message->body.delete.hash)
209 );
210
211 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
212 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.delete.hash), entry)))
213 {
214 destroy_message (entry->message);
215 GNUNET_free(entry);
216 }
217}
218
153void 219void
154handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 220handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
155 const struct GNUNET_HashCode *hash) 221 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
156{ 222{
157 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash)) 223 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
158 return; 224 return;
@@ -160,30 +226,78 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MES
160 switch (message->header.kind) 226 switch (message->header.kind)
161 { 227 {
162 case GNUNET_MESSENGER_KIND_JOIN: 228 case GNUNET_MESSENGER_KIND_JOIN:
163 handle_join_message (room, message, hash); 229 handle_join_message (room, sender, message, hash);
164 break; 230 break;
165 case GNUNET_MESSENGER_KIND_LEAVE: 231 case GNUNET_MESSENGER_KIND_LEAVE:
166 handle_leave_message (room, message, hash); 232 handle_leave_message (room, sender, message, hash);
167 break; 233 break;
168 case GNUNET_MESSENGER_KIND_NAME: 234 case GNUNET_MESSENGER_KIND_NAME:
169 handle_name_message (room, message, hash); 235 handle_name_message (room, sender, message, hash);
170 break; 236 break;
171 case GNUNET_MESSENGER_KIND_KEY: 237 case GNUNET_MESSENGER_KIND_KEY:
172 handle_key_message (room, message, hash); 238 handle_key_message (room, sender, message, hash);
173 break; 239 break;
174 case GNUNET_MESSENGER_KIND_ID: 240 case GNUNET_MESSENGER_KIND_ID:
175 handle_id_message (room, message, hash); 241 handle_id_message (room, sender, message, hash);
176 break; 242 break;
177 case GNUNET_MESSENGER_KIND_MISS: 243 case GNUNET_MESSENGER_KIND_MISS:
178 handle_miss_message (room, message, hash); 244 handle_miss_message (room, sender, message, hash);
245 break;
246 case GNUNET_MESSENGER_KIND_DELETE:
247 handle_delete_message (room, sender, message, hash);
179 break; 248 break;
180 default: 249 default:
181 break; 250 break;
182 } 251 }
183 252
184 struct GNUNET_MESSENGER_Message *clone = copy_message (message); 253 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
254
255 if (!entry)
256 return;
257
258 entry->sender = sender;
259 entry->message = copy_message (message);
185 260
186 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, clone, 261 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
188 destroy_message (clone); 263 {
264 destroy_message (entry->message);
265 GNUNET_free(entry);
266 }
267}
268
269struct GNUNET_MESSENGER_MemberCall
270{
271 struct GNUNET_MESSENGER_Room *room;
272 GNUNET_MESSENGER_MemberCallback callback;
273 void *cls;
274};
275
276static int
277iterate_local_members (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
278{
279 struct GNUNET_MESSENGER_MemberCall *call = cls;
280 struct GNUNET_MESSENGER_Contact *contact = value;
281
282 return call->callback(call->cls, call->room, contact);
283}
284
285int
286iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
287 void* cls)
288{
289 GNUNET_assert(room);
290
291 if (!callback)
292 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
293
294 struct GNUNET_MESSENGER_MemberCall call;
295
296 call.room = room;
297 call.callback = callback;
298 call.cls = cls;
299
300 GNUNET_assert(callback);
301
302 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
189} 303}
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h
index 0038128d8..9455fd43b 100644
--- a/src/messenger/messenger_api_room.h
+++ b/src/messenger/messenger_api_room.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -36,6 +36,11 @@
36#include "messenger_api_contact.h" 36#include "messenger_api_contact.h"
37#include "messenger_api_message.h" 37#include "messenger_api_message.h"
38 38
39struct GNUNET_MESSENGER_RoomMessageEntry {
40 struct GNUNET_MESSENGER_Contact* sender;
41 struct GNUNET_MESSENGER_Message* message;
42};
43
39struct GNUNET_MESSENGER_Room 44struct GNUNET_MESSENGER_Room
40{ 45{
41 struct GNUNET_MESSENGER_Handle *handle; 46 struct GNUNET_MESSENGER_Handle *handle;
@@ -45,17 +50,17 @@ struct GNUNET_MESSENGER_Room
45 50
46 struct GNUNET_ShortHashCode *contact_id; 51 struct GNUNET_ShortHashCode *contact_id;
47 52
48 struct GNUNET_CONTAINER_MultiShortmap *members;
49 struct GNUNET_MESSENGER_ListTunnels entries; 53 struct GNUNET_MESSENGER_ListTunnels entries;
50 54
51 struct GNUNET_CONTAINER_MultiHashMap *messages; 55 struct GNUNET_CONTAINER_MultiHashMap *messages;
56 struct GNUNET_CONTAINER_MultiShortmap *members;
52}; 57};
53 58
54/** 59/**
55 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API. 60 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API.
56 * 61 *
57 * @param handle Handle 62 * @param[in/out] handle Handle
58 * @param key Key of room 63 * @param[in] key Key of room
59 * @return New room 64 * @return New room
60 */ 65 */
61struct GNUNET_MESSENGER_Room* 66struct GNUNET_MESSENGER_Room*
@@ -64,7 +69,7 @@ create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCod
64/** 69/**
65 * Destroys a room and frees its memory fully from the client API. 70 * Destroys a room and frees its memory fully from the client API.
66 * 71 *
67 * @param room Room 72 * @param[in/out] room Room
68 */ 73 */
69void 74void
70destroy_room (struct GNUNET_MESSENGER_Room *room); 75destroy_room (struct GNUNET_MESSENGER_Room *room);
@@ -73,23 +78,48 @@ destroy_room (struct GNUNET_MESSENGER_Room *room);
73 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching 78 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching
74 * message is found, NULL gets returned. 79 * message is found, NULL gets returned.
75 * 80 *
76 * @param room Room 81 * @param[in] room Room
77 * @param hash Hash of message 82 * @param[in] hash Hash of message
78 * @return Message or NULL 83 * @return Message or NULL
79 */ 84 */
80const struct GNUNET_MESSENGER_Message* 85const struct GNUNET_MESSENGER_Message*
81get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); 86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
82 87
83/** 88/**
89 * Returns a messages sender locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no
90 * matching message is found, NULL gets returned.
91 *
92 * @param[in] room Room
93 * @param[in] hash Hash of message
94 * @return Contact of sender or NULL
95 */
96struct GNUNET_MESSENGER_Contact*
97get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
98
99/**
84 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update 100 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
85 * members and its information. The function also stores the message in map locally for access afterwards. 101 * members and its information. The function also stores the message in map locally for access afterwards.
86 * 102 *
87 * @param room Room 103 * @param[in/out] room Room
88 * @param message Message 104 * @param[in/out] sender Contact of sender
89 * @param hash Hash of message 105 * @param[in] message Message
106 * @param[in] hash Hash of message
90 */ 107 */
91void 108void
92handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, 109handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
93 const struct GNUNET_HashCode *hash); 110 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
111
112/**
113 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
114 * <i>callback</i> with a custom closure.
115 *
116 * @param[in/out] room Room
117 * @param[in] callback Function called for each member
118 * @param[in/out] cls Closure
119 * @return Amount of members iterated
120 */
121int
122iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
123 void* cls);
94 124
95#endif //GNUNET_MESSENGER_API_ROOM_H 125#endif //GNUNET_MESSENGER_API_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_util.c b/src/messenger/messenger_api_util.c
index 94fc9469d..68e15d789 100644
--- a/src/messenger/gnunet-service-messenger_util.c
+++ b/src/messenger/messenger_api_util.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -19,11 +19,11 @@
19 */ 19 */
20/** 20/**
21 * @author Tobias Frisch 21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_util.c 22 * @file src/messenger/messenger_api_util.c
23 * @brief GNUnet MESSENGER service 23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */ 24 */
25 25
26#include "gnunet-service-messenger_util.h" 26#include "messenger_api_util.h"
27 27
28static void 28static void
29callback_close_channel (void *cls) 29callback_close_channel (void *cls)
@@ -37,13 +37,18 @@ callback_close_channel (void *cls)
37void 37void
38delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel) 38delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel)
39{ 39{
40 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_URGENT, 40 GNUNET_assert(channel);
41
42 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (),
43 GNUNET_SCHEDULER_PRIORITY_URGENT,
41 callback_close_channel, channel); 44 callback_close_channel, channel);
42} 45}
43 46
44int 47int
45generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members) 48generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members)
46{ 49{
50 GNUNET_assert(id);
51
47 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0); 52 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0);
48 53
49 do 54 do
@@ -62,3 +67,18 @@ generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CO
62 67
63 return GNUNET_NO; 68 return GNUNET_NO;
64} 69}
70
71const struct GNUNET_IDENTITY_PublicKey*
72get_anonymous_public_key ()
73{
74 static struct GNUNET_IDENTITY_PublicKey public_key;
75 static struct GNUNET_IDENTITY_Ego* ego = NULL;
76
77 if (!ego)
78 {
79 ego = GNUNET_IDENTITY_ego_get_anonymous();
80 GNUNET_IDENTITY_ego_get_public_key(ego, &public_key);
81 }
82
83 return &public_key;
84}
diff --git a/src/messenger/gnunet-service-messenger_util.h b/src/messenger/messenger_api_util.h
index 20f8f0afe..c70a3601f 100644
--- a/src/messenger/gnunet-service-messenger_util.h
+++ b/src/messenger/messenger_api_util.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -19,8 +19,8 @@
19 */ 19 */
20/** 20/**
21 * @author Tobias Frisch 21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_util.h 22 * @file src/messenger/messenger_api_util.h
23 * @brief GNUnet MESSENGER service 23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */ 24 */
25 25
26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H 26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H
@@ -30,24 +30,35 @@
30#include "gnunet_cadet_service.h" 30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h" 32#include "gnunet_crypto_lib.h"
33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h"
33 35
34/** 36/**
35 * Starts an urgent task to close a CADET channel asynchronously. 37 * Starts an urgent task to close a CADET channel asynchronously.
36 * 38 *
37 * @param channel Channel 39 * @param[in/out] channel Channel
38 */ 40 */
39void 41void
40delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel); 42delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel);
41 43
42/** 44/**
43 * Tries to generate an unused member id and store it into the <i>id</i> parameter. A map containing all currently 45 * Tries to generate an unused member id and store it into the <i>id</i> parameter.
44 * used member ids is used to check against. 46 * A map containing all currently used member ids is used to check against.
45 * 47 *
46 * @param[out] id New member id 48 * @param[out] id New member id
47 * @param members Map of member ids 49 * @param[in] members Map of member ids
48 * @return GNUNET_YES on success, GNUNET_NO on failure 50 * @return #GNUNET_YES on success, #GNUNET_NO on failure
49 */ 51 */
50int 52int
51generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members); 53generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members);
52 54
55/**
56 * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() without
57 * recalculating it every time.
58 *
59 * @return anonymous public key
60 */
61const struct GNUNET_IDENTITY_PublicKey*
62get_anonymous_public_key ();
63
53#endif //GNUNET_SERVICE_MESSENGER_UTIL_H 64#endif //GNUNET_SERVICE_MESSENGER_UTIL_H
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
index b42dfe6d9..fb3e3e1bc 100644
--- a/src/messenger/test_messenger.c
+++ b/src/messenger/test_messenger.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -61,14 +61,13 @@ end (void *cls)
61 61
62 if (messenger) 62 if (messenger)
63 { 63 {
64 GNUNET_MESSENGER_disconnect(messenger); 64 GNUNET_MESSENGER_disconnect (messenger);
65 messenger = NULL; 65 messenger = NULL;
66 } 66 }
67 67
68 status = 0; 68 status = 0;
69} 69}
70 70
71
72static void 71static void
73end_badly (void *cls) 72end_badly (void *cls)
74{ 73{
@@ -83,7 +82,7 @@ end_operation (void *cls)
83{ 82{
84 op_task = NULL; 83 op_task = NULL;
85 84
86 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); 85 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
87 86
88 if (die_task) 87 if (die_task)
89 GNUNET_SCHEDULER_cancel (die_task); 88 GNUNET_SCHEDULER_cancel (die_task);
@@ -109,30 +108,25 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
109 op_task = NULL; 108 op_task = NULL;
110 } 109 }
111 110
112 const char* name = GNUNET_MESSENGER_get_name(handle); 111 const char *name = GNUNET_MESSENGER_get_name (handle);
113 112
114 if (0 != strcmp(name, TESTER_NAME)) 113 if (0 != strcmp (name, TESTER_NAME))
115 { 114 {
116 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name"); 115 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name");
117 return; 116 return;
118 } 117 }
119 118
120 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); 119 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
121 struct GNUNET_IDENTITY_PublicKey anonymous_key;
122
123 GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key);
124 120
125 const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle); 121 if (((!identity_counter) && (key)) || ((identity_counter) && (!key)))
126
127 if (((!identity_counter) && (0 != GNUNET_memcmp(key, (&anonymous_key)))) ||
128 ((identity_counter) && (0 == GNUNET_memcmp(key, (&anonymous_key)))))
129 { 122 {
130 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key"); 123 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key");
131 return; 124 return;
132 } 125 }
133 126
134 if (identity_counter) { 127 if (identity_counter)
135 GNUNET_MESSENGER_disconnect(handle); 128 {
129 GNUNET_MESSENGER_disconnect (handle);
136 130
137 op_task = NULL; 131 op_task = NULL;
138 messenger = NULL; 132 messenger = NULL;
@@ -144,7 +138,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
144 return; 138 return;
145 } 139 }
146 140
147 GNUNET_MESSENGER_update(messenger); 141 GNUNET_MESSENGER_update (messenger);
148 identity_counter++; 142 identity_counter++;
149} 143}
150 144
@@ -156,16 +150,14 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
156 * @param peer Peer for testing 150 * @param peer Peer for testing
157 */ 151 */
158static void 152static void
159run (void *cls, 153run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
160 const struct GNUNET_CONFIGURATION_Handle *cfg,
161 struct GNUNET_TESTING_Peer *peer)
162{ 154{
163 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); 155 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
164 156
165 identity_counter = 0; 157 identity_counter = 0;
166 158
167 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); 159 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
168 messenger = GNUNET_MESSENGER_connect(cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL); 160 messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL);
169} 161}
170 162
171/** 163/**
@@ -176,11 +168,9 @@ run (void *cls,
176 * @return 0 ok, 1 on error 168 * @return 0 ok, 1 on error
177 */ 169 */
178int 170int
179main(int argc, char **argv) 171main (int argc, char **argv)
180{ 172{
181 if (0 != GNUNET_TESTING_peer_run("test-messenger", 173 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
182 "test_messenger_api.conf",
183 &run, NULL))
184 return 1; 174 return 1;
185 175
186 return status; 176 return status;
diff --git a/src/messenger/test_messenger_adapt.c b/src/messenger/test_messenger_adapt.c
new file mode 100644
index 000000000..90e8ac28d
--- /dev/null
+++ b/src/messenger/test_messenger_adapt.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_adapt.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 5, 1, 2, 3, 6, 7, 8, 4 };
39 unsigned int stages [] = { 0x21, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_adapt", &cfg);
47}
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c
index e2057acc4..a70121a30 100644
--- a/src/messenger/test_messenger_anonymous.c
+++ b/src/messenger/test_messenger_anonymous.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -59,14 +59,13 @@ end (void *cls)
59 59
60 if (messenger) 60 if (messenger)
61 { 61 {
62 GNUNET_MESSENGER_disconnect(messenger); 62 GNUNET_MESSENGER_disconnect (messenger);
63 messenger = NULL; 63 messenger = NULL;
64 } 64 }
65 65
66 status = 0; 66 status = 0;
67} 67}
68 68
69
70static void 69static void
71end_badly (void *cls) 70end_badly (void *cls)
72{ 71{
@@ -81,7 +80,7 @@ end_operation (void *cls)
81{ 80{
82 op_task = NULL; 81 op_task = NULL;
83 82
84 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); 83 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
85 84
86 if (die_task) 85 if (die_task)
87 GNUNET_SCHEDULER_cancel (die_task); 86 GNUNET_SCHEDULER_cancel (die_task);
@@ -105,7 +104,7 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
105 op_task = NULL; 104 op_task = NULL;
106 } 105 }
107 106
108 const char* name = GNUNET_MESSENGER_get_name(handle); 107 const char *name = GNUNET_MESSENGER_get_name (handle);
109 108
110 if (NULL != name) 109 if (NULL != name)
111 { 110 {
@@ -113,26 +112,21 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
113 return; 112 return;
114 } 113 }
115 114
116 if (GNUNET_SYSERR != GNUNET_MESSENGER_update(handle)) 115 if (GNUNET_SYSERR != GNUNET_MESSENGER_update (handle))
117 { 116 {
118 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail"); 117 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail");
119 return; 118 return;
120 } 119 }
121 120
122 struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); 121 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
123 struct GNUNET_IDENTITY_PublicKey anonymous_key;
124
125 GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key);
126
127 const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle);
128 122
129 if (0 != GNUNET_memcmp(key, (&anonymous_key))) 123 if (key)
130 { 124 {
131 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous"); 125 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous");
132 return; 126 return;
133 } 127 }
134 128
135 GNUNET_MESSENGER_disconnect(handle); 129 GNUNET_MESSENGER_disconnect (handle);
136 130
137 messenger = NULL; 131 messenger = NULL;
138 132
@@ -150,14 +144,12 @@ on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
150 * @param peer Peer for testing 144 * @param peer Peer for testing
151 */ 145 */
152static void 146static void
153run (void *cls, 147run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
154 const struct GNUNET_CONFIGURATION_Handle *cfg,
155 struct GNUNET_TESTING_Peer *peer)
156{ 148{
157 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); 149 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
158 150
159 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); 151 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
160 messenger = GNUNET_MESSENGER_connect(cfg, NULL, &on_identity, NULL, NULL, NULL); 152 messenger = GNUNET_MESSENGER_connect (cfg, NULL, &on_identity, NULL, NULL, NULL);
161} 153}
162 154
163/** 155/**
@@ -168,11 +160,9 @@ run (void *cls,
168 * @return 0 ok, 1 on error 160 * @return 0 ok, 1 on error
169 */ 161 */
170int 162int
171main(int argc, char **argv) 163main (int argc, char **argv)
172{ 164{
173 if (0 != GNUNET_TESTING_peer_run("test-messenger", 165 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
174 "test_messenger_api.conf",
175 &run, NULL))
176 return 1; 166 return 1;
177 167
178 return status; 168 return status;
diff --git a/src/messenger/test_messenger_api.conf b/src/messenger/test_messenger_api.conf
index f5837392e..968f56f6d 100644
--- a/src/messenger/test_messenger_api.conf
+++ b/src/messenger/test_messenger_api.conf
@@ -1,11 +1,39 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf 1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf 2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf
3 3
4[testbed]
5HOSTNAME = localhost
6OVERLAY_TOPOLOGY = CLIQUE
7
8[arm]
9GLOBAL_POSTFIX = -l $GNUNET_CACHE_HOME/{}-logs -L verbose
10
11[transport]
12IMMEDIATE_START = YES
13
14[core]
15START_ON_DEMAND = YES
16IMMEDIATE_START = YES
17USE_EPHEMERAL_KEYS = NO
18
4[PATHS] 19[PATHS]
5GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/ 20GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/
6 21
22[peerinfo]
23NO_IO = YES
24
7[cadet] 25[cadet]
8START_ON_DEMAND = YES 26START_ON_DEMAND = YES
27REFRESH_CONNECTION_TIME = 1 s
28ID_ANNOUNCE_TIME = 5 s
29CONNECT_TIMEOUT = 30 s
30DEFAULT_TTL = 16
31DHT_REPLICATION_LEVEL = 10
32MAX_TUNNELS = 10
33MAX_CONNECTIONS = 10
34MAX_MSGS_QUEUE = 20
35DISABLE_TRY_CONNECT = YES
36REKEY_PERIOD = 2 s
9 37
10[identity] 38[identity]
11START_ON_DEMAND = YES 39START_ON_DEMAND = YES
@@ -14,4 +42,6 @@ START_ON_DEMAND = YES
14START_ON_DEMAND = YES 42START_ON_DEMAND = YES
15 43
16[nat] 44[nat]
17ENABLE_UPNP = NO \ No newline at end of file 45ENABLE_UPNP = NO
46RETURN_LOCAL_ADDRESSES = YES
47IMMEDIATE_START = NO \ No newline at end of file
diff --git a/src/messenger/test_messenger_async_client.c b/src/messenger/test_messenger_async_client.c
new file mode 100644
index 000000000..1067b9a6d
--- /dev/null
+++ b/src/messenger/test_messenger_async_client.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_async_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_async_p2p.c b/src/messenger/test_messenger_async_p2p.c
new file mode 100644
index 000000000..d827aae16
--- /dev/null
+++ b/src/messenger/test_messenger_async_p2p.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_async_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x30, 0x30 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_comm0.c b/src/messenger/test_messenger_comm0.c
deleted file mode 100644
index 631b5b2c9..000000000
--- a/src/messenger/test_messenger_comm0.c
+++ /dev/null
@@ -1,252 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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 * @file messenger/test_messenger_comm0.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testbed_logger_service.h"
29#include "gnunet_testbed_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_messenger_service.h"
32
33/**
34 * How long until we really give up on a particular testcase portion?
35 */
36#define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
37 60)
38
39/**
40 * How long until we give up on any particular operation (and retry)?
41 */
42#define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
43
44static int status = 1;
45
46static struct GNUNET_SCHEDULER_Task *die_task = NULL;
47static struct GNUNET_SCHEDULER_Task *op_task = NULL;
48
49static void
50end (void *cls)
51{
52 die_task = NULL;
53
54 if (op_task)
55 {
56 GNUNET_SCHEDULER_cancel (op_task);
57 op_task = NULL;
58 }
59
60 GNUNET_SCHEDULER_shutdown ();
61 status = 0;
62}
63
64
65static void
66end_badly (void *cls)
67{
68 fprintf (stderr, "Testcase failed (timeout).\n");
69
70 end (NULL);
71 status = 1;
72}
73
74static void
75end_operation (void *cls)
76{
77 op_task = NULL;
78
79 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown");
80
81 if (die_task)
82 GNUNET_SCHEDULER_cancel (die_task);
83
84 end (NULL);
85 status = 1;
86}
87
88static void
89end_error (void *cls)
90{
91 op_task = NULL;
92
93 fprintf (stderr, "Testcase failed (error: '%s').\n", cls? (const char*) cls : "unknown");
94 GNUNET_free(cls);
95
96 if (die_task)
97 GNUNET_SCHEDULER_cancel (die_task);
98
99 end (NULL);
100 status = 1;
101}
102
103/**
104 * Function called whenever a message is received or sent.
105 *
106 * @param cls Closure
107 * @param room Room
108 * @param message Message
109 * @param hash Hash of message
110 */
111static void
112on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
113 const struct GNUNET_HashCode *hash)
114{
115 // TODO
116}
117
118/**
119 * Function called when an identity is retrieved.
120 *
121 * @param cls Closure
122 * @param handle Handle of messenger service
123 */
124static void
125on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
126{
127 // TODO
128}
129
130static void
131on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
132 const struct GNUNET_TESTBED_PeerInformation *pinfo,
133 const char *emsg)
134{
135 if (emsg)
136 {
137 op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg));
138 return;
139 }
140
141 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
142 {
143 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "config");
144 return;
145 }
146
147 struct GNUNET_MESSENGER_Handle *handle;
148 struct GNUNET_MESSENGER_Room *room;
149
150 fprintf (stderr, "MSG: connect\n");
151
152 handle = GNUNET_MESSENGER_connect(pinfo->result.cfg, "tester", &on_identity, NULL, &on_message, NULL);
153
154 struct GNUNET_HashCode hash;
155 GNUNET_CRYPTO_hash("test", 4, &hash);
156
157 fprintf (stderr, "MSG: open\n");
158
159 room = GNUNET_MESSENGER_open_room(handle, &hash);
160
161 fprintf (stderr, "MSG: close\n");
162
163 GNUNET_MESSENGER_close_room(room);
164
165 fprintf (stderr, "MSG: disconnect\n");
166
167 GNUNET_MESSENGER_disconnect(handle);
168
169 GNUNET_TESTBED_operation_done(op);
170
171}
172
173/**
174 * Main function for a peer of the testcase.
175 *
176 * @param cls Closure
177 * @param event Information about the event
178 */
179static void
180run (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
181{
182 if (GNUNET_TESTBED_ET_PEER_START != event->type)
183 {
184 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "start");
185 return;
186 }
187
188 GNUNET_TESTBED_peer_get_information(event->details.peer_start.peer,
189 GNUNET_TESTBED_PIT_CONFIGURATION,
190 on_peer, event->details.peer_start.peer);
191
192 fprintf (stderr, "MSG: barrier\n");
193
194 GNUNET_TESTBED_barrier_wait("exit", NULL, NULL);
195
196 fprintf (stderr, "MSG: exit\n");
197}
198
199static void
200exit_status (void *cls, const char *name,
201 struct GNUNET_TESTBED_Barrier *barrier,
202 enum GNUNET_TESTBED_BarrierStatus status,
203 const char *emsg)
204{
205 if (emsg)
206 {
207 op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg));
208 return;
209 }
210
211 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
212 {
213 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "exit");
214 return;
215 }
216 else if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)
217 GNUNET_SCHEDULER_add_now(&end, NULL);
218}
219
220static void
221init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers,
222 struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded,
223 unsigned int links_failed)
224{
225 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
226
227 struct GNUNET_TESTBED_Controller *controller;
228
229 controller = GNUNET_TESTBED_run_get_controller_handle(h);
230
231 GNUNET_TESTBED_barrier_init(controller, "exit", num_peers, exit_status, NULL);
232}
233
234/**
235 * The main function.
236 *
237 * @param argc number of arguments from the command line
238 * @param argv command line arguments
239 * @return 0 ok, 1 on error
240 */
241int
242main(int argc, char **argv)
243{
244 if (GNUNET_OK != GNUNET_TESTBED_test_run("test-messenger-comm0",
245 "test_messenger_api.conf",
246 2, 0,
247 &run, NULL,
248 &init, NULL))
249 return 1;
250
251 return status;
252}
diff --git a/src/messenger/test_messenger_growth.c b/src/messenger/test_messenger_growth.c
new file mode 100644
index 000000000..3781f3ee5
--- /dev/null
+++ b/src/messenger/test_messenger_growth.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_growth.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_growth", &cfg);
47}
diff --git a/src/messenger/test_messenger_ring.c b/src/messenger/test_messenger_ring.c
new file mode 100644
index 000000000..07cfd0c47
--- /dev/null
+++ b/src/messenger/test_messenger_ring.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_ring.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 8, 1, 2, 3, 4, 5, 6, 7 };
39 unsigned int stages [] = { 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_ring", &cfg);
47}
diff --git a/src/messenger/test_messenger_server.c b/src/messenger/test_messenger_server.c
new file mode 100644
index 000000000..1cf2fcc27
--- /dev/null
+++ b/src/messenger/test_messenger_server.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_server.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_server", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_client.c b/src/messenger/test_messenger_sync_client.c
new file mode 100644
index 000000000..99f26b018
--- /dev/null
+++ b/src/messenger/test_messenger_sync_client.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_sync_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x01, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_p2p.c b/src/messenger/test_messenger_sync_p2p.c
new file mode 100644
index 000000000..77ce280a1
--- /dev/null
+++ b/src/messenger/test_messenger_sync_p2p.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_sync_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_client.c b/src/messenger/test_messenger_worst_client.c
new file mode 100644
index 000000000..63826631c
--- /dev/null
+++ b/src/messenger/test_messenger_worst_client.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_worst_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x02 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_p2p.c b/src/messenger/test_messenger_worst_p2p.c
new file mode 100644
index 000000000..c89288eea
--- /dev/null
+++ b/src/messenger/test_messenger_worst_p2p.c
@@ -0,0 +1,47 @@
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 * @file messenger/test_messenger_worst_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x12, 0x12 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_p2p", &cfg);
47}
diff --git a/src/messenger/testing_messenger_barrier.c b/src/messenger/testing_messenger_barrier.c
new file mode 100644
index 000000000..618d255b7
--- /dev/null
+++ b/src/messenger/testing_messenger_barrier.c
@@ -0,0 +1,170 @@
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 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#include "testing_messenger_barrier.h"
27
28struct GNUNET_BarrierHandle
29{
30 unsigned int requirement;
31 GNUNET_BarrierStatusCallback cb;
32 void *cls;
33
34 struct GNUNET_BarrierWaitHandle *head;
35 struct GNUNET_BarrierWaitHandle *tail;
36
37 struct GNUNET_SCHEDULER_Task* task;
38};
39
40struct GNUNET_BarrierHandle*
41GNUNET_init_barrier (unsigned int requirement,
42 GNUNET_BarrierStatusCallback cb,
43 void *cb_cls)
44{
45 if (0 == requirement)
46 return NULL;
47
48 struct GNUNET_BarrierHandle *barrier = GNUNET_new(struct GNUNET_BarrierHandle);
49
50 if (!barrier)
51 return NULL;
52
53 barrier->requirement = requirement;
54 barrier->cb = cb;
55 barrier->cls = cb_cls;
56 barrier->head = NULL;
57 barrier->tail = NULL;
58 barrier->task = NULL;
59
60 return barrier;
61}
62
63static void
64exit_status (struct GNUNET_BarrierHandle *barrier, int status);
65
66static void
67cancel_barrier (void *cls)
68{
69 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR);
70}
71
72static void
73complete_barrier (void *cls)
74{
75 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK);
76}
77
78void
79GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier)
80{
81 if ((!barrier) || (barrier->task))
82 return;
83
84 barrier->task = GNUNET_SCHEDULER_add_now(cancel_barrier, barrier);
85}
86
87struct GNUNET_BarrierWaitHandle
88{
89 GNUNET_BarrierWaitStatusCallback cb;
90 void *cls;
91
92 struct GNUNET_BarrierWaitHandle *prev;
93 struct GNUNET_BarrierWaitHandle *next;
94
95 struct GNUNET_BarrierHandle *barrier;
96};
97
98static void
99exit_status (struct GNUNET_BarrierHandle *barrier, int status)
100{
101 struct GNUNET_BarrierWaitHandle *waiting = barrier->head;
102 while (waiting)
103 {
104 struct GNUNET_BarrierWaitHandle *current = waiting;
105
106 if (current->cb)
107 current->cb(current->cls, current, status);
108
109 waiting = waiting->next;
110
111 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, current);
112 GNUNET_free(current);
113 }
114
115 if (barrier->cb)
116 barrier->cb(barrier->cls, barrier, status);
117
118 GNUNET_free(barrier);
119}
120
121struct GNUNET_BarrierWaitHandle*
122GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
123 GNUNET_BarrierWaitStatusCallback cb,
124 void *cb_cls)
125{
126 if ((!barrier) || (0 == barrier->requirement))
127 return NULL;
128
129 struct GNUNET_BarrierWaitHandle *waiting = GNUNET_new(struct GNUNET_BarrierWaitHandle);
130
131 if (!waiting)
132 return NULL;
133
134 waiting->cb = cb;
135 waiting->cls = cb_cls;
136 waiting->prev = NULL;
137 waiting->next = NULL;
138 waiting->barrier = barrier;
139
140 GNUNET_CONTAINER_DLL_insert_tail(barrier->head, barrier->tail, waiting);
141 barrier->requirement--;
142
143 if ((barrier->requirement == 0) && (!barrier->task))
144 barrier->task = GNUNET_SCHEDULER_add_now(complete_barrier, barrier);
145
146 return waiting;
147}
148
149void
150GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting)
151{
152 if (!waiting)
153 return;
154
155 struct GNUNET_BarrierHandle *barrier = waiting->barrier;
156
157 if (!barrier)
158 return;
159
160 if ((barrier->requirement == 0) && (barrier->task))
161 {
162 GNUNET_SCHEDULER_cancel(barrier->task);
163 barrier->task = NULL;
164 }
165
166 barrier->requirement++;
167 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, waiting);
168
169 GNUNET_free(waiting);
170}
diff --git a/src/messenger/testing_messenger_barrier.h b/src/messenger/testing_messenger_barrier.h
new file mode 100644
index 000000000..3062a393a
--- /dev/null
+++ b/src/messenger/testing_messenger_barrier.h
@@ -0,0 +1,131 @@
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 * @file messenger/testing_messenger_barrier.h
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_BARRIER_H_
27#define GNUNET_TESTING_MESSENGER_BARRIER_H_
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31
32/**
33 * Handle for pseudo-barrier
34 */
35struct GNUNET_BarrierHandle;
36
37
38/**
39 * Functions of this type are to be given as callback argument to
40 * GNUNET_init_barrier(). The callback will be called when status
41 * information is available for the pseudo-barrier.
42 *
43 * @param cls the closure given to GNUNET_init_barrier()
44 * @param barrier the pseudo-barrier handle
45 * @param status status of the pseudo-barrier. The pseudo-barrier is removed
46 * once it has been crossed or an error occurs while processing it.
47 * Therefore it is invalid to call GNUNET_cancel_barrier() on a
48 * crossed or errored pseudo-barrier.
49 */
50typedef void
51(*GNUNET_BarrierStatusCallback) (void *cls,
52 struct GNUNET_BarrierHandle *barrier,
53 int status);
54
55
56/**
57 * Initialise a pseudo-barrier and call the given callback when the required
58 * amount of peers (requirement) reach the pseudo-barrier OR upon error.
59 *
60 * @param requirement the amount of peers that is required to reach the
61 * pseudo-barrier. Peers signal reaching a pseudo-barrier by calling
62 * GNUNET_wait_barrier().
63 * @param cb the callback to call when the pseudo-barrier is reached or upon
64 * error. Can be NULL.
65 * @param cls closure for the above callback
66 * @return pseudo-barrier handle; NULL upon error
67 */
68struct GNUNET_BarrierHandle*
69GNUNET_init_barrier (unsigned int requirement,
70 GNUNET_BarrierStatusCallback cb,
71 void *cb_cls);
72
73
74/**
75 * Cancel a pseudo-barrier.
76 *
77 * @param barrier the pseudo-barrier handle
78 */
79void
80GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier);
81
82
83/**
84 * Handle for pseudo-barrier wait
85 */
86struct GNUNET_BarrierWaitHandle;
87
88
89/**
90 * Functions of this type are to be given as acallback argument to
91 * GNUNET_wait_barrier(). The callback will be called when the pseudo-barrier
92 * corresponding given in GNUNET_wait_barrier() is crossed or cancelled.
93 *
94 * @param cls closure pointer given to GNUNET_wait_barrier()
95 * @param waiting the pseudo-barrier wait handle
96 * @param status #GNUNET_SYSERR in case of error while waiting for the
97 * pseudo-barrier; #GNUNET_OK if the pseudo-barrier is crossed
98 */
99typedef void
100(*GNUNET_BarrierWaitStatusCallback) (void *cls,
101 struct GNUNET_BarrierWaitHandle *waiting,
102 int status);
103
104
105/**
106 * Wait for a pseudo-barrier to be crossed. This function should be called for
107 * the peers which have been started by the testbed.
108 *
109 * @param barrier the pseudo-barrier handle
110 * @param cb the pseudo-barrier wait callback
111 * @param cls the closure for the above callback
112 * @return pseudo-barrier wait handle which can be used to cancel the waiting
113 * at anytime before the callback is called. NULL upon error.
114 */
115struct GNUNET_BarrierWaitHandle*
116GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
117 GNUNET_BarrierWaitStatusCallback cb,
118 void *cb_cls);
119
120
121/**
122 * Cancel a pseudo-barrier wait handle. Should not be called in or after the
123 * callback given to GNUNET_wait_barrier() has been called.
124 *
125 * @param waiting the pseudo-barrier wait handle
126 */
127void
128GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting);
129
130
131#endif /* GNUNET_TESTING_MESSENGER_BARRIER_H_ */
diff --git a/src/messenger/testing_messenger_setup.c b/src/messenger/testing_messenger_setup.c
new file mode 100644
index 000000000..98241fa08
--- /dev/null
+++ b/src/messenger/testing_messenger_setup.c
@@ -0,0 +1,528 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#include "testing_messenger_setup.h"
27
28#include <stdio.h>
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_testbed_logger_service.h"
32#include "gnunet_testbed_service.h"
33#include "gnunet_testing_lib.h"
34#include "gnunet_messenger_service.h"
35#include "testing_messenger_barrier.h"
36
37#define TEST_ROOM "test"
38#define TEST_NAME "tester"
39
40struct test_properties;
41
42struct test_peer {
43 struct test_properties *props;
44 unsigned int num;
45
46 struct GNUNET_SCHEDULER_Task *op_task;
47 struct GNUNET_TESTBED_Operation *op;
48
49 struct GNUNET_TESTBED_Peer *peer;
50 struct GNUNET_PeerIdentity peer_id;
51 struct GNUNET_BarrierWaitHandle *wait;
52
53 struct GNUNET_MESSENGER_Handle *handle;
54 struct GNUNET_MESSENGER_Room *room;
55
56 unsigned int peer_messages;
57
58 const char *message;
59};
60
61struct test_properties {
62 const struct test_configuration *cfg;
63
64 unsigned int num_hosts;
65
66 struct GNUNET_SCHEDULER_Task *die_task;
67 struct GNUNET_SCHEDULER_Task *end_task;
68
69 struct GNUNET_BarrierHandle *barrier;
70
71 struct test_peer *peers;
72 unsigned int num_peer;
73
74 int status;
75};
76
77static void
78shutdown_cb (void *cls)
79{
80 struct test_properties *properties = cls;
81
82
83 for (unsigned int i = 0; i < properties->num_peer; i++)
84 {
85 struct test_peer *peer = &properties->peers[i];
86
87 GNUNET_assert(peer != NULL);
88
89 if (peer->op_task)
90 GNUNET_SCHEDULER_cancel(peer->op_task);
91
92 peer->op_task = NULL;
93
94 if (peer->op)
95 GNUNET_TESTBED_operation_done (peer->op);
96
97 peer->op = NULL;
98
99 if (peer->wait)
100 GNUNET_cancel_wait_barrier(peer->wait);
101
102 peer->wait = NULL;
103
104 if (peer->room)
105 GNUNET_MESSENGER_close_room (peer->room);
106
107 peer->room = NULL;
108
109 if (peer->handle)
110 GNUNET_MESSENGER_disconnect (peer->handle);
111
112 peer->handle = NULL;
113 }
114
115 if (properties->die_task)
116 GNUNET_SCHEDULER_cancel(properties->die_task);
117
118 properties->die_task = NULL;
119 properties->end_task = NULL;
120
121 if (properties->barrier)
122 GNUNET_cancel_barrier(properties->barrier);
123
124 properties->barrier = NULL;
125}
126
127
128
129static void
130end_cb (void *cls)
131{
132 struct test_properties *properties = cls;
133
134 GNUNET_assert(properties != NULL);
135
136 properties->die_task = NULL;
137
138 int status = 0;
139
140 for (unsigned int i = 0; i < properties->num_peer; i++)
141 {
142 struct test_peer *peer = &properties->peers[i];
143
144 GNUNET_assert(peer != NULL);
145
146 const int members = GNUNET_MESSENGER_iterate_members(peer->room, NULL, NULL);
147
148 GNUNET_assert (members >= 0);
149
150 if (peer->props->num_peer != (unsigned int) members)
151 {
152 fprintf (stderr, "Testcase failed (members: %d/%u).\n", members, peer->props->num_peer);
153 status = 1;
154 break;
155 }
156 }
157
158 GNUNET_SCHEDULER_shutdown ();
159
160 properties->status = status;
161}
162
163static void
164end_badly_cb (void *cls)
165{
166 struct test_properties *properties = cls;
167
168 GNUNET_assert(properties != NULL);
169
170 fprintf (stderr, "Testcase failed (timeout).\n");
171
172 end_cb (properties);
173
174 properties->status = 1;
175}
176
177static void
178end_operation_cb (void *cls)
179{
180 struct test_peer *peer = cls;
181
182 GNUNET_assert(peer != NULL);
183
184 peer->op_task = NULL;
185
186 fprintf (stderr, "Testcase failed (operation: '%s').\n", peer->message);
187
188 GNUNET_SCHEDULER_shutdown ();
189}
190
191static void
192end_error_cb (void *cls)
193{
194 struct test_peer *peer = cls;
195
196 GNUNET_assert(peer != NULL);
197
198 peer->op_task = NULL;
199
200 fprintf (stderr, "Testcase failed (error: '%s').\n", peer->message);
201 GNUNET_free (peer);
202
203 GNUNET_SCHEDULER_shutdown ();
204}
205
206static void
207barrier2_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
208{
209 struct test_peer *peer = cls;
210
211 GNUNET_assert(peer != NULL);
212
213 if (peer->wait == waiting)
214 peer->wait = NULL;
215}
216
217static void
218barrier_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
219{
220 struct test_peer *peer = cls;
221
222 GNUNET_assert(peer != NULL);
223
224 if (peer->wait == waiting)
225 peer->wait = NULL;
226
227 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x02))
228 {
229 unsigned int door = peer->props->cfg->doors[peer->num - 1];
230
231 if (door == 0)
232 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
233 else
234 door = door - 1;
235
236 struct GNUNET_HashCode hash;
237 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
238
239 struct GNUNET_MESSENGER_Room *room;
240 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
241
242 if (peer->room)
243 GNUNET_assert(room == peer->room);
244 else
245 GNUNET_assert(room != NULL);
246
247 peer->room = room;
248 }
249}
250
251/**
252 * Function called whenever a message is received or sent.
253 *
254 * @param cls Closure
255 * @param room Room
256 * @param sender Sender
257 * @param message Message
258 * @param hash Hash of message
259 * @param flags Flags of message
260 */
261static void
262on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
263 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
264 enum GNUNET_MESSENGER_MessageFlags flags)
265{
266 struct test_peer *peer = cls;
267
268 GNUNET_assert(peer != NULL);
269
270 fprintf (stderr, "Peer: %s; [%s] Message: %s (%s)\n",
271 GNUNET_i2s(&(peer->peer_id)),
272 GNUNET_sh2s(&(message->header.sender_id)),
273 GNUNET_MESSENGER_name_of_kind(message->header.kind),
274 GNUNET_h2s(hash));
275
276 if (GNUNET_MESSENGER_KIND_PEER == message->header.kind)
277 peer->peer_messages++;
278
279 if (peer->props->num_hosts == peer->peer_messages)
280 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier2_wait_cb, peer);
281 else if (peer->props->num_hosts < peer->peer_messages)
282 {
283 if (peer->wait)
284 GNUNET_cancel_wait_barrier(peer->wait);
285
286 peer->wait = NULL;
287
288 if (peer->op_task)
289 GNUNET_SCHEDULER_cancel(peer->op_task);
290
291 peer->message = "peer";
292 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
293 }
294}
295
296static void
297second_stage (void *cls)
298{
299 struct test_peer *peer = cls;
300
301 GNUNET_assert(peer != NULL);
302
303 peer->op_task = NULL;
304
305 struct GNUNET_HashCode hash;
306 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
307
308 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x10))
309 {
310 struct GNUNET_MESSENGER_Room *room;
311 room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
312
313 if (peer->room)
314 GNUNET_assert(room == peer->room);
315 else
316 GNUNET_assert(room != NULL);
317
318 peer->room = room;
319 }
320
321 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x20))
322 {
323 unsigned int door = peer->props->cfg->doors[peer->num - 1];
324
325 if (door == 0)
326 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
327 else
328 door = door - 1;
329
330 struct GNUNET_MESSENGER_Room *room;
331 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
332
333 if (peer->room)
334 GNUNET_assert(room == peer->room);
335 else
336 GNUNET_assert(room != NULL);
337
338 peer->room = room;
339 }
340}
341
342static void
343on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo,
344 const char *emsg)
345{
346 struct test_peer *peer = cb_cls;
347
348 GNUNET_assert(peer != NULL);
349
350 if (emsg)
351 {
352 peer->message = GNUNET_strdup(emsg);
353 peer->op_task = GNUNET_SCHEDULER_add_now (&end_error_cb, peer);
354 return;
355 }
356
357 if (!pinfo)
358 {
359 peer->message = "info";
360 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
361 return;
362 }
363
364 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
365 {
366 peer->message = "config";
367 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
368 return;
369 }
370
371 peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, NULL, &on_message, peer);
372
373 GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_get_peer_identity(
374 pinfo->result.cfg, &(peer->peer_id)
375 ));
376
377 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x01))
378 {
379 struct GNUNET_HashCode hash;
380 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
381
382 peer->room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
383
384 GNUNET_assert(peer->room != NULL);
385 }
386 else
387 peer->room = NULL;
388
389 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier_wait_cb, peer);
390}
391
392/**
393 * Main function for a peer of the testcase.
394 *
395 * @param cls Closure
396 * @param event Information about the event
397 */
398static void
399run (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
400{
401 struct test_properties *properties = cls;
402
403 GNUNET_assert(properties != NULL);
404
405 if (GNUNET_TESTBED_ET_PEER_START != event->type)
406 {
407 fprintf (stderr, "Testcase failed (operation: 'start').\n");
408
409 GNUNET_SCHEDULER_shutdown ();
410 return;
411 }
412
413 struct test_peer *peer = &(properties->peers[properties->num_peer++]);
414
415 peer->props = properties;
416 peer->num = properties->num_peer;
417
418 peer->peer = event->details.peer_start.peer;
419 peer->op = GNUNET_TESTBED_peer_get_information (peer->peer, GNUNET_TESTBED_PIT_CONFIGURATION, on_peer, peer);
420}
421
422static void
423barrier2_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
424{
425 struct test_properties *properties = cls;
426
427 GNUNET_assert(properties != NULL);
428
429 if (properties->barrier == barrier)
430 properties->barrier = NULL;
431
432 if (GNUNET_SYSERR == status)
433 {
434 fprintf (stderr, "Testcase failed (operation: 'barrier2').\n");
435
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438 }
439 else if (GNUNET_OK == status)
440 {
441 if (properties->die_task)
442 GNUNET_SCHEDULER_cancel(properties->die_task);
443
444 properties->die_task = GNUNET_SCHEDULER_add_delayed (
445 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count),
446 &end_cb, properties
447 );
448 }
449}
450
451static void
452barrier_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
453{
454 struct test_properties *properties = cls;
455
456 GNUNET_assert(properties != NULL);
457
458 if (properties->barrier == barrier)
459 properties->barrier = NULL;
460 else if (!properties->barrier)
461 return;
462
463 if (properties->num_peer != properties->cfg->count)
464 {
465 fprintf (stderr, "Testcase failed (operation: 'process').\n");
466
467 GNUNET_SCHEDULER_shutdown ();
468 return;
469 }
470
471 if (GNUNET_SYSERR == status)
472 {
473 fprintf (stderr, "Testcase failed (operation: 'barrier').\n");
474
475 GNUNET_SCHEDULER_shutdown ();
476 return;
477 }
478 else if (GNUNET_OK == status)
479 {
480 properties->barrier = GNUNET_init_barrier (properties->num_peer, &barrier2_cb, properties);
481
482 for (unsigned int i = 0; i < properties->num_peer; i++)
483 properties->peers[i].op_task = GNUNET_SCHEDULER_add_now (&second_stage, &(properties->peers[i]));
484 }
485}
486
487static void
488init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
489 unsigned int links_succeeded, unsigned int links_failed)
490{
491 struct test_properties *properties = cls;
492
493 GNUNET_assert(properties != NULL);
494
495 properties->end_task = GNUNET_SCHEDULER_add_shutdown(&shutdown_cb, properties);
496 properties->die_task = GNUNET_SCHEDULER_add_delayed (
497 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count * 5),
498 &end_badly_cb, properties
499 );
500}
501
502int
503GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg)
504{
505 struct test_properties properties;
506 memset(&properties, 0, sizeof(properties));
507
508 properties.cfg = cfg;
509 properties.peers = GNUNET_new_array(cfg->count, struct test_peer);
510
511 for (unsigned int i = 0; i < cfg->count; i++)
512 if (0 != (cfg->stages[i] & 0x11))
513 properties.num_hosts++;
514
515 properties.status = 1;
516 properties.barrier = GNUNET_init_barrier (cfg->count, &barrier_cb, &properties);
517
518 if (GNUNET_OK != GNUNET_TESTBED_test_run (test_name, "test_messenger_api.conf",
519 cfg->count,
520 (1LL << GNUNET_TESTBED_ET_PEER_START),
521 &run, &properties,
522 &init, &properties))
523 return 1;
524
525 GNUNET_free(properties.peers);
526
527 return properties.status;
528}
diff --git a/src/messenger/testing_messenger_setup.h b/src/messenger/testing_messenger_setup.h
new file mode 100644
index 000000000..5e6b5d461
--- /dev/null
+++ b/src/messenger/testing_messenger_setup.h
@@ -0,0 +1,39 @@
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 * @file messenger/testing_messenger_setup.h
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_SETUP_H_
27#define GNUNET_TESTING_MESSENGER_SETUP_H_
28
29struct test_configuration
30{
31 unsigned int count;
32 unsigned int *doors;
33 unsigned int *stages;
34};
35
36int
37GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg);
38
39#endif /* GNUNET_TESTING_MESSENGER_SETUP_H_ */