diff options
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 | |||
550 | src/zonemaster/gnunet-service-zonemaster-monitor.c | 550 | src/zonemaster/gnunet-service-zonemaster-monitor.c |
551 | src/zonemaster/gnunet-service-zonemaster.c | 551 | src/zonemaster/gnunet-service-zonemaster.c |
552 | src/fs/fs_api.h | 552 | src/fs/fs_api.h |
553 | src/include/gnunet_identity_service.h | ||
554 | src/include/gnunet_messenger_service.h | ||
553 | src/testbed/testbed_api.h | 555 | src/testbed/testbed_api.h |
554 | src/testbed/testbed_api_operations.h | 556 | src/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 | */ |
161 | struct GNUNET_MESSENGER_MessageHeader | 179 | struct 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 | */ |
192 | struct GNUNET_MESSENGER_MessageInfo | 213 | struct 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 | */ |
208 | struct GNUNET_MESSENGER_MessageJoin | 232 | struct 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 | */ |
219 | struct GNUNET_MESSENGER_MessageLeave | 246 | struct 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 | */ |
226 | struct GNUNET_MESSENGER_MessageName | 256 | struct 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 | */ |
237 | struct GNUNET_MESSENGER_MessageKey | 270 | struct 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 | */ |
248 | struct GNUNET_MESSENGER_MessagePeer | 284 | struct 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 | */ |
259 | struct GNUNET_MESSENGER_MessageId | 298 | struct 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 | */ |
270 | struct GNUNET_MESSENGER_MessageMiss | 312 | struct 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 | */ |
281 | struct GNUNET_MESSENGER_MessageMerge | 326 | struct 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 | */ |
292 | struct GNUNET_MESSENGER_MessageRequest | 340 | struct 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 | */ |
303 | struct GNUNET_MESSENGER_MessageInvite | 354 | struct 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 | */ |
319 | struct GNUNET_MESSENGER_MessageText | 373 | struct 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 | */ |
330 | struct GNUNET_MESSENGER_MessageFile | 387 | struct 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 | */ |
356 | struct GNUNET_MESSENGER_MessagePrivate | 416 | struct 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 | */ | ||
440 | struct 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 | */ |
377 | struct GNUNET_MESSENGER_MessageBody | 456 | struct 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 | */ | ||
497 | enum 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 | */ |
421 | typedef void | 517 | typedef 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 | */ |
432 | typedef void | 533 | typedef 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 | */ | ||
548 | typedef 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 | */ |
448 | struct GNUNET_MESSENGER_Handle* | 564 | struct 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 | */ |
464 | int | 580 | int |
465 | GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle); | 581 | GNUNET_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 | */ |
472 | void | 588 | void |
473 | GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle); | 589 | GNUNET_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 | */ |
481 | const char* | 597 | const 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 | */ |
493 | int | 609 | int |
494 | GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); | 610 | GNUNET_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 | */ |
502 | const struct GNUNET_IDENTITY_PublicKey* | 618 | const struct GNUNET_IDENTITY_PublicKey* |
503 | GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle); | 619 | GNUNET_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 | */ |
521 | struct GNUNET_MESSENGER_Room* | 637 | struct GNUNET_MESSENGER_Room* |
522 | GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | 638 | GNUNET_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 | */ |
542 | struct GNUNET_MESSENGER_Room* | 658 | struct GNUNET_MESSENGER_Room* |
543 | GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | 659 | GNUNET_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 | */ |
555 | void | 671 | void |
556 | GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room); | 672 | GNUNET_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 | */ |
567 | struct GNUNET_MESSENGER_Contact* | 683 | struct GNUNET_MESSENGER_Contact* |
568 | GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id); | 684 | GNUNET_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 | */ |
576 | const char* | 692 | const char* |
577 | GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact); | 693 | GNUNET_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 | */ |
585 | const struct GNUNET_IDENTITY_PublicKey* | 701 | const struct GNUNET_IDENTITY_PublicKey* |
586 | GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact); | 702 | GNUNET_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 | */ |
599 | void | 722 | void |
600 | GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message); | 723 | GNUNET_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 | */ |
609 | const struct GNUNET_MESSENGER_Message* | 733 | const struct GNUNET_MESSENGER_Message* |
610 | GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); | 734 | GNUNET_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 | */ | ||
746 | int | ||
747 | GNUNET_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 | |||
2 | gnunet-messenger | 2 | gnunet-messenger |
3 | test_messenger_api | 3 | test_messenger_api |
4 | test_messenger_anonymous | 4 | test_messenger_anonymous |
5 | test_messenger_sync_client | ||
6 | test_messenger_async_client | ||
7 | test_messenger_worst_client | ||
8 | test_messenger_sync_p2p | ||
9 | test_messenger_async_p2p | ||
10 | test_messenger_worst_p2p | ||
11 | test_messenger_server | ||
12 | test_messenger_growth | ||
13 | test_messenger_ring | ||
14 | test_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 | ||
32 | libgnunetmessenger_common_la_SOURCES = \ | 32 | libgnunetmessenger_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 | ||
36 | libgnunetmessenger_common_la_LIBADD = \ | 39 | libgnunetmessenger_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 | ||
45 | libgnunetmessenger_la_SOURCES = \ | 49 | libgnunetmessenger_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 |
50 | libgnunetmessenger_la_LIBADD = \ | 53 | libgnunetmessenger_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 | ||
86 | gnunet_service_messenger_LDADD = \ | 93 | gnunet_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 = \ | |||
94 | check_PROGRAMS = \ | 101 | check_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 | ||
99 | if ENABLE_TEST_RUN | 115 | if ENABLE_TEST_RUN |
100 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | 116 | AM_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 | ||
121 | test_messenger_comm0_SOURCES = \ | 137 | test_messenger_sync_client_SOURCES = \ |
122 | test_messenger_comm0.c | 138 | test_messenger_sync_client.c \ |
123 | test_messenger_comm0_LDADD = \ | 139 | testing_messenger_barrier.c testing_messenger_barrier.h \ |
140 | testing_messenger_setup.c testing_messenger_setup.h | ||
141 | test_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 | |||
148 | test_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 | ||
152 | test_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 | |||
159 | test_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 | ||
163 | test_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 | |||
170 | test_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 | ||
174 | test_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 | |||
181 | test_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 | ||
185 | test_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 | |||
192 | test_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 | ||
196 | test_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 | |||
203 | test_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 | ||
207 | test_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 | |||
214 | test_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 | ||
218 | test_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 | |||
225 | test_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 | ||
229 | test_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 | |||
236 | test_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 | ||
240 | test_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 | */ |
42 | void | 44 | void |
43 | on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 45 | on_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 | */ |
91 | static void | 101 | static void |
92 | shutdown_hook (void *cls) | 102 | shutdown_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 | ||
121 | static int | ||
122 | iterate_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 | |||
133 | int 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 | */ |
116 | static void | 140 | static void |
117 | read_stdio (void *cls) | 141 | read_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 | */ |
153 | static void | 180 | static void |
154 | listen_stdio (void *cls) | 181 | listen_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 | */ |
176 | static void | 201 | static void |
177 | idle (void *cls) | 202 | idle (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 | */ |
198 | static void | 223 | static void |
199 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | 224 | on_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 | */ |
261 | static void | 295 | static void |
262 | run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) | 296 | run (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 | */ |
276 | int | 310 | int |
277 | main (int argc, char **argv) | 311 | main (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) | |||
187 | static int | 179 | static int |
188 | check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg) | 180 | check_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 | |||
203 | check_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 | ||
264 | end_handling: | ||
228 | GNUNET_SERVICE_client_continue (msg_client->client); | 265 | GNUNET_SERVICE_client_continue (msg_client->client); |
229 | } | 266 | } |
230 | 267 | ||
231 | static void | 268 | static void |
232 | handle_get_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) | 269 | handle_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 | ||
304 | end_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 | */ |
278 | static void | 336 | static void |
279 | run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service) | 337 | run (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 | |||
74 | struct GNUNET_MESSENGER_KeyMessage | 74 | struct 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 | |||
105 | struct GNUNET_MESSENGER_SendMessage | 104 | struct 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 | */ | ||
115 | struct 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 | |||
114 | struct GNUNET_MESSENGER_RecvMessage | 126 | struct 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 @@ | |||
28 | size_t | 28 | size_t |
29 | count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels) | 29 | count_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 | */ |
37 | size_t | 37 | size_t |
38 | count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels); | 38 | count_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 | */ |
50 | int | 50 | int |
51 | should_connect_tunnel_to (size_t count, size_t src, size_t dst); | 51 | should_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 | */ |
63 | int | 63 | int |
64 | required_connection_between (size_t count, size_t src, size_t dst); | 64 | required_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 | |||
28 | struct GNUNET_MESSENGER_SrvContact* | ||
29 | create_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 | |||
41 | void | ||
42 | destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact) | ||
43 | { | ||
44 | if (contact->name) | ||
45 | GNUNET_free(contact->name); | ||
46 | |||
47 | GNUNET_free(contact); | ||
48 | } | ||
49 | |||
50 | const char* | ||
51 | get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact) | ||
52 | { | ||
53 | return contact->name; | ||
54 | } | ||
55 | |||
56 | void | ||
57 | set_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 | |||
67 | const struct GNUNET_IDENTITY_PublicKey* | ||
68 | get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact) | ||
69 | { | ||
70 | return &(contact->public_key); | ||
71 | } | ||
72 | |||
73 | void | ||
74 | increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact) | ||
75 | { | ||
76 | contact->rc++; | ||
77 | } | ||
78 | |||
79 | int | ||
80 | decrease_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 | |||
88 | const struct GNUNET_HashCode* | ||
89 | get_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 | |||
33 | struct 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 | */ | ||
47 | struct GNUNET_MESSENGER_SrvContact* | ||
48 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key); | ||
49 | |||
50 | /** | ||
51 | * Destroys a contact and frees its memory fully. | ||
52 | * | ||
53 | * @param contact Contact | ||
54 | */ | ||
55 | void | ||
56 | destroy_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 | */ | ||
64 | const char* | ||
65 | get_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 | */ | ||
73 | void | ||
74 | set_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 | */ | ||
82 | const struct GNUNET_IDENTITY_PublicKey* | ||
83 | get_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 | */ | ||
90 | void | ||
91 | increase_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 | */ | ||
100 | int | ||
101 | decrease_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 | */ | ||
109 | const struct GNUNET_HashCode* | ||
110 | get_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 | |||
30 | static void | ||
31 | callback_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 | |||
43 | void | ||
44 | init_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 | |||
60 | static int | ||
61 | iterate_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 | |||
68 | void | ||
69 | clear_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 | |||
114 | static void | ||
115 | callback_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 | |||
141 | void | ||
142 | create_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 | |||
160 | static void | ||
161 | callback_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 | |||
185 | void | ||
186 | lookup_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 | |||
221 | struct GNUNET_MESSENGER_Ego* | ||
222 | update_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 | |||
246 | static void | ||
247 | callback_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 | |||
279 | void | ||
280 | rename_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 | |||
34 | struct GNUNET_MESSENGER_Ego; | ||
35 | struct GNUNET_MESSENGER_EgoStore; | ||
36 | |||
37 | typedef void | ||
38 | (*GNUNET_MESSENGER_EgoLookupCallback) (void *cls, const char *identifier, | ||
39 | const struct GNUNET_MESSENGER_Ego *ego); | ||
40 | |||
41 | struct 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 | |||
56 | struct 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 | |||
69 | struct 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 | */ | ||
89 | void | ||
90 | init_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 | */ | ||
97 | void | ||
98 | clear_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 | */ | ||
109 | void | ||
110 | create_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 | */ | ||
122 | void | ||
123 | lookup_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 | */ | ||
135 | struct GNUNET_MESSENGER_Ego* | ||
136 | update_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 | */ | ||
148 | void | ||
149 | rename_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 | |||
31 | struct GNUNET_MESSENGER_SrvHandle* | 33 | struct GNUNET_MESSENGER_SrvHandle* |
32 | create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) | 34 | create_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 | |||
58 | void | 59 | void |
59 | destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle) | 60 | destroy_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 | ||
76 | void | 76 | void |
77 | get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir) | 77 | get_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 | |||
87 | static int | 89 | static int |
88 | create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | 90 | create_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 | |||
108 | const struct GNUNET_ShortHashCode* | 114 | const struct GNUNET_ShortHashCode* |
109 | get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | 115 | get_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 | ||
114 | void | 122 | int |
115 | change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | 123 | change_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 | |||
156 | send_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 | ||
150 | static void | 167 | static void |
151 | change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | 168 | change_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 | ||
175 | static void | 194 | static void |
176 | change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, struct GNUNET_MESSENGER_Ego *ego) | 195 | change_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 | ||
192 | struct GNUNET_MESSENGER_Ego* | 218 | struct GNUNET_MESSENGER_MessageHandle |
193 | get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle) | 219 | { |
220 | struct GNUNET_MESSENGER_SrvHandle *handle; | ||
221 | struct GNUNET_MESSENGER_Message *message; | ||
222 | }; | ||
223 | |||
224 | static int | ||
225 | iterate_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 | |||
234 | void | ||
235 | set_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 | |||
251 | const struct GNUNET_MESSENGER_Ego* | ||
252 | get_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 | ||
212 | void | 273 | static void |
213 | setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | 274 | callback_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 | ||
222 | struct GNUNET_MESSENGER_MessageHandle | 287 | void |
223 | { | 288 | setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) |
224 | struct GNUNET_MESSENGER_SrvHandle *handle; | ||
225 | struct GNUNET_MESSENGER_Message *message; | ||
226 | }; | ||
227 | |||
228 | static int | ||
229 | iterate_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 | ||
238 | static void | 297 | static void |
239 | callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) | 298 | callback_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 | ||
265 | int | 312 | void |
266 | update_handle (struct GNUNET_MESSENGER_SrvHandle *handle) | 313 | update_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 | ||
284 | int | 328 | static void |
285 | set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | 329 | callback_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 | |||
385 | void | ||
386 | set_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 | ||
346 | int | 405 | int |
347 | open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | 406 | open_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 | |||
356 | entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, | 417 | entry_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 | |||
365 | int | 428 | int |
366 | close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | 429 | close_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 | ||
374 | int | 439 | int |
375 | send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | 440 | send_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 | |||
468 | static const struct GNUNET_HashCode* | ||
469 | get_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 | |||
477 | void | ||
478 | notify_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 | ||
402 | static int callback_scan_for_rooms(void* cls, const char *filename) { | 539 | static int |
403 | struct GNUNET_MESSENGER_SrvHandle* handle = cls; | 540 | callback_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 | ||
422 | void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) { | 560 | void |
423 | char* id_dir; | 561 | load_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 | ||
440 | static int | 582 | static int |
441 | iterate_save_rooms(void* cls, const struct GNUNET_HashCode* key, void* value) | 583 | iterate_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 | ||
484 | void save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) | 624 | void |
625 | save_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 | */ |
63 | struct GNUNET_MESSENGER_SrvHandle* | 62 | struct 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 | */ |
71 | void | 70 | void |
72 | destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle); | 71 | destroy_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 | */ |
82 | void | 81 | void |
83 | get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir); | 82 | get_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 | */ |
94 | const struct GNUNET_ShortHashCode* | 93 | const struct GNUNET_ShortHashCode* |
95 | get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | 94 | get_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 | */ |
106 | void | 107 | int |
107 | change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | 108 | change_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 | */ | ||
117 | void | ||
118 | set_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 | */ |
116 | struct GNUNET_MESSENGER_Ego* | 126 | const struct GNUNET_MESSENGER_Ego* |
117 | get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle); | 127 | get_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 | */ |
125 | void | 135 | void |
126 | setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); | 136 | setup_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 | */ |
135 | int | 144 | void |
136 | update_handle (struct GNUNET_MESSENGER_SrvHandle *handle); | 145 | update_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 | */ |
148 | int | 156 | void |
149 | set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); | 157 | set_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 | */ |
159 | int | 167 | int |
160 | open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | 168 | open_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 | */ |
171 | int | 179 | int |
172 | entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, | 180 | entry_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 | */ |
183 | int | 191 | int |
184 | close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | 192 | close_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 | */ |
194 | int | 202 | int |
195 | send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | 203 | send_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 | */ | ||
215 | void | ||
216 | notify_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 | */ |
204 | void | 226 | void |
205 | load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); | 227 | load_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 | */ |
213 | void | 235 | void |
214 | save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); | 236 | save_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 | ||
57 | void | 57 | void |
58 | add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) | 58 | add_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 | ||
67 | int | 69 | int |
68 | remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) | 70 | remove_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 | ||
85 | void* | 89 | struct GNUNET_MESSENGER_SrvHandle* |
86 | find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key) | 90 | find_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 | ||
33 | struct GNUNET_MESSENGER_SrvHandle; | ||
34 | |||
33 | struct GNUNET_MESSENGER_ListHandle | 35 | struct 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 | ||
41 | struct GNUNET_MESSENGER_ListHandles | 43 | struct 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 | */ |
52 | void | 54 | void |
53 | init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); | 55 | init_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 | */ |
60 | void | 62 | void |
61 | clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); | 63 | clear_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 | */ |
69 | void | 71 | void |
70 | add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); | 72 | add_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 | */ |
80 | int | 82 | int |
81 | remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); | 83 | remove_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 | */ |
93 | void* | 95 | struct GNUNET_MESSENGER_SrvHandle* |
94 | find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key); | 96 | find_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) | |||
54 | void | 54 | void |
55 | add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) | 55 | add_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 | ||
64 | void | 66 | void |
67 | copy_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 | |||
77 | void | ||
65 | remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) | 78 | remove_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 | |||
93 | void | ||
94 | load_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 | |||
127 | void | ||
128 | save_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 | ||
33 | struct GNUNET_MESSENGER_ListMessage | 34 | struct 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 | */ |
52 | void | 53 | void |
53 | init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); | 54 | init_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 | */ |
60 | void | 61 | void |
61 | clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); | 62 | clear_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 | */ |
69 | void | 70 | void |
70 | add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); | 71 | add_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 | */ | ||
79 | void | ||
80 | copy_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 | */ |
78 | void | 88 | void |
79 | remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); | 89 | remove_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 | */ | ||
97 | void | ||
98 | load_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 | */ | ||
106 | void | ||
107 | save_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 | |||
30 | struct GNUNET_MESSENGER_Member* | ||
31 | create_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 | |||
52 | static int | ||
53 | iterate_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 | |||
60 | void | ||
61 | destroy_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 | |||
71 | const struct GNUNET_ShortHashCode* | ||
72 | get_member_id (const struct GNUNET_MESSENGER_Member *member) | ||
73 | { | ||
74 | GNUNET_assert (member); | ||
75 | |||
76 | return &(member->id); | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | callback_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 | |||
96 | void | ||
97 | load_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 | |||
121 | destroy_config: | ||
122 | |||
123 | GNUNET_CONFIGURATION_destroy (cfg); | ||
124 | |||
125 | free_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 | |||
140 | static int | ||
141 | iterate_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 | |||
157 | void | ||
158 | load_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 | |||
170 | static int | ||
171 | iterate_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 | |||
188 | void | ||
189 | save_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 | |||
222 | static void | ||
223 | sync_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 | |||
236 | static int | ||
237 | iterate_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 | |||
247 | void | ||
248 | sync_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 | |||
255 | struct GNUNET_MESSENGER_MemberSession* | ||
256 | get_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 | |||
266 | struct 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 | |||
273 | static int | ||
274 | iterate_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 | |||
286 | static struct GNUNET_MESSENGER_MemberSession* | ||
287 | try_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 | |||
302 | struct GNUNET_MESSENGER_MemberSession* | ||
303 | get_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 | |||
325 | void | ||
326 | add_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 | |||
341 | void | ||
342 | remove_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 | |||
354 | struct GNUNET_MESSENGER_ClosureIterateSessions { | ||
355 | GNUNET_MESSENGER_MemberIteratorCallback it; | ||
356 | void *cls; | ||
357 | }; | ||
358 | |||
359 | static int | ||
360 | iterate_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 | |||
368 | int | ||
369 | iterate_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 | |||
36 | struct 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 | */ | ||
54 | struct GNUNET_MESSENGER_Member* | ||
55 | create_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 | */ | ||
62 | void | ||
63 | destroy_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 | */ | ||
71 | const struct GNUNET_ShortHashCode* | ||
72 | get_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 | */ | ||
82 | void | ||
83 | load_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 | */ | ||
92 | void | ||
93 | load_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 | */ | ||
102 | void | ||
103 | save_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 | */ | ||
111 | void | ||
112 | sync_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 | */ | ||
122 | struct GNUNET_MESSENGER_MemberSession* | ||
123 | get_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 | */ | ||
135 | struct GNUNET_MESSENGER_MemberSession* | ||
136 | get_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 | */ | ||
145 | void | ||
146 | add_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 | */ | ||
154 | void | ||
155 | remove_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 | */ | ||
167 | int | ||
168 | iterate_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 | |||
33 | struct GNUNET_MESSENGER_MemberSession* | ||
34 | create_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 | |||
79 | static void | ||
80 | check_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 | |||
139 | completion: | ||
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 | |||
157 | static int | ||
158 | iterate_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 | |||
168 | struct GNUNET_MESSENGER_MemberSession* | ||
169 | switch_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 | |||
236 | void | ||
237 | destroy_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 | |||
257 | int | ||
258 | reset_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 | |||
279 | clear_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 | |||
290 | void | ||
291 | close_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 | |||
299 | int | ||
300 | is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session) | ||
301 | { | ||
302 | GNUNET_assert(session); | ||
303 | |||
304 | return session->closed; | ||
305 | } | ||
306 | |||
307 | int | ||
308 | is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session) | ||
309 | { | ||
310 | GNUNET_assert(session); | ||
311 | |||
312 | return session->completed; | ||
313 | } | ||
314 | |||
315 | const struct GNUNET_HashCode* | ||
316 | get_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 | |||
323 | const struct GNUNET_ShortHashCode* | ||
324 | get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session) | ||
325 | { | ||
326 | GNUNET_assert(session); | ||
327 | |||
328 | return get_member_id(session->member); | ||
329 | } | ||
330 | |||
331 | const struct GNUNET_IDENTITY_PublicKey* | ||
332 | get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session) | ||
333 | { | ||
334 | GNUNET_assert(session); | ||
335 | |||
336 | return &(session->public_key); | ||
337 | } | ||
338 | |||
339 | const struct GNUNET_HashCode* | ||
340 | get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session) | ||
341 | { | ||
342 | GNUNET_assert(session); | ||
343 | |||
344 | return &(session->context); | ||
345 | } | ||
346 | |||
347 | struct GNUNET_MESSENGER_Contact* | ||
348 | get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session) | ||
349 | { | ||
350 | GNUNET_assert (session); | ||
351 | |||
352 | return session->contact; | ||
353 | } | ||
354 | |||
355 | int 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 | |||
370 | int | ||
371 | check_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 | |||
382 | static void | ||
383 | update_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 | |||
393 | void | ||
394 | update_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 | |||
420 | static void | ||
421 | clear_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 | |||
430 | void | ||
431 | clear_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 | |||
439 | struct GNUNET_MESSENGER_MemberSessionHistoryEntry | ||
440 | { | ||
441 | struct GNUNET_HashCode hash; | ||
442 | unsigned char ownership; | ||
443 | }; | ||
444 | |||
445 | static void | ||
446 | load_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 | |||
487 | void | ||
488 | load_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 | |||
521 | destroy_config: | ||
522 | GNUNET_CONFIGURATION_destroy (cfg); | ||
523 | |||
524 | free_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 | |||
545 | static struct GNUNET_MESSENGER_MemberSession* | ||
546 | get_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 | |||
563 | void | ||
564 | load_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 | |||
604 | destroy_config: | ||
605 | GNUNET_CONFIGURATION_destroy (cfg); | ||
606 | |||
607 | free_config: | ||
608 | GNUNET_free(config_file); | ||
609 | } | ||
610 | |||
611 | static int | ||
612 | iterate_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 | |||
623 | static void | ||
624 | save_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 | |||
649 | void | ||
650 | save_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 | |||
38 | struct 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 | */ | ||
65 | struct GNUNET_MESSENGER_MemberSession* | ||
66 | create_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 | */ | ||
81 | struct GNUNET_MESSENGER_MemberSession* | ||
82 | switch_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 | */ | ||
91 | void | ||
92 | destroy_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 | */ | ||
104 | int | ||
105 | reset_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 | */ | ||
117 | void | ||
118 | close_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 | */ | ||
126 | int | ||
127 | is_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 | */ | ||
138 | int | ||
139 | is_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 | */ | ||
147 | const struct GNUNET_HashCode* | ||
148 | get_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 | */ | ||
156 | const struct GNUNET_ShortHashCode* | ||
157 | get_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 | */ | ||
165 | const struct GNUNET_IDENTITY_PublicKey* | ||
166 | get_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 | */ | ||
174 | const struct GNUNET_HashCode* | ||
175 | get_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 | */ | ||
183 | struct GNUNET_MESSENGER_Contact* | ||
184 | get_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 | */ | ||
198 | int | ||
199 | verify_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 | */ | ||
213 | int | ||
214 | check_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 | */ | ||
227 | void | ||
228 | update_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 | */ | ||
239 | void | ||
240 | clear_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 | */ | ||
251 | void | ||
252 | load_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 | */ | ||
262 | void | ||
263 | load_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 | */ | ||
272 | void | ||
273 | save_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 | |||
32 | void | ||
33 | init_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 | |||
41 | static int | ||
42 | iterate_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 | |||
49 | void | ||
50 | clear_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 | |||
59 | struct GNUNET_MESSENGER_ContactStore* | ||
60 | get_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 | |||
69 | const struct GNUNET_HashCode* | ||
70 | get_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 | |||
77 | static int | ||
78 | callback_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 | |||
96 | static int | ||
97 | iterate_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 | |||
116 | static int | ||
117 | iterate_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 | |||
128 | void | ||
129 | load_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 | |||
145 | static int | ||
146 | iterate_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 | |||
166 | void | ||
167 | save_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 | |||
181 | struct GNUNET_MESSENGER_Member* | ||
182 | get_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 | |||
189 | struct GNUNET_MESSENGER_Member* | ||
190 | get_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 | |||
199 | struct GNUNET_MESSENGER_Member* | ||
200 | add_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 | |||
224 | struct GNUNET_MESSENGER_ClosureIterateMembers { | ||
225 | GNUNET_MESSENGER_MemberIteratorCallback it; | ||
226 | void *cls; | ||
227 | }; | ||
228 | |||
229 | static int | ||
230 | iterate_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 | |||
238 | int | ||
239 | iterate_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 | |||
35 | struct GNUNET_MESSENGER_SrvRoom; | ||
36 | |||
37 | struct GNUNET_MESSENGER_Member; | ||
38 | struct GNUNET_MESSENGER_MemberSession; | ||
39 | |||
40 | struct GNUNET_MESSENGER_MemberStore | ||
41 | { | ||
42 | struct GNUNET_MESSENGER_SrvRoom *room; | ||
43 | |||
44 | struct GNUNET_CONTAINER_MultiShortmap *members; | ||
45 | }; | ||
46 | |||
47 | typedef 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 | */ | ||
58 | void | ||
59 | init_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 | */ | ||
66 | void | ||
67 | clear_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 | */ | ||
75 | struct GNUNET_MESSENGER_ContactStore* | ||
76 | get_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 | */ | ||
84 | const struct GNUNET_HashCode* | ||
85 | get_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 | */ | ||
93 | void | ||
94 | load_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 | */ | ||
102 | void | ||
103 | save_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 | */ | ||
113 | struct GNUNET_MESSENGER_Member* | ||
114 | get_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 | */ | ||
124 | struct GNUNET_MESSENGER_Member* | ||
125 | get_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 | */ | ||
134 | struct GNUNET_MESSENGER_Member* | ||
135 | add_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 | */ | ||
147 | int | ||
148 | iterate_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 | ||
28 | void | 28 | static void |
29 | handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 29 | handle_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 | ||
54 | void | 38 | void |
55 | handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 39 | handle_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 | ||
64 | void | 49 | void |
65 | handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 50 | handle_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 | ||
79 | void | 59 | void |
80 | handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 60 | handle_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) | 71 | void |
91 | add_to_list_messages (&(info->session_messages), hash); | 72 | handle_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 | ||
94 | void | 78 | void |
95 | handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 79 | handle_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 | ||
105 | void | 89 | void |
106 | handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 90 | handle_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 | ||
117 | void | 96 | void |
118 | handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 97 | handle_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 | |||
111 | void | ||
112 | handle_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 | */ |
46 | void | 47 | void |
47 | handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 48 | handle_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 | */ |
59 | void | 60 | void |
60 | handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 61 | handle_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 | */ |
72 | void | 73 | void |
73 | handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 74 | handle_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 | */ |
85 | void | 86 | void |
86 | handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 87 | handle_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 | */ |
98 | void | 99 | void |
99 | handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 100 | handle_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 | */ |
111 | void | 112 | void |
112 | handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 113 | handle_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 | */ |
124 | void | 125 | void |
125 | handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 126 | handle_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 | */ | ||
138 | void | ||
139 | handle_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 | ||
29 | struct GNUNET_MESSENGER_Message* | 30 | struct GNUNET_MESSENGER_Message* |
30 | create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members) | 31 | create_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 | ||
48 | struct GNUNET_MESSENGER_Message* | 48 | struct GNUNET_MESSENGER_Message* |
49 | create_message_join (struct GNUNET_MESSENGER_Ego *ego) | 49 | create_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 () | |||
67 | struct GNUNET_MESSENGER_Message* | 70 | struct GNUNET_MESSENGER_Message* |
68 | create_message_name (const char *name) | 71 | create_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) | |||
79 | struct GNUNET_MESSENGER_Message* | 85 | struct GNUNET_MESSENGER_Message* |
80 | create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key) | 86 | create_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) | |||
91 | struct GNUNET_MESSENGER_Message* | 100 | struct GNUNET_MESSENGER_Message* |
92 | create_message_peer (const struct GNUNET_MESSENGER_Service *service) | 101 | create_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) | |||
108 | struct GNUNET_MESSENGER_Message* | 120 | struct GNUNET_MESSENGER_Message* |
109 | create_message_id (const struct GNUNET_ShortHashCode *unique_id) | 121 | create_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) | |||
121 | struct GNUNET_MESSENGER_Message* | 136 | struct GNUNET_MESSENGER_Message* |
122 | create_message_miss (const struct GNUNET_PeerIdentity *peer) | 137 | create_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) | |||
136 | struct GNUNET_MESSENGER_Message* | 154 | struct GNUNET_MESSENGER_Message* |
137 | create_message_merge (const struct GNUNET_HashCode *previous) | 155 | create_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) | |||
149 | struct GNUNET_MESSENGER_Message* | 170 | struct GNUNET_MESSENGER_Message* |
150 | create_message_request (const struct GNUNET_HashCode *hash) | 171 | create_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) | |||
168 | struct GNUNET_MESSENGER_Message* | 192 | struct GNUNET_MESSENGER_Message* |
169 | create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) | 193 | create_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 | |||
182 | struct GNUNET_MESSENGER_Message* | 209 | struct GNUNET_MESSENGER_Message* |
183 | create_message_text (const char *text) | 210 | create_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 | |||
224 | struct GNUNET_MESSENGER_Message* | ||
225 | create_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 | */ |
46 | struct GNUNET_MESSENGER_Message* | 47 | struct GNUNET_MESSENGER_Message* |
47 | create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members); | 48 | create_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 | */ |
56 | struct GNUNET_MESSENGER_Message* | 57 | struct GNUNET_MESSENGER_Message* |
57 | create_message_join (struct GNUNET_MESSENGER_Ego *ego); | 58 | create_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 | */ |
74 | struct GNUNET_MESSENGER_Message* | 75 | struct GNUNET_MESSENGER_Message* |
75 | create_message_name (const char *name); | 76 | create_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 | */ |
84 | struct GNUNET_MESSENGER_Message* | 85 | struct 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 | */ |
94 | struct GNUNET_MESSENGER_Message* | 95 | struct 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 | */ |
104 | struct GNUNET_MESSENGER_Message* | 105 | struct GNUNET_MESSENGER_Message* |
105 | create_message_id (const struct GNUNET_ShortHashCode *unique_id); | 106 | create_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 | */ |
114 | struct GNUNET_MESSENGER_Message* | 115 | struct GNUNET_MESSENGER_Message* |
115 | create_message_miss (const struct GNUNET_PeerIdentity *peer); | 116 | create_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 | */ |
125 | struct GNUNET_MESSENGER_Message* | 126 | struct GNUNET_MESSENGER_Message* |
126 | create_message_merge (const struct GNUNET_HashCode *previous); | 127 | create_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 | */ |
135 | struct GNUNET_MESSENGER_Message* | 136 | struct 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 | */ |
147 | struct GNUNET_MESSENGER_Message* | 148 | struct GNUNET_MESSENGER_Message* |
148 | create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key); | 149 | create_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 | */ |
157 | struct GNUNET_MESSENGER_Message* | 158 | struct GNUNET_MESSENGER_Message* |
158 | create_message_text (const char *text); | 159 | create_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 | */ | ||
169 | struct GNUNET_MESSENGER_Message* | ||
170 | create_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 | ||
29 | void | 28 | #include "gnunet-service-messenger_operation.h" |
30 | recv_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 | |||
80 | struct GNUNET_MESSENGER_MemberInfoSpread | ||
81 | { | ||
82 | struct GNUNET_MESSENGER_SrvRoom *room; | ||
83 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
84 | }; | ||
85 | 29 | ||
86 | static int | 30 | static int |
87 | iterate_send_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value) | 31 | iterate_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 | ||
108 | void | 45 | int |
109 | recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 46 | recv_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 | ||
134 | void | 70 | if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer)) |
135 | recv_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 | ||
141 | void | 74 | iterate_store_members(member_store, iterate_forward_members, tunnel); |
142 | recv_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 | ||
148 | void | 77 | check_room_peer_status(room, tunnel); |
149 | recv_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 | ||
155 | void | 82 | int |
156 | recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 83 | recv_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 | ||
178 | void | 100 | int |
179 | recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 101 | recv_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 | ||
188 | void | 112 | use_store_operation( |
189 | recv_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 | ||
195 | void | 119 | return GNUNET_YES; |
196 | recv_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 | */ |
44 | void | 48 | int |
45 | recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 49 | recv_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 | */ | ||
57 | void | ||
58 | recv_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 | */ | ||
70 | void | ||
71 | recv_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 | */ | ||
83 | void | ||
84 | recv_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 | */ | ||
96 | void | ||
97 | recv_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 | */ |
111 | void | 62 | int |
112 | recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 63 | recv_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 | */ | ||
126 | void | ||
127 | recv_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 | */ | ||
139 | void | ||
140 | recv_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 | */ |
155 | void | 77 | int |
156 | recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 78 | recv_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 | ||
29 | void | 28 | #include "gnunet-service-messenger_member.h" |
30 | send_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 | ||
46 | void | 32 | void |
47 | send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 33 | send_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 | |||
65 | void | ||
66 | send_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 | |||
73 | void | ||
74 | send_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 | |||
81 | void | ||
82 | send_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 | ||
89 | void | 39 | void |
90 | send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 40 | send_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 | ||
104 | void | 49 | void |
105 | send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 50 | send_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 | ||
112 | void | 55 | use_store_operation( |
113 | send_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 | */ | ||
45 | void | ||
46 | send_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 | */ |
60 | void | 46 | void |
61 | send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 47 | send_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 | */ | ||
75 | void | ||
76 | send_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 | */ | ||
90 | void | ||
91 | send_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 | */ | ||
105 | void | ||
106 | send_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 | */ |
120 | void | 59 | void |
121 | send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 60 | send_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 | */ | ||
135 | void | ||
136 | send_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 | */ |
150 | void | 72 | void |
151 | send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 73 | send_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 @@ | |||
29 | void | 29 | void |
30 | init_message_store (struct GNUNET_MESSENGER_MessageStore *store) | 30 | init_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 | ||
38 | static int | 44 | static 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 | ||
64 | static int | ||
65 | iterate_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 | |||
58 | void | 74 | void |
59 | clear_message_store (struct GNUNET_MESSENGER_MessageStore *store) | 75 | clear_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 | ||
75 | struct GNUNET_MESSENGER_MessageEntryStorage | 95 | struct 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 | ||
81 | void | 101 | static void |
82 | load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) | 102 | load_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 | |||
142 | struct GNUNET_MESSENGER_MessageLinkStorage | ||
143 | { | ||
144 | struct GNUNET_HashCode hash; | ||
145 | struct GNUNET_MESSENGER_MessageLink link; | ||
146 | }; | ||
147 | |||
148 | static void | ||
149 | load_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 | |||
187 | void | ||
188 | load_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 | ||
138 | free_filename: | ||
139 | GNUNET_free(filename); | 222 | GNUNET_free(filename); |
140 | } | 223 | } |
141 | 224 | ||
142 | struct GNUNET_MESSENGER_MessageSave | 225 | struct 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 | ||
149 | static int | 232 | static int |
233 | iterate_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 | |||
248 | static int | ||
150 | iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value) | 249 | iterate_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 | ||
279 | static int | ||
280 | iterate_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 | |||
180 | void | 295 | void |
181 | save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) | 296 | save_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 | |||
323 | close_links: | ||
324 | GNUNET_DISK_file_close (save.storage); | ||
325 | |||
326 | save_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 | ||
219 | close_entries: | 367 | close_entries: |
220 | GNUNET_DISK_file_close (save.storage_entries); | 368 | GNUNET_DISK_file_close (save.storage); |
221 | } | 369 | } |
222 | 370 | ||
223 | int | 371 | int |
224 | contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) | 372 | contains_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 | |||
232 | const struct GNUNET_MESSENGER_Message* | 382 | const struct GNUNET_MESSENGER_Message* |
233 | get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) | 383 | get_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 | |||
430 | free_message: destroy_message (message); | ||
431 | message = NULL; | ||
432 | |||
270 | free_buffer: | 433 | free_buffer: |
271 | GNUNET_free(buffer); | 434 | GNUNET_free(buffer); |
272 | 435 | ||
273 | return message; | 436 | return message; |
274 | } | 437 | } |
275 | 438 | ||
439 | const struct GNUNET_MESSENGER_MessageLink* | ||
440 | get_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 | |||
464 | get_link: | ||
465 | return GNUNET_CONTAINER_multihashmap_get (store->links, hash); | ||
466 | } | ||
467 | |||
276 | int | 468 | int |
277 | put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, | 469 | put_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 | |||
478 | static void | ||
479 | add_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 | |||
498 | int | ||
499 | delete_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 | |||
535 | clear_entry: | ||
536 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry)) | ||
537 | store->rewrite_entries = GNUNET_YES; | ||
538 | |||
539 | clear_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 | ||
39 | struct GNUNET_MESSENGER_Message; | ||
40 | |||
41 | struct GNUNET_MESSENGER_MessageLink | ||
42 | { | ||
43 | uint8_t multiple; | ||
44 | |||
45 | struct GNUNET_HashCode first; | ||
46 | struct GNUNET_HashCode second; | ||
47 | }; | ||
48 | |||
39 | struct GNUNET_MESSENGER_MessageStore | 49 | struct 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 | */ |
52 | void | 66 | void |
53 | init_message_store (struct GNUNET_MESSENGER_MessageStore *store); | 67 | init_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 | */ |
60 | void | 74 | void |
61 | clear_message_store (struct GNUNET_MESSENGER_MessageStore *store); | 75 | clear_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 | */ |
69 | void | 83 | void |
70 | load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); | 84 | load_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 | */ |
78 | void | 92 | void |
79 | save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); | 93 | save_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 | */ |
91 | int | 105 | int |
92 | contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); | 106 | contains_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 | */ |
105 | const struct GNUNET_MESSENGER_Message* | 119 | const struct GNUNET_MESSENGER_Message* |
106 | get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); | 120 | get_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 | */ | ||
135 | const struct GNUNET_MESSENGER_MessageLink* | ||
136 | get_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 | */ |
116 | int | 147 | int |
117 | put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, | 148 | put_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 | */ | ||
159 | int | ||
160 | delete_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 | |||
30 | struct GNUNET_MESSENGER_Operation* | ||
31 | create_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 | |||
46 | void | ||
47 | destroy_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 | |||
57 | static void | ||
58 | callback_operation (void *cls); | ||
59 | |||
60 | struct GNUNET_MESSENGER_Operation* | ||
61 | load_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 | |||
114 | destroy_config: | ||
115 | GNUNET_CONFIGURATION_destroy (cfg); | ||
116 | |||
117 | return op; | ||
118 | } | ||
119 | |||
120 | void | ||
121 | save_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 | |||
153 | extern void | ||
154 | callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store, | ||
155 | enum GNUNET_MESSENGER_OperationType type, | ||
156 | const struct GNUNET_HashCode *hash); | ||
157 | |||
158 | static void | ||
159 | callback_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 | |||
168 | int | ||
169 | start_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 | |||
198 | int | ||
199 | stop_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 | |||
36 | enum 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 | |||
45 | struct GNUNET_MESSENGER_OperationStore; | ||
46 | |||
47 | struct 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 | */ | ||
63 | struct GNUNET_MESSENGER_Operation* | ||
64 | create_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 | */ | ||
71 | void | ||
72 | destroy_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 | */ | ||
88 | struct GNUNET_MESSENGER_Operation* | ||
89 | load_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 | */ | ||
99 | void | ||
100 | save_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 | */ | ||
114 | int | ||
115 | start_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 | */ | ||
126 | int | ||
127 | stop_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 | |||
31 | void | ||
32 | init_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 | |||
40 | static int | ||
41 | iterate_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 | |||
50 | void | ||
51 | clear_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 | |||
59 | static int | ||
60 | callback_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 | |||
86 | void | ||
87 | load_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 | |||
96 | static int | ||
97 | iterate_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 | |||
114 | void | ||
115 | save_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 | |||
130 | enum GNUNET_MESSENGER_OperationType | ||
131 | get_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 | |||
144 | int | ||
145 | use_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 | |||
166 | use_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 | |||
174 | void | ||
175 | cancel_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 | |||
192 | extern void | ||
193 | callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash); | ||
194 | |||
195 | extern void | ||
196 | callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash); | ||
197 | |||
198 | void | ||
199 | callback_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 | |||
35 | struct GNUNET_MESSENGER_SrvRoom; | ||
36 | |||
37 | struct 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 | */ | ||
50 | void | ||
51 | init_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 | */ | ||
58 | void | ||
59 | clear_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 | */ | ||
67 | void | ||
68 | load_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 | */ | ||
77 | void | ||
78 | save_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 | */ | ||
90 | enum GNUNET_MESSENGER_OperationType | ||
91 | get_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 | */ | ||
111 | int | ||
112 | use_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 | */ | ||
127 | void | ||
128 | cancel_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 | ||
33 | static void | 42 | static void |
34 | idle_request_room_messages (void *cls); | 43 | idle_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 | ||
82 | static int | 88 | static void |
83 | iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value) | 89 | handle_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 | |||
100 | static int | ||
101 | iterate_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 | ||
111 | void | 91 | void |
112 | destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) | 92 | destroy_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 | ||
156 | struct GNUNET_MESSENGER_SrvContact* | 128 | struct GNUNET_MESSENGER_MemberStore* |
157 | get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) | 129 | get_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 | |||
164 | void | ||
165 | add_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 | ||
175 | struct GNUNET_MESSENGER_MemberInfo* | 136 | struct GNUNET_MESSENGER_MessageStore* |
176 | get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) | 137 | get_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 | ||
183 | struct GNUNET_ShortHashCode* | 144 | struct GNUNET_MESSENGER_OperationStore* |
184 | generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room) | 145 | get_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 | ||
199 | const struct GNUNET_ShortHashCode* | 152 | const 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 | ||
207 | void | 160 | void |
@@ -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 | ||
215 | static int | 168 | static int |
216 | send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 169 | send_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 | ||
255 | static void* | 178 | static 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 | ||
310 | static int | 215 | static int |
311 | join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 216 | join_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); | 239 | struct 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); | 246 | static int |
247 | iterate_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 | ||
352 | static int | 270 | static int |
353 | join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | 271 | join_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, ¬ify); | ||
361 | 297 | ||
362 | return GNUNET_YES; | 298 | return GNUNET_YES; |
363 | } | 299 | } |
364 | 300 | ||
365 | extern int | 301 | extern int |
366 | check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); | 302 | check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); |
303 | |||
367 | extern void | 304 | extern void |
368 | handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); | 305 | handle_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 | |||
373 | int | 310 | int |
374 | open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | 311 | open_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); | 355 | exit_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 | ||
416 | int | 359 | int |
417 | entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 360 | enter_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 | |||
458 | struct GNUNET_MESSENGER_SrvTunnelFinder | ||
459 | { | ||
460 | const struct GNUNET_ShortHashCode *needle; | ||
461 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
462 | }; | ||
463 | |||
464 | static int | ||
465 | iterate_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 | |||
479 | struct GNUNET_MESSENGER_SrvTunnel* | ||
480 | find_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 | ||
492 | struct GNUNET_MQ_Envelope* | 397 | struct GNUNET_MQ_Envelope* |
493 | pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 398 | pack_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 | ||
560 | void | 462 | int |
561 | callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, | 463 | update_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 | ||
564 | void | 466 | void |
467 | callback_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 | |||
470 | int | ||
565 | send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 471 | send_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 | ||
588 | void | 485 | struct GNUNET_HashCode hash; |
589 | send_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 | ||
613 | void | 524 | void |
614 | forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 525 | forward_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 | ||
632 | void | 548 | void |
633 | merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | 549 | check_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 | ||
660 | struct GNUNET_CADET_Handle* | 574 | if (tunnel) |
661 | get_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 | ||
666 | struct GNUNET_HashCode* | 577 | return; |
667 | get_room_key (struct GNUNET_MESSENGER_SrvRoom *room) | 578 | |
668 | { | 579 | resend_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 | ||
672 | const struct GNUNET_MESSENGER_SrvTunnel* | 584 | static void |
673 | get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer) | 585 | merge_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 | ||
678 | const struct GNUNET_MESSENGER_Message* | 593 | void |
679 | get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 594 | merge_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); | 608 | void |
697 | } | 609 | callback_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 | ||
705 | void | 623 | void |
706 | callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls) | 624 | callback_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 | ||
731 | int | 632 | int |
732 | callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, | 633 | delete_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 | ||
767 | static void | 670 | struct GNUNET_CADET_Handle* |
768 | search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) | 671 | get_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) | 678 | const struct GNUNET_HashCode* |
776 | search_room_for_message (room, &(message->body.merge.previous)); | 679 | get_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 | ||
781 | static void | 686 | const struct GNUNET_MESSENGER_SrvTunnel* |
782 | idle_request_room_messages (void *cls) | 687 | get_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; | 694 | const struct GNUNET_MESSENGER_Message* |
695 | get_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 | ||
804 | void | 713 | void |
805 | update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, | 714 | callback_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)) | 732 | int |
733 | callback_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 | ||
855 | void | 748 | static void |
856 | switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, | 749 | idle_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 | ||
876 | void | 774 | void |
877 | rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) | 775 | rebuild_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 | ||
921 | void | 821 | static void |
922 | handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) | 822 | handle_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 | |||
844 | finish_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" | 850 | static void |
851 | remove_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 | |||
861 | int | ||
862 | update_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 | |||
903 | struct 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 | |||
911 | struct 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 | |||
920 | static int | ||
921 | iterate_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 | ||
940 | void | 942 | void |
941 | callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, | 943 | callback_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" | 1022 | static void |
1023 | get_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 | ||
997 | void | 1030 | void |
998 | callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, | 1031 | load_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 | |||
1060 | void | ||
1061 | save_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 | ||
49 | enum 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 | ||
57 | struct 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; | 57 | struct GNUNET_MESSENGER_SrvTunnel; |
62 | }; | 58 | struct GNUNET_MESSENGER_MemberSession; |
63 | 59 | ||
64 | struct GNUNET_MESSENGER_SrvRoom | 60 | struct 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 | */ |
97 | struct GNUNET_MESSENGER_SrvRoom* | 90 | struct 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 | */ |
105 | void | 98 | void |
106 | destroy_room (struct GNUNET_MESSENGER_SrvRoom *room); | 99 | destroy_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 | */ | ||
116 | struct GNUNET_MESSENGER_SrvContact* | ||
117 | get_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 | */ |
126 | void | 107 | struct GNUNET_MESSENGER_MemberStore* |
127 | add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id, | 108 | get_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 | */ |
138 | struct GNUNET_MESSENGER_MemberInfo* | 116 | struct GNUNET_MESSENGER_MessageStore* |
139 | get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id); | 117 | get_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 | */ |
148 | struct GNUNET_ShortHashCode* | 125 | struct GNUNET_MESSENGER_OperationStore* |
149 | generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room); | 126 | get_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 | */ |
157 | const struct GNUNET_ShortHashCode* | 134 | const 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 | */ |
166 | void | 143 | void |
167 | change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id); | 144 | change_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 | */ |
181 | int | 158 | int |
182 | open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); | 159 | open_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 | */ |
194 | int | 171 | int |
195 | entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 172 | enter_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 | */ | ||
206 | struct GNUNET_MESSENGER_SrvTunnel* | ||
207 | find_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 | */ |
226 | struct GNUNET_MQ_Envelope* | 192 | struct GNUNET_MQ_Envelope* |
227 | pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 193 | pack_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 | */ |
242 | void | 211 | int |
243 | send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 212 | send_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 | */ |
259 | void | 223 | void |
260 | send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 224 | forward_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 | */ |
272 | void | 235 | void |
273 | forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 236 | check_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 | */ |
283 | void | 245 | void |
284 | merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); | 246 | merge_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 | */ | ||
258 | int | ||
259 | delete_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 | */ |
292 | struct GNUNET_CADET_Handle* | 268 | struct 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 | */ |
301 | struct GNUNET_HashCode* | 277 | const struct GNUNET_HashCode* |
302 | get_room_key (struct GNUNET_MESSENGER_SrvRoom *room); | 278 | get_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 | */ |
312 | const struct GNUNET_MESSENGER_SrvTunnel* | 288 | const struct GNUNET_MESSENGER_SrvTunnel* |
313 | get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); | 289 | get_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 | */ |
332 | const struct GNUNET_MESSENGER_Message* | 308 | const 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 | */ | ||
344 | void | ||
345 | update_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 | */ |
357 | void | 318 | void |
358 | switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, | 319 | rebuild_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 | */ |
367 | void | 327 | void |
368 | rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room); | 328 | load_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 | */ |
375 | void | 336 | void |
376 | handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room); | 337 | save_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 | ||
33 | static void | 30 | static void |
34 | callback_shutdown_service (void *cls) | 31 | callback_shutdown_service (void *cls) |
@@ -43,23 +40,11 @@ callback_shutdown_service (void *cls) | |||
43 | } | 40 | } |
44 | } | 41 | } |
45 | 42 | ||
46 | static void | ||
47 | callback_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 | |||
60 | struct GNUNET_MESSENGER_Service* | 43 | struct GNUNET_MESSENGER_Service* |
61 | create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle) | 44 | create_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 | ||
105 | static int | 87 | return service; |
106 | iterate_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 | ||
113 | static int | 90 | static 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 | ||
121 | static int | ||
122 | iterate_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 | |||
129 | void | 98 | void |
130 | destroy_service (struct GNUNET_MESSENGER_Service *service) | 99 | destroy_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 | ||
176 | struct GNUNET_MESSENGER_Ego* | 137 | struct GNUNET_MESSENGER_EgoStore* |
177 | lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier) | 138 | get_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 | ||
187 | void | 145 | struct GNUNET_MESSENGER_ContactStore* |
188 | update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, | 146 | get_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 | ||
211 | struct GNUNET_MESSENGER_SrvHandle* | 153 | struct GNUNET_MESSENGER_SrvHandle* |
212 | add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) | 154 | add_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 | |||
224 | void | 168 | void |
225 | remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle) | 169 | remove_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 | |||
234 | int | 180 | int |
235 | get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer) | 181 | get_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 | ||
240 | struct GNUNET_MESSENGER_SrvContact* | 185 | return GNUNET_CRYPTO_get_peer_identity (service->config, peer); |
241 | get_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 | |||
262 | void | ||
263 | swap_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 | |||
279 | struct GNUNET_ShortHashCode* | ||
280 | generate_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 | ||
296 | struct GNUNET_MESSENGER_SrvRoom* | 188 | struct GNUNET_MESSENGER_SrvRoom* |
297 | get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key) | 189 | get_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 | |||
303 | open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 197 | open_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 | |||
322 | entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 220 | entry_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 | |||
351 | close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 253 | close_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 | ||
396 | static void | ||
397 | get_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 | |||
402 | void | ||
403 | load_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 | |||
450 | void | ||
451 | save_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 | |||
486 | void | 292 | void |
487 | handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, | 293 | handle_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 | |||
43 | struct GNUNET_MESSENGER_Service | 44 | struct 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 | */ |
70 | struct GNUNET_MESSENGER_Service* | 70 | struct 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 | */ |
78 | void | 78 | void |
79 | destroy_service (struct GNUNET_MESSENGER_Service *service); | 79 | destroy_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 | */ |
89 | struct GNUNET_MESSENGER_Ego* | 87 | struct GNUNET_MESSENGER_EgoStore* |
90 | lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier); | 88 | get_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 | */ |
100 | void | 96 | struct GNUNET_MESSENGER_ContactStore* |
101 | update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, | 97 | get_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 | */ |
111 | struct GNUNET_MESSENGER_SrvHandle* | 106 | struct 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 | */ |
120 | void | 115 | void |
121 | remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle); | 116 | remove_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 | */ |
131 | int | 126 | int |
132 | get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer); | 127 | get_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 | */ | ||
143 | struct GNUNET_MESSENGER_SrvContact* | ||
144 | get_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 | */ | ||
154 | void | ||
155 | swap_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 | */ | ||
166 | struct GNUNET_ShortHashCode* | ||
167 | generate_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 | */ |
177 | struct GNUNET_MESSENGER_SrvRoom* | 137 | struct GNUNET_MESSENGER_SrvRoom* |
178 | get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key); | 138 | get_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 | */ |
189 | int | 149 | int |
190 | open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 150 | open_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 | */ |
206 | int | 166 | int |
207 | entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 167 | entry_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 | */ |
222 | int | 182 | int |
223 | close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | 183 | close_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 | */ | ||
233 | void | ||
234 | load_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 | */ | ||
243 | void | ||
244 | save_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 | */ |
255 | void | 196 | void |
256 | handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, | 197 | handle_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 | ||
31 | struct GNUNET_MESSENGER_SrvTunnel* | 32 | struct GNUNET_MESSENGER_SrvTunnel* |
32 | create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door) | 33 | create_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 | ||
72 | int | 71 | void |
73 | bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel) | 72 | bind_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 | ||
90 | extern void | 82 | extern 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 | ||
135 | extern int | ||
136 | update_room_message (struct GNUNET_MESSENGER_SrvRoom *room, | ||
137 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
138 | |||
159 | extern void | 139 | extern void |
160 | callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, | 140 | callback_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 | |||
143 | static void | ||
144 | update_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 | ||
163 | void | 152 | void |
164 | handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header) | 153 | handle_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 | ||
204 | receive_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) | |||
212 | void | 230 | void |
213 | disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) | 231 | disconnect_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) | |||
223 | int | 243 | int |
224 | is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) | 244 | is_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 | ||
235 | extern void | ||
236 | callback_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 | |||
239 | static void | 257 | static void |
240 | callback_tunnel_sent (void *cls) | 258 | callback_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 | ||
255 | void | 268 | void |
256 | send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, | 269 | send_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 | ||
273 | void | 286 | int |
274 | send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, | 287 | send_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 | ||
285 | void | 312 | void |
286 | forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, | 313 | forward_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 | ||
296 | const struct GNUNET_HashCode* | 335 | const struct GNUNET_HashCode* |
297 | get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) | 336 | get_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 | |||
343 | void | ||
344 | get_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 | |||
351 | uint32_t | ||
352 | get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) | ||
353 | { | ||
354 | GNUNET_assert(tunnel); | ||
355 | |||
356 | return tunnel->messenger_version; | ||
357 | } | ||
358 | |||
359 | int | ||
360 | update_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 | */ |
55 | struct GNUNET_MESSENGER_SrvTunnel* | 56 | struct 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 | */ |
63 | void | 64 | void |
64 | destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | 65 | destroy_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 | */ |
74 | int | 74 | void |
75 | bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel); | 75 | bind_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 | */ |
84 | int | 84 | int |
85 | connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | 85 | connect_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 | */ |
93 | void | 93 | void |
94 | disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | 94 | disconnect_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 | */ |
102 | int | 102 | int |
103 | is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); | 103 | is_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 | */ |
115 | void | 113 | void |
116 | send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, | 114 | send_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 | */ |
129 | void | 127 | int |
130 | send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, | 128 | send_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 | */ |
140 | void | 137 | void |
141 | forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, | 138 | forward_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 | */ |
152 | const struct GNUNET_HashCode* | 149 | const struct GNUNET_HashCode* |
153 | get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); | 150 | get_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 | */ | ||
159 | void | ||
160 | get_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 | */ | ||
171 | uint32_t | ||
172 | get_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 | */ | ||
182 | int | ||
183 | update_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 | ||
33 | const char* | 34 | const char* |
34 | GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind) | 35 | GNUNET_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 | |||
91 | static int | ||
92 | check_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 | ||
88 | static void | 109 | static 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) | |||
161 | static int | 189 | static int |
162 | check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) | 190 | check_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 | ||
213 | static void | 254 | static 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 | ||
227 | static void | 268 | static void |
228 | send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room, | 269 | send_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) | |||
319 | static void | 360 | static void |
320 | reconnect (struct GNUNET_MESSENGER_Handle *handle) | 361 | reconnect (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 | ||
354 | struct GNUNET_MESSENGER_Handle* | 404 | struct GNUNET_MESSENGER_Handle* |
@@ -389,7 +439,7 @@ GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const c | |||
389 | int | 439 | int |
390 | GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle) | 440 | GNUNET_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 | ||
501 | static const struct GNUNET_IDENTITY_PublicKey* | ||
502 | get_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 | |||
451 | const struct GNUNET_IDENTITY_PublicKey* | 510 | const struct GNUNET_IDENTITY_PublicKey* |
452 | GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle) | 511 | GNUNET_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 | ||
460 | struct GNUNET_MESSENGER_Room* | 519 | struct GNUNET_MESSENGER_Room* |
461 | GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | 520 | GNUNET_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 | ||
481 | struct GNUNET_MESSENGER_Room* | 543 | struct GNUNET_MESSENGER_Room* |
482 | GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | 544 | GNUNET_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 | ||
503 | void | 568 | void |
504 | GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room) | 569 | GNUNET_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 | ||
509 | struct GNUNET_MESSENGER_Contact* | 577 | struct GNUNET_MESSENGER_Contact* |
510 | GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id) | 578 | GNUNET_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 | ||
515 | const char* | 586 | const 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 | ||
533 | void | 604 | void |
534 | GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message) | 605 | GNUNET_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 | |||
551 | const struct GNUNET_MESSENGER_Message* | 672 | const struct GNUNET_MESSENGER_Message* |
552 | GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | 673 | GNUNET_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 | |||
694 | int | ||
695 | GNUNET_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 @@ | |||
28 | struct GNUNET_MESSENGER_Contact* | 28 | struct GNUNET_MESSENGER_Contact* |
29 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key) | 29 | create_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) | |||
40 | void | 43 | void |
41 | destroy_contact (struct GNUNET_MESSENGER_Contact *contact) | 44 | destroy_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) | |||
49 | const char* | 54 | const char* |
50 | get_contact_name (const struct GNUNET_MESSENGER_Contact *contact) | 55 | get_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 | ||
55 | void | 62 | void |
56 | set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name) | 63 | set_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 | ||
64 | const struct GNUNET_IDENTITY_PublicKey* | 73 | const struct GNUNET_IDENTITY_PublicKey* |
65 | get_contact_key (const struct GNUNET_MESSENGER_Contact *contact) | 74 | get_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 | ||
70 | const struct GNUNET_HashCode* | 81 | void |
71 | get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact) | 82 | increase_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); | 89 | int |
90 | decrease_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 | |||
100 | void | ||
101 | get_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 @@ | |||
33 | struct GNUNET_MESSENGER_Contact | 33 | struct 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 | */ |
46 | struct GNUNET_MESSENGER_Contact* | 47 | struct 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 | */ |
54 | void | 55 | void |
55 | destroy_contact (struct GNUNET_MESSENGER_Contact *contact); | 56 | destroy_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 | */ |
63 | const char* | 64 | const 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 | */ |
72 | void | 73 | void |
73 | set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name); | 74 | set_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 | */ |
81 | const struct GNUNET_IDENTITY_PublicKey* | 82 | const struct GNUNET_IDENTITY_PublicKey* |
82 | get_contact_key (const struct GNUNET_MESSENGER_Contact *contact); | 83 | get_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 | */ |
90 | const struct GNUNET_HashCode* | 90 | void |
91 | get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact); | 91 | increase_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 | */ | ||
100 | int | ||
101 | decrease_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 | */ | ||
110 | void | ||
111 | get_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 | |||
31 | void | ||
32 | init_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 | |||
40 | static int | ||
41 | iterate_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 | |||
48 | void | ||
49 | clear_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 | |||
60 | static struct GNUNET_CONTAINER_MultiHashMap* | ||
61 | select_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 | |||
78 | struct GNUNET_MESSENGER_Contact* | ||
79 | get_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 | |||
94 | struct GNUNET_MESSENGER_Contact* | ||
95 | get_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 | |||
132 | void | ||
133 | update_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 | |||
163 | void | ||
164 | remove_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 | |||
34 | struct GNUNET_MESSENGER_Contact; | ||
35 | |||
36 | struct 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 | */ | ||
47 | void | ||
48 | init_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 | */ | ||
55 | void | ||
56 | clear_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 | */ | ||
70 | struct GNUNET_MESSENGER_Contact* | ||
71 | get_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 | */ | ||
89 | struct GNUNET_MESSENGER_Contact* | ||
90 | get_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 | */ | ||
105 | void | ||
106 | update_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 | */ | ||
118 | void | ||
119 | remove_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 | |||
28 | struct GNUNET_MESSENGER_Handle* | 30 | struct GNUNET_MESSENGER_Handle* |
29 | create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback, | 31 | create_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 | ||
65 | static int | ||
66 | iterate_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 | |||
75 | void | 70 | void |
76 | destroy_handle (struct GNUNET_MESSENGER_Handle *handle) | 71 | destroy_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) | |||
107 | void | 99 | void |
108 | set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name) | 100 | set_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 | ||
116 | const char* | 110 | const char* |
117 | get_handle_name (const struct GNUNET_MESSENGER_Handle *handle) | 111 | get_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 | ||
122 | void | 118 | void |
123 | set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey) | 119 | set_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 | |||
131 | const struct GNUNET_IDENTITY_PublicKey* | 129 | const struct GNUNET_IDENTITY_PublicKey* |
132 | get_handle_key (const struct GNUNET_MESSENGER_Handle *handle) | 130 | get_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 | ||
147 | struct GNUNET_MESSENGER_Contact* | 140 | struct GNUNET_MESSENGER_ContactStore* |
148 | get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, | 141 | get_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 | ||
170 | void | 148 | struct GNUNET_MESSENGER_Contact* |
171 | swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, | 149 | get_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 | ||
187 | void | 164 | void |
188 | open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | 165 | open_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 | |||
197 | entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | 176 | entry_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 | |||
206 | void | 187 | void |
207 | close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | 188 | close_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 | ||
41 | struct GNUNET_MESSENGER_Handle | 41 | struct 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 | */ |
72 | struct GNUNET_MESSENGER_Handle* | 73 | struct 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 | */ |
81 | void | 82 | void |
82 | destroy_handle (struct GNUNET_MESSENGER_Handle *handle); | 83 | destroy_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 | */ |
90 | void | 91 | void |
91 | set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); | 92 | set_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 | */ |
99 | const char* | 100 | const 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 | */ |
108 | void | 109 | void |
109 | set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey); | 110 | set_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 | */ |
117 | const struct GNUNET_IDENTITY_PublicKey* | 118 | const struct GNUNET_IDENTITY_PublicKey* |
118 | get_handle_key (const struct GNUNET_MESSENGER_Handle *handle); | 119 | get_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 | */ |
128 | struct GNUNET_MESSENGER_Contact* | 127 | struct GNUNET_MESSENGER_ContactStore* |
129 | get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, | 128 | get_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 | */ |
140 | void | 138 | struct GNUNET_MESSENGER_Contact* |
141 | swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, | 139 | get_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 | */ |
150 | void | 147 | void |
151 | open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | 148 | open_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 | */ |
161 | void | 158 | void |
162 | entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | 159 | entry_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 | */ |
171 | void | 168 | void |
172 | close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | 169 | close_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, | |||
62 | void | 62 | void |
63 | add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) | 63 | add_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 | |||
73 | struct GNUNET_MESSENGER_ListTunnel* | 75 | struct GNUNET_MESSENGER_ListTunnel* |
74 | find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index) | 76 | find_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 | |||
96 | int | 100 | int |
97 | contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) | 101 | contains_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 | ||
102 | struct GNUNET_MESSENGER_ListTunnel* | 108 | struct GNUNET_MESSENGER_ListTunnel* |
103 | remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element) | 109 | remove_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 | |||
122 | void | ||
123 | load_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 | |||
156 | void | ||
157 | save_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 | */ |
52 | void | 52 | void |
53 | init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); | 53 | init_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 | */ |
60 | void | 60 | void |
61 | clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); | 61 | clear_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 | */ |
69 | void | 69 | void |
70 | add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); | 70 | add_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 | */ |
98 | int | 98 | int |
99 | contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); | 99 | contains_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 | */ |
109 | struct GNUNET_MESSENGER_ListTunnel* | 109 | struct GNUNET_MESSENGER_ListTunnel* |
110 | remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element); | 110 | remove_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 | */ | ||
118 | void | ||
119 | load_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 | */ | ||
127 | void | ||
128 | save_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) | |||
69 | struct GNUNET_MESSENGER_Message* | 69 | struct GNUNET_MESSENGER_Message* |
70 | copy_message (const struct GNUNET_MESSENGER_Message *message) | 70 | copy_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 | |||
125 | void | 127 | void |
126 | destroy_message (struct GNUNET_MESSENGER_Message *message) | 128 | destroy_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 | ||
137 | int | ||
138 | is_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 | |||
133 | static void | 152 | static void |
134 | fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) | 153 | fold_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 | ||
218 | typedef uint32_t kind_t; | ||
219 | |||
210 | uint16_t | 220 | uint16_t |
211 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | 221 | get_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 | ||
250 | uint16_t | 268 | uint16_t |
251 | get_message_size (const struct GNUNET_MESSENGER_Message *message) | 269 | get_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 | ||
256 | static uint16_t | 285 | static uint16_t |
257 | get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) | 286 | get_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 | |||
297 | static uint16_t | ||
298 | calc_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 | |||
315 | static uint16_t | ||
316 | calc_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 | ||
277 | static void | 372 | static void |
278 | encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, | 373 | encode_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 | ||
336 | void | 444 | void |
337 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer) | 445 | encode_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, | |||
350 | static void | 465 | static void |
351 | encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) | 466 | encode_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 | ||
375 | static 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 | |||
511 | static uint16_t | ||
376 | decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, | 512 | decode_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 | ||
439 | int | 589 | int |
440 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer) | 590 | decode_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 | |||
461 | static int | 634 | static int |
462 | decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) | 635 | decode_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 | ||
479 | void | 671 | void |
480 | hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash) | 672 | hash_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 | ||
486 | void | 684 | void |
487 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, | 685 | sign_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 | ||
501 | int | 702 | int |
502 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, | 703 | verify_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 | |||
516 | int | 722 | int |
517 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) | 723 | encrypt_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 | |||
544 | int | 756 | int |
545 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) | 757 | decrypt_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* | |||
563 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | 785 | pack_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 | |||
833 | int | ||
834 | filter_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 | */ |
45 | struct GNUNET_MESSENGER_Message* | 52 | struct 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 | */ |
54 | struct GNUNET_MESSENGER_Message* | 61 | struct 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 | */ |
62 | void | 69 | void |
63 | destroy_message (struct GNUNET_MESSENGER_Message *message); | 70 | destroy_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 | */ | ||
78 | int | ||
79 | is_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 | */ |
71 | uint16_t | 87 | uint16_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 | */ |
80 | uint16_t | 97 | uint16_t |
81 | get_message_size (const struct GNUNET_MESSENGER_Message *message); | 98 | get_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 | */ |
90 | void | 109 | void |
91 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer); | 110 | encode_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 | */ |
106 | int | 127 | int |
107 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer); | 128 | decode_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 | */ |
116 | void | 140 | void |
117 | hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash); | 141 | hash_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 | */ |
129 | void | 154 | void |
130 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, | 155 | sign_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 | */ |
143 | int | 168 | int |
144 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, | 169 | verify_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 | */ |
156 | int | 181 | int |
157 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key); | 182 | encrypt_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 | */ |
168 | int | 193 | int |
169 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key); | 194 | decrypt_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 | */ |
186 | struct GNUNET_MQ_Envelope* | 211 | struct GNUNET_MQ_Envelope* |
187 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | 212 | pack_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 | */ | ||
222 | int | ||
223 | filter_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 @@ | |||
30 | struct GNUNET_MESSENGER_Room* | 30 | struct GNUNET_MESSENGER_Room* |
31 | create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | 31 | create_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 | |||
50 | static int | 51 | static int |
51 | iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) | 52 | iterate_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 | |||
60 | void | 62 | void |
61 | destroy_room (struct GNUNET_MESSENGER_Room *room) | 63 | destroy_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) | |||
81 | const struct GNUNET_MESSENGER_Message* | 85 | const struct GNUNET_MESSENGER_Message* |
82 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | 86 | get_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 | |||
97 | struct GNUNET_MESSENGER_Contact* | ||
98 | get_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 | ||
87 | static void | 109 | static void |
88 | handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 110 | handle_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 | ||
98 | static void | 129 | static void |
99 | handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 130 | handle_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 | ||
105 | static void | 146 | static void |
106 | handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 147 | handle_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 | ||
116 | static void | 156 | static void |
117 | handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 157 | handle_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 | ||
127 | static void | 171 | static void |
128 | handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 172 | handle_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 | ||
140 | static void | 190 | static void |
141 | handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 191 | handle_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 | ||
203 | static void | ||
204 | handle_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 | |||
153 | void | 219 | void |
154 | handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 220 | handle_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 | |||
269 | struct GNUNET_MESSENGER_MemberCall | ||
270 | { | ||
271 | struct GNUNET_MESSENGER_Room *room; | ||
272 | GNUNET_MESSENGER_MemberCallback callback; | ||
273 | void *cls; | ||
274 | }; | ||
275 | |||
276 | static int | ||
277 | iterate_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 | |||
285 | int | ||
286 | iterate_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 | ||
39 | struct GNUNET_MESSENGER_RoomMessageEntry { | ||
40 | struct GNUNET_MESSENGER_Contact* sender; | ||
41 | struct GNUNET_MESSENGER_Message* message; | ||
42 | }; | ||
43 | |||
39 | struct GNUNET_MESSENGER_Room | 44 | struct 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 | */ |
61 | struct GNUNET_MESSENGER_Room* | 66 | struct 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 | */ |
69 | void | 74 | void |
70 | destroy_room (struct GNUNET_MESSENGER_Room *room); | 75 | destroy_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 | */ |
80 | const struct GNUNET_MESSENGER_Message* | 85 | const struct GNUNET_MESSENGER_Message* |
81 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); | 86 | get_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 | */ | ||
96 | struct GNUNET_MESSENGER_Contact* | ||
97 | get_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 | */ |
91 | void | 108 | void |
92 | handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | 109 | handle_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 | */ | ||
121 | int | ||
122 | iterate_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 | ||
28 | static void | 28 | static void |
29 | callback_close_channel (void *cls) | 29 | callback_close_channel (void *cls) |
@@ -37,13 +37,18 @@ callback_close_channel (void *cls) | |||
37 | void | 37 | void |
38 | delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel) | 38 | delayed_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 | ||
44 | int | 47 | int |
45 | generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members) | 48 | generate_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 | |||
71 | const struct GNUNET_IDENTITY_PublicKey* | ||
72 | get_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 | */ |
39 | void | 41 | void |
40 | delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel); | 42 | delayed_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 | */ |
50 | int | 52 | int |
51 | generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members); | 53 | generate_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 | */ | ||
61 | const struct GNUNET_IDENTITY_PublicKey* | ||
62 | get_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 | |||
72 | static void | 71 | static void |
73 | end_badly (void *cls) | 72 | end_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 | */ |
158 | static void | 152 | static void |
159 | run (void *cls, | 153 | run (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 | */ |
178 | int | 170 | int |
179 | main(int argc, char **argv) | 171 | main (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 | */ | ||
35 | int | ||
36 | main (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 | |||
70 | static void | 69 | static void |
71 | end_badly (void *cls) | 70 | end_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 | */ |
152 | static void | 146 | static void |
153 | run (void *cls, | 147 | run (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 | */ |
170 | int | 162 | int |
171 | main(int argc, char **argv) | 163 | main (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] | ||
5 | HOSTNAME = localhost | ||
6 | OVERLAY_TOPOLOGY = CLIQUE | ||
7 | |||
8 | [arm] | ||
9 | GLOBAL_POSTFIX = -l $GNUNET_CACHE_HOME/{}-logs -L verbose | ||
10 | |||
11 | [transport] | ||
12 | IMMEDIATE_START = YES | ||
13 | |||
14 | [core] | ||
15 | START_ON_DEMAND = YES | ||
16 | IMMEDIATE_START = YES | ||
17 | USE_EPHEMERAL_KEYS = NO | ||
18 | |||
4 | [PATHS] | 19 | [PATHS] |
5 | GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/ | 20 | GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/ |
6 | 21 | ||
22 | [peerinfo] | ||
23 | NO_IO = YES | ||
24 | |||
7 | [cadet] | 25 | [cadet] |
8 | START_ON_DEMAND = YES | 26 | START_ON_DEMAND = YES |
27 | REFRESH_CONNECTION_TIME = 1 s | ||
28 | ID_ANNOUNCE_TIME = 5 s | ||
29 | CONNECT_TIMEOUT = 30 s | ||
30 | DEFAULT_TTL = 16 | ||
31 | DHT_REPLICATION_LEVEL = 10 | ||
32 | MAX_TUNNELS = 10 | ||
33 | MAX_CONNECTIONS = 10 | ||
34 | MAX_MSGS_QUEUE = 20 | ||
35 | DISABLE_TRY_CONNECT = YES | ||
36 | REKEY_PERIOD = 2 s | ||
9 | 37 | ||
10 | [identity] | 38 | [identity] |
11 | START_ON_DEMAND = YES | 39 | START_ON_DEMAND = YES |
@@ -14,4 +42,6 @@ START_ON_DEMAND = YES | |||
14 | START_ON_DEMAND = YES | 42 | START_ON_DEMAND = YES |
15 | 43 | ||
16 | [nat] | 44 | [nat] |
17 | ENABLE_UPNP = NO \ No newline at end of file | 45 | ENABLE_UPNP = NO |
46 | RETURN_LOCAL_ADDRESSES = YES | ||
47 | IMMEDIATE_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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | |||
44 | static int status = 1; | ||
45 | |||
46 | static struct GNUNET_SCHEDULER_Task *die_task = NULL; | ||
47 | static struct GNUNET_SCHEDULER_Task *op_task = NULL; | ||
48 | |||
49 | static void | ||
50 | end (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 | |||
65 | static void | ||
66 | end_badly (void *cls) | ||
67 | { | ||
68 | fprintf (stderr, "Testcase failed (timeout).\n"); | ||
69 | |||
70 | end (NULL); | ||
71 | status = 1; | ||
72 | } | ||
73 | |||
74 | static void | ||
75 | end_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 | |||
88 | static void | ||
89 | end_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 | */ | ||
111 | static void | ||
112 | on_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 | */ | ||
124 | static void | ||
125 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | ||
126 | { | ||
127 | // TODO | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | on_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 | */ | ||
179 | static void | ||
180 | run (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 | |||
199 | static void | ||
200 | exit_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 | |||
220 | static void | ||
221 | init (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 | */ | ||
241 | int | ||
242 | main(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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | */ | ||
35 | int | ||
36 | main (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 | |||
28 | struct 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 | |||
40 | struct GNUNET_BarrierHandle* | ||
41 | GNUNET_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 | |||
63 | static void | ||
64 | exit_status (struct GNUNET_BarrierHandle *barrier, int status); | ||
65 | |||
66 | static void | ||
67 | cancel_barrier (void *cls) | ||
68 | { | ||
69 | exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR); | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | complete_barrier (void *cls) | ||
74 | { | ||
75 | exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK); | ||
76 | } | ||
77 | |||
78 | void | ||
79 | GNUNET_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 | |||
87 | struct 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 | |||
98 | static void | ||
99 | exit_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 | |||
121 | struct GNUNET_BarrierWaitHandle* | ||
122 | GNUNET_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 | |||
149 | void | ||
150 | GNUNET_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 | */ | ||
35 | struct 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 | */ | ||
50 | typedef 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 | */ | ||
68 | struct GNUNET_BarrierHandle* | ||
69 | GNUNET_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 | */ | ||
79 | void | ||
80 | GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier); | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Handle for pseudo-barrier wait | ||
85 | */ | ||
86 | struct 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 | */ | ||
99 | typedef 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 | */ | ||
115 | struct GNUNET_BarrierWaitHandle* | ||
116 | GNUNET_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 | */ | ||
127 | void | ||
128 | GNUNET_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 | |||
40 | struct test_properties; | ||
41 | |||
42 | struct 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 | |||
61 | struct 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 | |||
77 | static void | ||
78 | shutdown_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 | |||
129 | static void | ||
130 | end_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 | |||
163 | static void | ||
164 | end_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 | |||
177 | static void | ||
178 | end_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 | |||
191 | static void | ||
192 | end_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 | |||
206 | static void | ||
207 | barrier2_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 | |||
217 | static void | ||
218 | barrier_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 | */ | ||
261 | static void | ||
262 | on_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 | |||
296 | static void | ||
297 | second_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 | |||
342 | static void | ||
343 | on_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 | */ | ||
398 | static void | ||
399 | run (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 | |||
422 | static void | ||
423 | barrier2_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 | |||
451 | static void | ||
452 | barrier_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 | |||
487 | static void | ||
488 | init (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 | |||
502 | int | ||
503 | GNUNET_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 | |||
29 | struct test_configuration | ||
30 | { | ||
31 | unsigned int count; | ||
32 | unsigned int *doors; | ||
33 | unsigned int *stages; | ||
34 | }; | ||
35 | |||
36 | int | ||
37 | GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg); | ||
38 | |||
39 | #endif /* GNUNET_TESTING_MESSENGER_SETUP_H_ */ | ||