diff options
author | Gabor X Toth <*@tg-x.net> | 2015-09-26 17:09:57 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2015-09-26 17:09:57 +0000 |
commit | 5a042e00e06de726a21d9db05ddeb2ac16ca7c0c (patch) | |
tree | 9b2f504796b72a50d061eb812be4aa87efbf6584 /src/multicast | |
parent | 0c5cea1c26efb8b53f643a6ce6b162d9c9fe2b8f (diff) | |
download | gnunet-5a042e00e06de726a21d9db05ddeb2ac16ca7c0c.tar.gz gnunet-5a042e00e06de726a21d9db05ddeb2ac16ca7c0c.zip |
multicast: replay
Diffstat (limited to 'src/multicast')
-rw-r--r-- | src/multicast/gnunet-service-multicast.c | 562 | ||||
-rw-r--r-- | src/multicast/multicast.h | 114 | ||||
-rw-r--r-- | src/multicast/multicast_api.c | 236 | ||||
-rw-r--r-- | src/multicast/test_multicast.c | 211 |
4 files changed, 925 insertions, 198 deletions
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c index dee573848..e7ee92cdf 100644 --- a/src/multicast/gnunet-service-multicast.c +++ b/src/multicast/gnunet-service-multicast.c | |||
@@ -88,18 +88,33 @@ static struct GNUNET_CONTAINER_MultiHashMap *members; | |||
88 | static struct GNUNET_CONTAINER_MultiHashMap *group_members; | 88 | static struct GNUNET_CONTAINER_MultiHashMap *group_members; |
89 | 89 | ||
90 | /** | 90 | /** |
91 | * Incoming CADET channels. | 91 | * Incoming CADET channels with connected children in the tree. |
92 | * Group's pub_key_hash -> struct Channel * (multi) | 92 | * Group's pub_key_hash -> struct Channel * (multi) |
93 | */ | 93 | */ |
94 | static struct GNUNET_CONTAINER_MultiHashMap *channels_in; | 94 | static struct GNUNET_CONTAINER_MultiHashMap *channels_in; |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * Outgoing CADET channels. | 97 | * Outgoing CADET channels connecting to parents in the tree. |
98 | * Group's pub_key_hash -> struct Channel * (multi) | 98 | * Group's pub_key_hash -> struct Channel * (multi) |
99 | */ | 99 | */ |
100 | static struct GNUNET_CONTAINER_MultiHashMap *channels_out; | 100 | static struct GNUNET_CONTAINER_MultiHashMap *channels_out; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Incoming replay requests from CADET. | ||
104 | * Group's pub_key_hash -> | ||
105 | * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel * | ||
106 | */ | ||
107 | static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet; | ||
108 | |||
109 | /** | ||
110 | * Incoming replay requests from clients. | ||
111 | * Group's pub_key_hash -> | ||
112 | * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVER_Client * | ||
113 | */ | ||
114 | static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client; | ||
115 | |||
116 | |||
117 | /** | ||
103 | * Join status of a remote peer. | 118 | * Join status of a remote peer. |
104 | */ | 119 | */ |
105 | enum JoinStatus | 120 | enum JoinStatus |
@@ -294,6 +309,15 @@ struct Member | |||
294 | }; | 309 | }; |
295 | 310 | ||
296 | 311 | ||
312 | struct ReplayRequestKey | ||
313 | { | ||
314 | uint64_t fragment_id; | ||
315 | uint64_t message_id; | ||
316 | uint64_t fragment_offset; | ||
317 | uint64_t flags; | ||
318 | }; | ||
319 | |||
320 | |||
297 | /** | 321 | /** |
298 | * Task run during shutdown. | 322 | * Task run during shutdown. |
299 | * | 323 | * |
@@ -375,6 +399,95 @@ cleanup_group (struct Group *grp) | |||
375 | } | 399 | } |
376 | 400 | ||
377 | 401 | ||
402 | void | ||
403 | replay_key_hash (uint64_t fragment_id, uint64_t message_id, | ||
404 | uint64_t fragment_offset, uint64_t flags, | ||
405 | struct GNUNET_HashCode *key_hash) | ||
406 | { | ||
407 | struct ReplayRequestKey key = { | ||
408 | .fragment_id = fragment_id, | ||
409 | .message_id = message_id, | ||
410 | .fragment_offset = fragment_offset, | ||
411 | .flags = flags, | ||
412 | }; | ||
413 | GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash); | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Remove channel from replay request hashmap. | ||
419 | * | ||
420 | * @param chn | ||
421 | * Channel to remove. | ||
422 | * | ||
423 | * @return #GNUNET_YES if there are more entries to process, | ||
424 | * #GNUNET_NO when reached end of hashmap. | ||
425 | */ | ||
426 | static int | ||
427 | replay_req_remove_cadet (struct Channel *chn) | ||
428 | { | ||
429 | struct GNUNET_CONTAINER_MultiHashMap * | ||
430 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
431 | &chn->grp->pub_key_hash); | ||
432 | if (NULL == grp_replay_req) | ||
433 | return GNUNET_NO; | ||
434 | |||
435 | struct GNUNET_CONTAINER_MultiHashMapIterator * | ||
436 | it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req); | ||
437 | struct GNUNET_HashCode key; | ||
438 | const struct Channel *c; | ||
439 | while (GNUNET_YES | ||
440 | == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key, | ||
441 | (const void **) &c)) | ||
442 | { | ||
443 | if (c == chn) | ||
444 | { | ||
445 | GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn); | ||
446 | return GNUNET_YES; | ||
447 | } | ||
448 | } | ||
449 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
450 | return GNUNET_NO; | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
455 | * Remove client from replay request hashmap. | ||
456 | * | ||
457 | * @param client | ||
458 | * Client to remove. | ||
459 | * | ||
460 | * @return #GNUNET_YES if there are more entries to process, | ||
461 | * #GNUNET_NO when reached end of hashmap. | ||
462 | */ | ||
463 | static int | ||
464 | replay_req_remove_client (struct Group *grp, struct GNUNET_SERVER_Client *client) | ||
465 | { | ||
466 | struct GNUNET_CONTAINER_MultiHashMap * | ||
467 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
468 | &grp->pub_key_hash); | ||
469 | if (NULL == grp_replay_req) | ||
470 | return GNUNET_NO; | ||
471 | |||
472 | struct GNUNET_CONTAINER_MultiHashMapIterator * | ||
473 | it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req); | ||
474 | struct GNUNET_HashCode key; | ||
475 | const struct GNUNET_SERVER_Client *c; | ||
476 | while (GNUNET_YES | ||
477 | == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key, | ||
478 | (const void **) &c)) | ||
479 | { | ||
480 | if (c == client) | ||
481 | { | ||
482 | GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client); | ||
483 | return GNUNET_YES; | ||
484 | } | ||
485 | } | ||
486 | GNUNET_CONTAINER_multihashmap_iterator_destroy (it); | ||
487 | return GNUNET_NO; | ||
488 | } | ||
489 | |||
490 | |||
378 | /** | 491 | /** |
379 | * Called whenever a client is disconnected. | 492 | * Called whenever a client is disconnected. |
380 | * | 493 | * |
@@ -417,6 +530,8 @@ client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
417 | cl = cl->next; | 530 | cl = cl->next; |
418 | } | 531 | } |
419 | 532 | ||
533 | while (GNUNET_YES == replay_req_remove_client (grp, client)); | ||
534 | |||
420 | if (NULL == grp->clients_head) | 535 | if (NULL == grp->clients_head) |
421 | { /* Last client disconnected. */ | 536 | { /* Last client disconnected. */ |
422 | #if FIXME | 537 | #if FIXME |
@@ -434,14 +549,29 @@ client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
434 | 549 | ||
435 | 550 | ||
436 | /** | 551 | /** |
552 | * Send message to a client. | ||
553 | */ | ||
554 | static void | ||
555 | client_send (struct GNUNET_SERVER_Client *client, | ||
556 | const struct GNUNET_MessageHeader *msg) | ||
557 | { | ||
558 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
559 | "%p Sending message to client.\n", client); | ||
560 | |||
561 | GNUNET_SERVER_notification_context_add (nc, client); | ||
562 | GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO); | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
437 | * Send message to all clients connected to the group. | 567 | * Send message to all clients connected to the group. |
438 | */ | 568 | */ |
439 | static void | 569 | static void |
440 | client_send_msg (const struct Group *grp, | 570 | client_send_group (const struct Group *grp, |
441 | const struct GNUNET_MessageHeader *msg) | 571 | const struct GNUNET_MessageHeader *msg) |
442 | { | 572 | { |
443 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 573 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
444 | "%p Sending message to clients.\n", grp); | 574 | "%p Sending message to all clients of the group.\n", grp); |
445 | 575 | ||
446 | struct ClientList *cl = grp->clients_head; | 576 | struct ClientList *cl = grp->clients_head; |
447 | while (NULL != cl) | 577 | while (NULL != cl) |
@@ -463,7 +593,7 @@ client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | |||
463 | const struct GNUNET_MessageHeader *msg = cls; | 593 | const struct GNUNET_MessageHeader *msg = cls; |
464 | struct Member *orig = origin; | 594 | struct Member *orig = origin; |
465 | 595 | ||
466 | client_send_msg (&orig->grp, msg); | 596 | client_send_group (&orig->grp, msg); |
467 | return GNUNET_YES; | 597 | return GNUNET_YES; |
468 | } | 598 | } |
469 | 599 | ||
@@ -480,7 +610,7 @@ client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | |||
480 | 610 | ||
481 | if (NULL != mem->join_dcsn) | 611 | if (NULL != mem->join_dcsn) |
482 | { /* Only send message to admitted members */ | 612 | { /* Only send message to admitted members */ |
483 | client_send_msg (&mem->grp, msg); | 613 | client_send_group (&mem->grp, msg); |
484 | } | 614 | } |
485 | return GNUNET_YES; | 615 | return GNUNET_YES; |
486 | } | 616 | } |
@@ -497,14 +627,32 @@ client_send_all (struct GNUNET_HashCode *pub_key_hash, | |||
497 | const struct GNUNET_MessageHeader *msg) | 627 | const struct GNUNET_MessageHeader *msg) |
498 | { | 628 | { |
499 | int n = 0; | 629 | int n = 0; |
500 | if (origins != NULL) | 630 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, |
501 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, | 631 | client_send_origin_cb, |
502 | client_send_origin_cb, | 632 | (void *) msg); |
503 | (void *) msg); | 633 | n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash, |
504 | if (members != NULL) | 634 | client_send_member_cb, |
505 | n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash, | 635 | (void *) msg); |
506 | client_send_member_cb, | 636 | return n; |
507 | (void *) msg); | 637 | } |
638 | |||
639 | |||
640 | /** | ||
641 | * Send message to a random origin client or a random member client. | ||
642 | * | ||
643 | * @param grp The group to send @a msg to. | ||
644 | * @param msg Message to send. | ||
645 | */ | ||
646 | static int | ||
647 | client_send_random (struct GNUNET_HashCode *pub_key_hash, | ||
648 | const struct GNUNET_MessageHeader *msg) | ||
649 | { | ||
650 | int n = 0; | ||
651 | n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb, | ||
652 | (void *) msg); | ||
653 | if (n <= 0) | ||
654 | n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb, | ||
655 | (void *) msg); | ||
508 | return n; | 656 | return n; |
509 | } | 657 | } |
510 | 658 | ||
@@ -520,10 +668,9 @@ client_send_origin (struct GNUNET_HashCode *pub_key_hash, | |||
520 | const struct GNUNET_MessageHeader *msg) | 668 | const struct GNUNET_MessageHeader *msg) |
521 | { | 669 | { |
522 | int n = 0; | 670 | int n = 0; |
523 | if (origins != NULL) | 671 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, |
524 | n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, | 672 | client_send_origin_cb, |
525 | client_send_origin_cb, | 673 | (void *) msg); |
526 | (void *) msg); | ||
527 | return n; | 674 | return n; |
528 | } | 675 | } |
529 | 676 | ||
@@ -554,7 +701,7 @@ cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf) | |||
554 | * @param msg Message. | 701 | * @param msg Message. |
555 | */ | 702 | */ |
556 | static void | 703 | static void |
557 | cadet_send_msg (struct Channel *chn, const struct GNUNET_MessageHeader *msg) | 704 | cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg) |
558 | { | 705 | { |
559 | chn->tmit_handle | 706 | chn->tmit_handle |
560 | = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO, | 707 | = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO, |
@@ -604,14 +751,14 @@ static void | |||
604 | cadet_send_join_request (struct Member *mem) | 751 | cadet_send_join_request (struct Member *mem) |
605 | { | 752 | { |
606 | mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin); | 753 | mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin); |
607 | cadet_send_msg (mem->origin_channel, &mem->join_req->header); | 754 | cadet_send_channel (mem->origin_channel, &mem->join_req->header); |
608 | 755 | ||
609 | uint32_t i; | 756 | uint32_t i; |
610 | for (i = 0; i < mem->relay_count; i++) | 757 | for (i = 0; i < mem->relay_count; i++) |
611 | { | 758 | { |
612 | struct Channel * | 759 | struct Channel * |
613 | chn = cadet_channel_create (&mem->grp, &mem->relays[i]); | 760 | chn = cadet_channel_create (&mem->grp, &mem->relays[i]); |
614 | cadet_send_msg (chn, &mem->join_req->header); | 761 | cadet_send_channel (chn, &mem->join_req->header); |
615 | } | 762 | } |
616 | } | 763 | } |
617 | 764 | ||
@@ -627,7 +774,7 @@ cadet_send_join_decision_cb (void *cls, | |||
627 | if (0 == memcmp (&hdcsn->member_key, &chn->member_key, sizeof (chn->member_key)) | 774 | if (0 == memcmp (&hdcsn->member_key, &chn->member_key, sizeof (chn->member_key)) |
628 | && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer))) | 775 | && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer))) |
629 | { | 776 | { |
630 | cadet_send_msg (chn, &hdcsn->header); | 777 | cadet_send_channel (chn, &hdcsn->header); |
631 | return GNUNET_NO; | 778 | return GNUNET_NO; |
632 | } | 779 | } |
633 | return GNUNET_YES; | 780 | return GNUNET_YES; |
@@ -651,29 +798,47 @@ cadet_send_join_decision (struct Group *grp, | |||
651 | * Iterator callback for sending a message to origin clients. | 798 | * Iterator callback for sending a message to origin clients. |
652 | */ | 799 | */ |
653 | static int | 800 | static int |
654 | cadet_send_members_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, | 801 | cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, |
655 | void *channel) | 802 | void *channel) |
656 | { | 803 | { |
657 | const struct GNUNET_MessageHeader *msg = cls; | 804 | const struct GNUNET_MessageHeader *msg = cls; |
658 | struct Channel *chn = channel; | 805 | struct Channel *chn = channel; |
659 | if (JOIN_ADMITTED == chn->join_status) | 806 | if (JOIN_ADMITTED == chn->join_status) |
660 | cadet_send_msg (chn, msg); | 807 | cadet_send_channel (chn, msg); |
661 | return GNUNET_YES; | 808 | return GNUNET_YES; |
662 | } | 809 | } |
663 | 810 | ||
664 | 811 | ||
812 | /** | ||
813 | * Send message to all connected children. | ||
814 | */ | ||
665 | static int | 815 | static int |
666 | cadet_send_members (struct GNUNET_HashCode *pub_key_hash, | 816 | cadet_send_children (struct GNUNET_HashCode *pub_key_hash, |
667 | const struct GNUNET_MessageHeader *msg) | 817 | const struct GNUNET_MessageHeader *msg) |
668 | { | 818 | { |
669 | int n = 0; | 819 | int n = 0; |
670 | if (channels_in != NULL) | 820 | if (channels_in != NULL) |
671 | n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash, | 821 | n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash, |
672 | cadet_send_members_cb, | 822 | cadet_send_cb, (void *) msg); |
673 | (void *) msg); | 823 | return n; |
824 | } | ||
825 | |||
826 | |||
827 | /** | ||
828 | * Send message to all connected parents. | ||
829 | */ | ||
830 | static int | ||
831 | cadet_send_parents (struct GNUNET_HashCode *pub_key_hash, | ||
832 | const struct GNUNET_MessageHeader *msg) | ||
833 | { | ||
834 | int n = 0; | ||
835 | if (channels_in != NULL) | ||
836 | n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash, | ||
837 | cadet_send_cb, (void *) msg); | ||
674 | return n; | 838 | return n; |
675 | } | 839 | } |
676 | 840 | ||
841 | |||
677 | /** | 842 | /** |
678 | * Handle a connecting client starting an origin. | 843 | * Handle a connecting client starting an origin. |
679 | */ | 844 | */ |
@@ -866,7 +1031,7 @@ static void | |||
866 | client_send_join_decision (struct Member *mem, | 1031 | client_send_join_decision (struct Member *mem, |
867 | const struct MulticastJoinDecisionMessageHeader *hdcsn) | 1032 | const struct MulticastJoinDecisionMessageHeader *hdcsn) |
868 | { | 1033 | { |
869 | client_send_msg (&mem->grp, &hdcsn->header); | 1034 | client_send_group (&mem->grp, &hdcsn->header); |
870 | 1035 | ||
871 | const struct MulticastJoinDecisionMessage * | 1036 | const struct MulticastJoinDecisionMessage * |
872 | dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; | 1037 | dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; |
@@ -959,9 +1124,9 @@ client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client, | |||
959 | } | 1124 | } |
960 | GNUNET_assert (GNUNET_YES == grp->is_origin); | 1125 | GNUNET_assert (GNUNET_YES == grp->is_origin); |
961 | orig = (struct Origin *) grp; | 1126 | orig = (struct Origin *) grp; |
1127 | |||
962 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ | 1128 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ |
963 | out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m); | 1129 | out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m); |
964 | |||
965 | out->fragment_id = GNUNET_htonll (++orig->max_fragment_id); | 1130 | out->fragment_id = GNUNET_htonll (++orig->max_fragment_id); |
966 | out->purpose.size = htonl (ntohs (out->header.size) | 1131 | out->purpose.size = htonl (ntohs (out->header.size) |
967 | - sizeof (out->header) | 1132 | - sizeof (out->header) |
@@ -976,7 +1141,7 @@ client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client, | |||
976 | } | 1141 | } |
977 | 1142 | ||
978 | client_send_all (&grp->pub_key_hash, &out->header); | 1143 | client_send_all (&grp->pub_key_hash, &out->header); |
979 | cadet_send_members (&grp->pub_key_hash, &out->header); | 1144 | cadet_send_children (&grp->pub_key_hash, &out->header); |
980 | GNUNET_free (out); | 1145 | GNUNET_free (out); |
981 | 1146 | ||
982 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1147 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
@@ -993,7 +1158,6 @@ client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client, | |||
993 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | 1158 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); |
994 | struct Member *mem; | 1159 | struct Member *mem; |
995 | struct GNUNET_MULTICAST_RequestHeader *out; | 1160 | struct GNUNET_MULTICAST_RequestHeader *out; |
996 | |||
997 | if (NULL == grp) | 1161 | if (NULL == grp) |
998 | { | 1162 | { |
999 | GNUNET_break (0); | 1163 | GNUNET_break (0); |
@@ -1002,9 +1166,9 @@ client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client, | |||
1002 | } | 1166 | } |
1003 | GNUNET_assert (GNUNET_NO == grp->is_origin); | 1167 | GNUNET_assert (GNUNET_NO == grp->is_origin); |
1004 | mem = (struct Member *) grp; | 1168 | mem = (struct Member *) grp; |
1169 | |||
1005 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ | 1170 | /* FIXME: yucky, should use separate message structs for P2P and CS! */ |
1006 | out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m); | 1171 | out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m); |
1007 | |||
1008 | out->member_key = mem->pub_key; | 1172 | out->member_key = mem->pub_key; |
1009 | out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id); | 1173 | out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id); |
1010 | out->purpose.size = htonl (ntohs (out->header.size) | 1174 | out->purpose.size = htonl (ntohs (out->header.size) |
@@ -1023,7 +1187,7 @@ client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client, | |||
1023 | { /* No local origins, send to remote origin */ | 1187 | { /* No local origins, send to remote origin */ |
1024 | if (NULL != mem->origin_channel) | 1188 | if (NULL != mem->origin_channel) |
1025 | { | 1189 | { |
1026 | cadet_send_msg (mem->origin_channel, &out->header); | 1190 | cadet_send_channel (mem->origin_channel, &out->header); |
1027 | } | 1191 | } |
1028 | else | 1192 | else |
1029 | { | 1193 | { |
@@ -1039,6 +1203,207 @@ client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client, | |||
1039 | 1203 | ||
1040 | 1204 | ||
1041 | /** | 1205 | /** |
1206 | * Incoming replay request from a client. | ||
1207 | */ | ||
1208 | static void | ||
1209 | client_recv_replay_request (void *cls, struct GNUNET_SERVER_Client *client, | ||
1210 | const struct GNUNET_MessageHeader *m) | ||
1211 | { | ||
1212 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | ||
1213 | struct Member *mem; | ||
1214 | if (NULL == grp) | ||
1215 | { | ||
1216 | GNUNET_break (0); | ||
1217 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1218 | return; | ||
1219 | } | ||
1220 | GNUNET_assert (GNUNET_NO == grp->is_origin); | ||
1221 | mem = (struct Member *) grp; | ||
1222 | |||
1223 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1224 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
1225 | &grp->pub_key_hash); | ||
1226 | if (NULL == grp_replay_req) | ||
1227 | { | ||
1228 | grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1229 | GNUNET_CONTAINER_multihashmap_put (replay_req_client, | ||
1230 | &grp->pub_key_hash, grp_replay_req, | ||
1231 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1232 | } | ||
1233 | struct MulticastReplayRequestMessage * | ||
1234 | rep = (struct MulticastReplayRequestMessage *) m; | ||
1235 | struct GNUNET_HashCode key_hash; | ||
1236 | replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset, | ||
1237 | rep->flags, &key_hash); | ||
1238 | GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client, | ||
1239 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1240 | |||
1241 | if (0 == client_send_origin (&grp->pub_key_hash, m)) | ||
1242 | { /* No local origin, replay from remote members / origin. */ | ||
1243 | if (NULL != mem->origin_channel) | ||
1244 | { | ||
1245 | cadet_send_channel (mem->origin_channel, m); | ||
1246 | } | ||
1247 | else | ||
1248 | { | ||
1249 | /* FIXME: not yet connected to origin */ | ||
1250 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1251 | return; | ||
1252 | } | ||
1253 | } | ||
1254 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | static int | ||
1259 | cadet_send_replay_response_cb (void *cls, | ||
1260 | const struct GNUNET_HashCode *key_hash, | ||
1261 | void *value) | ||
1262 | { | ||
1263 | struct Channel *chn = value; | ||
1264 | struct GNUNET_MessageHeader *msg = cls; | ||
1265 | |||
1266 | cadet_send_channel (chn, msg); | ||
1267 | return GNUNET_OK; | ||
1268 | } | ||
1269 | |||
1270 | |||
1271 | static int | ||
1272 | client_send_replay_response_cb (void *cls, | ||
1273 | const struct GNUNET_HashCode *key_hash, | ||
1274 | void *value) | ||
1275 | { | ||
1276 | struct GNUNET_SERVER_Client *client = value; | ||
1277 | struct GNUNET_MessageHeader *msg = cls; | ||
1278 | |||
1279 | client_send (client, msg); | ||
1280 | return GNUNET_OK; | ||
1281 | } | ||
1282 | |||
1283 | |||
1284 | /** | ||
1285 | * End of replay response from a client. | ||
1286 | */ | ||
1287 | static void | ||
1288 | client_recv_replay_response_end (void *cls, struct GNUNET_SERVER_Client *client, | ||
1289 | const struct GNUNET_MessageHeader *m) | ||
1290 | { | ||
1291 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | ||
1292 | if (NULL == grp) | ||
1293 | { | ||
1294 | GNUNET_break (0); | ||
1295 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1296 | return; | ||
1297 | } | ||
1298 | |||
1299 | struct MulticastReplayResponseMessage * | ||
1300 | res = (struct MulticastReplayResponseMessage *) m; | ||
1301 | |||
1302 | struct GNUNET_HashCode key_hash; | ||
1303 | replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, | ||
1304 | res->flags, &key_hash); | ||
1305 | |||
1306 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1307 | grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
1308 | &grp->pub_key_hash); | ||
1309 | if (NULL != grp_replay_req_cadet) | ||
1310 | { | ||
1311 | GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash); | ||
1312 | } | ||
1313 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1314 | grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
1315 | &grp->pub_key_hash); | ||
1316 | if (NULL != grp_replay_req_client) | ||
1317 | { | ||
1318 | GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash); | ||
1319 | } | ||
1320 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Incoming replay response from a client. | ||
1326 | * | ||
1327 | * Respond with a multicast message on success, or otherwise with an error code. | ||
1328 | */ | ||
1329 | static void | ||
1330 | client_recv_replay_response (void *cls, struct GNUNET_SERVER_Client *client, | ||
1331 | const struct GNUNET_MessageHeader *m) | ||
1332 | { | ||
1333 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | ||
1334 | if (NULL == grp) | ||
1335 | { | ||
1336 | GNUNET_break (0); | ||
1337 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1338 | return; | ||
1339 | } | ||
1340 | |||
1341 | struct MulticastReplayResponseMessage * | ||
1342 | res = (struct MulticastReplayResponseMessage *) m; | ||
1343 | |||
1344 | const struct GNUNET_MessageHeader *msg = m; | ||
1345 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | ||
1346 | { | ||
1347 | msg = (struct GNUNET_MessageHeader *) &res[1]; | ||
1348 | } | ||
1349 | |||
1350 | struct GNUNET_HashCode key_hash; | ||
1351 | replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, | ||
1352 | res->flags, &key_hash); | ||
1353 | |||
1354 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1355 | grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
1356 | &grp->pub_key_hash); | ||
1357 | if (NULL != grp_replay_req_cadet) | ||
1358 | { | ||
1359 | GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash, | ||
1360 | cadet_send_replay_response_cb, | ||
1361 | (void *) msg); | ||
1362 | } | ||
1363 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | ||
1364 | { | ||
1365 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1366 | grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client, | ||
1367 | &grp->pub_key_hash); | ||
1368 | if (NULL != grp_replay_req_client) | ||
1369 | { | ||
1370 | GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash, | ||
1371 | client_send_replay_response_cb, | ||
1372 | (void *) msg); | ||
1373 | } | ||
1374 | } | ||
1375 | else | ||
1376 | { | ||
1377 | client_recv_replay_response_end (cls, client, m); | ||
1378 | return; | ||
1379 | } | ||
1380 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1381 | } | ||
1382 | |||
1383 | |||
1384 | /** | ||
1385 | * Incoming replay request from a client. | ||
1386 | */ | ||
1387 | static void | ||
1388 | client_recv_replay_request_cancel (void *cls, struct GNUNET_SERVER_Client *client, | ||
1389 | const struct GNUNET_MessageHeader *m) | ||
1390 | { | ||
1391 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | ||
1392 | } | ||
1393 | |||
1394 | |||
1395 | /** | ||
1396 | * Incoming replay request from a client. | ||
1397 | */ | ||
1398 | static void | ||
1399 | client_recv_membership_test_result (void *cls, struct GNUNET_SERVER_Client *client, | ||
1400 | const struct GNUNET_MessageHeader *m) | ||
1401 | { | ||
1402 | struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group); | ||
1403 | } | ||
1404 | |||
1405 | |||
1406 | /** | ||
1042 | * A new client connected. | 1407 | * A new client connected. |
1043 | */ | 1408 | */ |
1044 | static void | 1409 | static void |
@@ -1053,22 +1418,37 @@ client_notify_connect (void *cls, struct GNUNET_SERVER_Client *client) | |||
1053 | * Message handlers for the server. | 1418 | * Message handlers for the server. |
1054 | */ | 1419 | */ |
1055 | static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { | 1420 | static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { |
1056 | { &client_recv_origin_start, NULL, | 1421 | { client_recv_origin_start, NULL, |
1057 | GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 }, | 1422 | GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 }, |
1058 | 1423 | ||
1059 | { &client_recv_member_join, NULL, | 1424 | { client_recv_member_join, NULL, |
1060 | GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 }, | 1425 | GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 }, |
1061 | 1426 | ||
1062 | { &client_recv_join_decision, NULL, | 1427 | { client_recv_join_decision, NULL, |
1063 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 }, | 1428 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 }, |
1064 | 1429 | ||
1065 | { &client_recv_multicast_message, NULL, | 1430 | { client_recv_multicast_message, NULL, |
1066 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, | 1431 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, |
1067 | 1432 | ||
1068 | { &client_recv_multicast_request, NULL, | 1433 | { client_recv_multicast_request, NULL, |
1069 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 }, | 1434 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 }, |
1070 | 1435 | ||
1071 | {NULL, NULL, 0, 0} | 1436 | { client_recv_replay_request, NULL, |
1437 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 }, | ||
1438 | |||
1439 | { client_recv_replay_request_cancel, NULL, | ||
1440 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL, 0 }, | ||
1441 | |||
1442 | { client_recv_replay_response, NULL, | ||
1443 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 }, | ||
1444 | |||
1445 | { client_recv_replay_response_end, NULL, | ||
1446 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, 0 }, | ||
1447 | |||
1448 | { client_recv_membership_test_result, NULL, | ||
1449 | GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT, 0 }, | ||
1450 | |||
1451 | { NULL, NULL, 0, 0 } | ||
1072 | }; | 1452 | }; |
1073 | 1453 | ||
1074 | 1454 | ||
@@ -1107,6 +1487,9 @@ cadet_notify_channel_end (void *cls, | |||
1107 | mem->origin_channel = NULL; | 1487 | mem->origin_channel = NULL; |
1108 | } | 1488 | } |
1109 | } | 1489 | } |
1490 | |||
1491 | while (GNUNET_YES == replay_req_remove_cadet (chn)); | ||
1492 | |||
1110 | GNUNET_free (chn); | 1493 | GNUNET_free (chn); |
1111 | } | 1494 | } |
1112 | 1495 | ||
@@ -1320,12 +1703,99 @@ cadet_recv_request (void *cls, | |||
1320 | 1703 | ||
1321 | 1704 | ||
1322 | /** | 1705 | /** |
1706 | * Incoming multicast replay request from CADET. | ||
1707 | */ | ||
1708 | int | ||
1709 | cadet_recv_replay_request (void *cls, | ||
1710 | struct GNUNET_CADET_Channel *channel, | ||
1711 | void **ctx, | ||
1712 | const struct GNUNET_MessageHeader *m) | ||
1713 | { | ||
1714 | struct MulticastReplayRequestMessage rep; | ||
1715 | uint16_t size = ntohs (m->size); | ||
1716 | if (size < sizeof (rep)) | ||
1717 | { | ||
1718 | GNUNET_break_op (0); | ||
1719 | return GNUNET_SYSERR; | ||
1720 | } | ||
1721 | struct Channel *chn = *ctx; | ||
1722 | |||
1723 | memcpy (&rep, m, sizeof (rep)); | ||
1724 | memcpy (&rep.member_key, &chn->member_key, sizeof (chn->member_key)); | ||
1725 | |||
1726 | struct GNUNET_CONTAINER_MultiHashMap * | ||
1727 | grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet, | ||
1728 | &chn->grp->pub_key_hash); | ||
1729 | if (NULL == grp_replay_req) | ||
1730 | { | ||
1731 | grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1732 | GNUNET_CONTAINER_multihashmap_put (replay_req_cadet, | ||
1733 | &chn->grp->pub_key_hash, grp_replay_req, | ||
1734 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1735 | } | ||
1736 | struct GNUNET_HashCode key_hash; | ||
1737 | replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset, | ||
1738 | rep.flags, &key_hash); | ||
1739 | GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn, | ||
1740 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1741 | |||
1742 | client_send_random (&chn->group_key_hash, &rep.header); | ||
1743 | return GNUNET_OK; | ||
1744 | } | ||
1745 | |||
1746 | |||
1747 | /** | ||
1748 | * Incoming multicast replay request cancellation from CADET. | ||
1749 | */ | ||
1750 | int | ||
1751 | cadet_recv_replay_request_cancel (void *cls, | ||
1752 | struct GNUNET_CADET_Channel *channel, | ||
1753 | void **ctx, | ||
1754 | const struct GNUNET_MessageHeader *m) | ||
1755 | { | ||
1756 | |||
1757 | } | ||
1758 | |||
1759 | |||
1760 | /** | ||
1761 | * Incoming multicast replay response from CADET. | ||
1762 | */ | ||
1763 | int | ||
1764 | cadet_recv_replay_response (void *cls, | ||
1765 | struct GNUNET_CADET_Channel *channel, | ||
1766 | void **ctx, | ||
1767 | const struct GNUNET_MessageHeader *m) | ||
1768 | { | ||
1769 | struct Channel *chn = *ctx; | ||
1770 | |||
1771 | /* @todo FIXME: got replay error response, send request to other members */ | ||
1772 | |||
1773 | return GNUNET_OK; | ||
1774 | } | ||
1775 | |||
1776 | |||
1777 | /** | ||
1323 | * Message handlers for CADET. | 1778 | * Message handlers for CADET. |
1324 | */ | 1779 | */ |
1325 | static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { | 1780 | static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { |
1326 | { &cadet_recv_join_request, GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 }, | 1781 | { cadet_recv_join_request, |
1327 | { &cadet_recv_message, GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, | 1782 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 }, |
1328 | { &cadet_recv_request, GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 }, | 1783 | |
1784 | { cadet_recv_message, | ||
1785 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, | ||
1786 | |||
1787 | { cadet_recv_request, | ||
1788 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 }, | ||
1789 | |||
1790 | { cadet_recv_replay_request, | ||
1791 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 }, | ||
1792 | |||
1793 | { cadet_recv_replay_request_cancel, | ||
1794 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL, 0 }, | ||
1795 | |||
1796 | { cadet_recv_replay_response, | ||
1797 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 }, | ||
1798 | |||
1329 | { NULL, 0, 0 } | 1799 | { NULL, 0, 0 } |
1330 | }; | 1800 | }; |
1331 | 1801 | ||
@@ -1350,6 +1820,8 @@ core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) | |||
1350 | group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | 1820 | group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); |
1351 | channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | 1821 | channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); |
1352 | channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); | 1822 | channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); |
1823 | replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1824 | replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); | ||
1353 | 1825 | ||
1354 | cadet = GNUNET_CADET_connect (cfg, NULL, | 1826 | cadet = GNUNET_CADET_connect (cfg, NULL, |
1355 | &cadet_notify_channel_new, | 1827 | &cadet_notify_channel_new, |
diff --git a/src/multicast/multicast.h b/src/multicast/multicast.h index 5dc803952..497d67683 100644 --- a/src/multicast/multicast.h +++ b/src/multicast/multicast.h | |||
@@ -27,6 +27,9 @@ | |||
27 | #ifndef MULTICAST_H | 27 | #ifndef MULTICAST_H |
28 | #define MULTICAST_H | 28 | #define MULTICAST_H |
29 | 29 | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_multicast_service.h" | ||
32 | |||
30 | GNUNET_NETWORK_STRUCT_BEGIN | 33 | GNUNET_NETWORK_STRUCT_BEGIN |
31 | 34 | ||
32 | 35 | ||
@@ -157,49 +160,91 @@ struct MulticastMembershipTestResultMessage | |||
157 | 160 | ||
158 | 161 | ||
159 | /** | 162 | /** |
160 | * Message sent from the client to the service to give the service | 163 | * Message sent from the client to the service OR the service to the |
161 | * a replayed message. | 164 | * client asking for a message fragment to be replayed. |
162 | */ | 165 | */ |
163 | struct MulticastReplayResponseMessage | 166 | struct MulticastReplayRequestMessage |
164 | { | 167 | { |
165 | 168 | ||
166 | /** | 169 | /** |
167 | * | 170 | * The message type can be either |
171 | * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST or | ||
172 | * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL. | ||
168 | */ | 173 | */ |
169 | struct GNUNET_MessageHeader header; | 174 | struct GNUNET_MessageHeader header; |
170 | 175 | ||
171 | /** | 176 | /** |
172 | * Unique ID that identifies the associated replay session. | 177 | * S->C: Public key of the member requesting replay. |
178 | * C->S: Unused. | ||
173 | */ | 179 | */ |
174 | uint32_t uid; | 180 | struct GNUNET_CRYPTO_EcdsaPublicKey member_key; |
175 | 181 | ||
176 | /** | 182 | /** |
177 | * An `enum GNUNET_MULTICAST_ReplayErrorCode` identifying issues (in NBO). | 183 | * ID of the message that is being requested. |
178 | */ | 184 | */ |
179 | int32_t error_code; | 185 | uint64_t fragment_id; |
180 | 186 | ||
181 | /* followed by replayed message */ | 187 | /** |
188 | * ID of the message that is being requested. | ||
189 | */ | ||
190 | uint64_t message_id; | ||
191 | |||
192 | /** | ||
193 | * Offset of the fragment that is being requested. | ||
194 | */ | ||
195 | uint64_t fragment_offset; | ||
182 | 196 | ||
197 | /** | ||
198 | * Additional flags for the request. | ||
199 | */ | ||
200 | uint64_t flags; | ||
201 | |||
202 | /** | ||
203 | * Replay request ID. | ||
204 | */ | ||
205 | uint32_t uid; | ||
183 | }; | 206 | }; |
184 | 207 | ||
185 | 208 | ||
186 | /** | 209 | /** |
187 | * Message sent from the client to the service to notify the service | 210 | * Message sent from the client to the service to give the service |
188 | * about the end of a replay session. | 211 | * a replayed message. |
189 | */ | 212 | */ |
190 | struct MulticastReplayEndMessage | 213 | struct MulticastReplayResponseMessage |
191 | { | 214 | { |
192 | 215 | ||
193 | /** | 216 | /** |
194 | * | 217 | * Type: GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE |
218 | * or GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END | ||
195 | */ | 219 | */ |
196 | struct GNUNET_MessageHeader header; | 220 | struct GNUNET_MessageHeader header; |
197 | 221 | ||
198 | /** | 222 | /** |
199 | * Unique ID that identifies the associated replay session. | 223 | * ID of the message that is being requested. |
200 | */ | 224 | */ |
201 | uint32_t uid; | 225 | uint64_t fragment_id; |
226 | |||
227 | /** | ||
228 | * ID of the message that is being requested. | ||
229 | */ | ||
230 | uint64_t message_id; | ||
231 | |||
232 | /** | ||
233 | * Offset of the fragment that is being requested. | ||
234 | */ | ||
235 | uint64_t fragment_offset; | ||
202 | 236 | ||
237 | /** | ||
238 | * Additional flags for the request. | ||
239 | */ | ||
240 | uint64_t flags; | ||
241 | |||
242 | /** | ||
243 | * An `enum GNUNET_MULTICAST_ReplayErrorCode` identifying issues (in NBO). | ||
244 | */ | ||
245 | int32_t error_code; | ||
246 | |||
247 | /* followed by replayed message */ | ||
203 | }; | 248 | }; |
204 | 249 | ||
205 | 250 | ||
@@ -253,6 +298,7 @@ struct MulticastMemberJoinMessage | |||
253 | /* Followed by struct GNUNET_MessageHeader join_msg */ | 298 | /* Followed by struct GNUNET_MessageHeader join_msg */ |
254 | }; | 299 | }; |
255 | 300 | ||
301 | |||
256 | #if NOT_USED | 302 | #if NOT_USED |
257 | /** | 303 | /** |
258 | * Message sent from the client to the service to broadcast to all group | 304 | * Message sent from the client to the service to broadcast to all group |
@@ -323,44 +369,6 @@ struct MulticastJoinMessage | |||
323 | 369 | ||
324 | 370 | ||
325 | /** | 371 | /** |
326 | * Message sent from the client to the service OR the service to the | ||
327 | * client asking for a message fragment to be replayed. | ||
328 | */ | ||
329 | struct MulticastReplayRequestMessage | ||
330 | { | ||
331 | |||
332 | /** | ||
333 | * The message type can be either | ||
334 | * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST or | ||
335 | * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL. | ||
336 | */ | ||
337 | struct GNUNET_MessageHeader header; | ||
338 | |||
339 | /** | ||
340 | * Replay request ID. | ||
341 | */ | ||
342 | uint32_t uid; | ||
343 | |||
344 | /** | ||
345 | * ID of the message that is being requested. | ||
346 | */ | ||
347 | uint64_t message_id; | ||
348 | |||
349 | /** | ||
350 | * Offset of the fragment that is being requested. | ||
351 | */ | ||
352 | uint64_t fragment_offset; | ||
353 | |||
354 | /** | ||
355 | * Additional flags for the request. | ||
356 | */ | ||
357 | uint64_t flags; | ||
358 | |||
359 | }; | ||
360 | |||
361 | |||
362 | |||
363 | /** | ||
364 | * Message sent from the client to the service to unicast to the group origin. | 372 | * Message sent from the client to the service to unicast to the group origin. |
365 | */ | 373 | */ |
366 | struct MulticastUnicastToOriginMessage | 374 | struct MulticastUnicastToOriginMessage |
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c index ef4cc73e7..9f0c77f36 100644 --- a/src/multicast/multicast_api.c +++ b/src/multicast/multicast_api.c | |||
@@ -137,6 +137,11 @@ struct GNUNET_MULTICAST_Member | |||
137 | 137 | ||
138 | GNUNET_MULTICAST_JoinDecisionCallback join_dcsn_cb; | 138 | GNUNET_MULTICAST_JoinDecisionCallback join_dcsn_cb; |
139 | 139 | ||
140 | /** | ||
141 | * Replay fragment -> struct GNUNET_MULTICAST_MemberReplayHandle * | ||
142 | */ | ||
143 | struct GNUNET_CONTAINER_MultiHashMap *replay_reqs; | ||
144 | |||
140 | uint64_t next_fragment_id; | 145 | uint64_t next_fragment_id; |
141 | }; | 146 | }; |
142 | 147 | ||
@@ -176,6 +181,8 @@ struct GNUNET_MULTICAST_MembershipTestHandle | |||
176 | */ | 181 | */ |
177 | struct GNUNET_MULTICAST_ReplayHandle | 182 | struct GNUNET_MULTICAST_ReplayHandle |
178 | { | 183 | { |
184 | struct GNUNET_MULTICAST_Group *grp; | ||
185 | struct MulticastReplayRequestMessage req; | ||
179 | }; | 186 | }; |
180 | 187 | ||
181 | 188 | ||
@@ -184,6 +191,9 @@ struct GNUNET_MULTICAST_ReplayHandle | |||
184 | */ | 191 | */ |
185 | struct GNUNET_MULTICAST_MemberReplayHandle | 192 | struct GNUNET_MULTICAST_MemberReplayHandle |
186 | { | 193 | { |
194 | |||
195 | GNUNET_MULTICAST_ResultCallback result_cb; | ||
196 | void *result_cls; | ||
187 | }; | 197 | }; |
188 | 198 | ||
189 | 199 | ||
@@ -263,11 +273,14 @@ group_recv_message (void *cls, | |||
263 | struct GNUNET_MULTICAST_MessageHeader * | 273 | struct GNUNET_MULTICAST_MessageHeader * |
264 | mmsg = (struct GNUNET_MULTICAST_MessageHeader *) msg; | 274 | mmsg = (struct GNUNET_MULTICAST_MessageHeader *) msg; |
265 | 275 | ||
276 | if (GNUNET_YES == grp->is_disconnecting) | ||
277 | return; | ||
278 | |||
266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 279 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
267 | "Calling message callback with a message of size %u.\n", | 280 | "Calling message callback with a message of size %u.\n", |
268 | ntohs (mmsg->header.size)); | 281 | ntohs (mmsg->header.size)); |
269 | 282 | ||
270 | if (GNUNET_YES != grp->is_disconnecting && NULL != grp->message_cb) | 283 | if (NULL != grp->message_cb) |
271 | grp->message_cb (grp->cb_cls, mmsg); | 284 | grp->message_cb (grp->cb_cls, mmsg); |
272 | } | 285 | } |
273 | 286 | ||
@@ -297,6 +310,73 @@ origin_recv_request (void *cls, | |||
297 | 310 | ||
298 | 311 | ||
299 | /** | 312 | /** |
313 | * Receive multicast replay request from service. | ||
314 | */ | ||
315 | static void | ||
316 | group_recv_replay_request (void *cls, | ||
317 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
318 | const struct GNUNET_MessageHeader *msg) | ||
319 | { | ||
320 | struct GNUNET_MULTICAST_Group * | ||
321 | grp = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp)); | ||
322 | struct MulticastReplayRequestMessage * | ||
323 | rep = (struct MulticastReplayRequestMessage *) msg; | ||
324 | |||
325 | if (GNUNET_YES == grp->is_disconnecting) | ||
326 | return; | ||
327 | |||
328 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got replay request.\n"); | ||
329 | |||
330 | if (0 != rep->fragment_id) | ||
331 | { | ||
332 | if (NULL != grp->replay_frag_cb) | ||
333 | { | ||
334 | struct GNUNET_MULTICAST_ReplayHandle * rh = GNUNET_malloc (sizeof (*rh)); | ||
335 | rh->grp = grp; | ||
336 | rh->req = *rep; | ||
337 | grp->replay_frag_cb (grp->cb_cls, &rep->member_key, | ||
338 | GNUNET_ntohll (rep->fragment_id), | ||
339 | GNUNET_ntohll (rep->flags), rh); | ||
340 | } | ||
341 | } | ||
342 | else if (0 != rep->message_id) | ||
343 | { | ||
344 | if (NULL != grp->replay_msg_cb) | ||
345 | { | ||
346 | struct GNUNET_MULTICAST_ReplayHandle * rh = GNUNET_malloc (sizeof (*rh)); | ||
347 | rh->grp = grp; | ||
348 | rh->req = *rep; | ||
349 | grp->replay_msg_cb (grp->cb_cls, &rep->member_key, | ||
350 | GNUNET_ntohll (rep->message_id), | ||
351 | GNUNET_ntohll (rep->fragment_offset), | ||
352 | GNUNET_ntohll (rep->flags), rh); | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Receive multicast replay request from service. | ||
360 | */ | ||
361 | static void | ||
362 | member_recv_replay_response (void *cls, | ||
363 | struct GNUNET_CLIENT_MANAGER_Connection *client, | ||
364 | const struct GNUNET_MessageHeader *msg) | ||
365 | { | ||
366 | struct GNUNET_MULTICAST_Group *grp; | ||
367 | struct GNUNET_MULTICAST_Member * | ||
368 | mem = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*grp)); | ||
369 | grp = &mem->grp; | ||
370 | struct MulticastReplayResponseMessage * | ||
371 | res = (struct MulticastReplayResponseMessage *) msg; | ||
372 | |||
373 | if (GNUNET_YES == grp->is_disconnecting) | ||
374 | return; | ||
375 | |||
376 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got replay response.\n"); | ||
377 | } | ||
378 | |||
379 | /** | ||
300 | * Member receives join decision. | 380 | * Member receives join decision. |
301 | */ | 381 | */ |
302 | static void | 382 | static void |
@@ -369,20 +449,24 @@ member_recv_join_decision (void *cls, | |||
369 | */ | 449 | */ |
370 | static struct GNUNET_CLIENT_MANAGER_MessageHandler origin_handlers[] = | 450 | static struct GNUNET_CLIENT_MANAGER_MessageHandler origin_handlers[] = |
371 | { | 451 | { |
372 | { &group_recv_disconnect, NULL, 0, 0, GNUNET_NO }, | 452 | { group_recv_disconnect, NULL, 0, 0, GNUNET_NO }, |
373 | 453 | ||
374 | { &group_recv_message, NULL, | 454 | { group_recv_message, NULL, |
375 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | 455 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, |
376 | sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES }, | 456 | sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES }, |
377 | 457 | ||
378 | { &origin_recv_request, NULL, | 458 | { origin_recv_request, NULL, |
379 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, | 459 | GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, |
380 | sizeof (struct GNUNET_MULTICAST_RequestHeader), GNUNET_YES }, | 460 | sizeof (struct GNUNET_MULTICAST_RequestHeader), GNUNET_YES }, |
381 | 461 | ||
382 | { &group_recv_join_request, NULL, | 462 | { group_recv_join_request, NULL, |
383 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, | 463 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, |
384 | sizeof (struct MulticastJoinRequestMessage), GNUNET_YES }, | 464 | sizeof (struct MulticastJoinRequestMessage), GNUNET_YES }, |
385 | 465 | ||
466 | { group_recv_replay_request, NULL, | ||
467 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
468 | sizeof (struct MulticastReplayRequestMessage), GNUNET_NO }, | ||
469 | |||
386 | { NULL, NULL, 0, 0, GNUNET_NO } | 470 | { NULL, NULL, 0, 0, GNUNET_NO } |
387 | }; | 471 | }; |
388 | 472 | ||
@@ -392,20 +476,28 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler origin_handlers[] = | |||
392 | */ | 476 | */ |
393 | static struct GNUNET_CLIENT_MANAGER_MessageHandler member_handlers[] = | 477 | static struct GNUNET_CLIENT_MANAGER_MessageHandler member_handlers[] = |
394 | { | 478 | { |
395 | { &group_recv_disconnect, NULL, 0, 0, GNUNET_NO }, | 479 | { group_recv_disconnect, NULL, 0, 0, GNUNET_NO }, |
396 | 480 | ||
397 | { &group_recv_message, NULL, | 481 | { group_recv_message, NULL, |
398 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, | 482 | GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, |
399 | sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES }, | 483 | sizeof (struct GNUNET_MULTICAST_MessageHeader), GNUNET_YES }, |
400 | 484 | ||
401 | { &group_recv_join_request, NULL, | 485 | { group_recv_join_request, NULL, |
402 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, | 486 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, |
403 | sizeof (struct MulticastJoinRequestMessage), GNUNET_YES }, | 487 | sizeof (struct MulticastJoinRequestMessage), GNUNET_YES }, |
404 | 488 | ||
405 | { &member_recv_join_decision, NULL, | 489 | { member_recv_join_decision, NULL, |
406 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, | 490 | GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, |
407 | sizeof (struct MulticastJoinDecisionMessage), GNUNET_YES }, | 491 | sizeof (struct MulticastJoinDecisionMessage), GNUNET_YES }, |
408 | 492 | ||
493 | { group_recv_replay_request, NULL, | ||
494 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, | ||
495 | sizeof (struct MulticastReplayRequestMessage), GNUNET_NO }, | ||
496 | |||
497 | { member_recv_replay_response, NULL, | ||
498 | GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, | ||
499 | sizeof (struct MulticastReplayRequestMessage), GNUNET_NO }, | ||
500 | |||
409 | { NULL, NULL, 0, 0, GNUNET_NO } | 501 | { NULL, NULL, 0, 0, GNUNET_NO } |
410 | }; | 502 | }; |
411 | 503 | ||
@@ -514,15 +606,45 @@ GNUNET_MULTICAST_membership_test_result (struct GNUNET_MULTICAST_MembershipTestH | |||
514 | /** | 606 | /** |
515 | * Replay a message fragment for the multicast group. | 607 | * Replay a message fragment for the multicast group. |
516 | * | 608 | * |
517 | * @param rh Replay handle identifying which replay operation was requested. | 609 | * @param rh |
518 | * @param msg Replayed message fragment, NULL if unknown/error. | 610 | * Replay handle identifying which replay operation was requested. |
519 | * @param ec Error code. | 611 | * @param msg |
612 | * Replayed message fragment, NULL if not found / an error occurred. | ||
613 | * @param ec | ||
614 | * Error code. See enum GNUNET_MULTICAST_ReplayErrorCode | ||
615 | * If not #GNUNET_MULTICAST_REC_OK, the replay handle is invalidated. | ||
520 | */ | 616 | */ |
521 | void | 617 | void |
522 | GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, | 618 | GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, |
523 | const struct GNUNET_MessageHeader *msg, | 619 | const struct GNUNET_MessageHeader *msg, |
524 | enum GNUNET_MULTICAST_ReplayErrorCode ec) | 620 | enum GNUNET_MULTICAST_ReplayErrorCode ec) |
525 | { | 621 | { |
622 | uint8_t msg_size = (NULL != msg) ? ntohs (msg->size) : 0; | ||
623 | struct MulticastReplayResponseMessage * | ||
624 | res = GNUNET_malloc (sizeof (*res) + msg_size); | ||
625 | *res = (struct MulticastReplayResponseMessage) { | ||
626 | .header = { | ||
627 | .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE), | ||
628 | .size = htons (sizeof (*res) + msg_size), | ||
629 | }, | ||
630 | .fragment_id = rh->req.fragment_id, | ||
631 | .message_id = rh->req.message_id, | ||
632 | .fragment_offset = rh->req.fragment_offset, | ||
633 | .flags = rh->req.flags, | ||
634 | .error_code = htonl (ec), | ||
635 | }; | ||
636 | |||
637 | if (GNUNET_MULTICAST_REC_OK == ec) | ||
638 | { | ||
639 | GNUNET_assert (NULL != msg); | ||
640 | memcpy (&res[1], msg, msg_size); | ||
641 | } | ||
642 | |||
643 | GNUNET_CLIENT_MANAGER_transmit (rh->grp->client, &res->header); | ||
644 | GNUNET_free (res); | ||
645 | |||
646 | if (GNUNET_MULTICAST_REC_OK != ec) | ||
647 | GNUNET_free (rh); | ||
526 | } | 648 | } |
527 | 649 | ||
528 | 650 | ||
@@ -536,6 +658,19 @@ GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, | |||
536 | void | 658 | void |
537 | GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh) | 659 | GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh) |
538 | { | 660 | { |
661 | struct MulticastReplayResponseMessage end = { | ||
662 | .header = { | ||
663 | .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END), | ||
664 | .size = htons (sizeof (end)), | ||
665 | }, | ||
666 | .fragment_id = rh->req.fragment_id, | ||
667 | .message_id = rh->req.message_id, | ||
668 | .fragment_offset = rh->req.fragment_offset, | ||
669 | .flags = rh->req.flags, | ||
670 | }; | ||
671 | |||
672 | GNUNET_CLIENT_MANAGER_transmit (rh->grp->client, &end.header); | ||
673 | GNUNET_free (rh); | ||
539 | } | 674 | } |
540 | 675 | ||
541 | 676 | ||
@@ -827,6 +962,7 @@ GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
827 | grp->join_req_cb = join_request_cb; | 962 | grp->join_req_cb = join_request_cb; |
828 | grp->member_test_cb = member_test_cb; | 963 | grp->member_test_cb = member_test_cb; |
829 | grp->replay_frag_cb = replay_frag_cb; | 964 | grp->replay_frag_cb = replay_frag_cb; |
965 | grp->replay_msg_cb = replay_msg_cb; | ||
830 | grp->message_cb = message_cb; | 966 | grp->message_cb = message_cb; |
831 | grp->cb_cls = cls; | 967 | grp->cb_cls = cls; |
832 | 968 | ||
@@ -864,26 +1000,55 @@ GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem, | |||
864 | } | 1000 | } |
865 | 1001 | ||
866 | 1002 | ||
1003 | void | ||
1004 | member_replay_request (struct GNUNET_MULTICAST_Member *mem, | ||
1005 | uint64_t fragment_id, | ||
1006 | uint64_t message_id, | ||
1007 | uint64_t fragment_offset, | ||
1008 | uint64_t flags) | ||
1009 | { | ||
1010 | struct MulticastReplayRequestMessage rep = { | ||
1011 | .header = { | ||
1012 | .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST), | ||
1013 | .size = htons (sizeof (rep)), | ||
1014 | }, | ||
1015 | .fragment_id = GNUNET_htonll (fragment_id), | ||
1016 | .message_id = GNUNET_htonll (message_id), | ||
1017 | .fragment_offset = GNUNET_htonll (fragment_offset), | ||
1018 | .flags = GNUNET_htonll (flags), | ||
1019 | }; | ||
1020 | GNUNET_CLIENT_MANAGER_transmit (mem->grp.client, &rep.header); | ||
1021 | } | ||
1022 | |||
1023 | |||
867 | /** | 1024 | /** |
868 | * Request a fragment to be replayed by fragment ID. | 1025 | * Request a fragment to be replayed by fragment ID. |
869 | * | 1026 | * |
870 | * Useful if messages below the @e max_known_fragment_id given when joining are | 1027 | * Useful if messages below the @e max_known_fragment_id given when joining are |
871 | * needed and not known to the client. | 1028 | * needed and not known to the client. |
872 | * | 1029 | * |
873 | * @param member Membership handle. | 1030 | * @param member |
874 | * @param fragment_id ID of a message fragment that this client would like to | 1031 | * Membership handle. |
875 | see replayed. | 1032 | * @param fragment_id |
876 | * @param flags Additional flags for the replay request. It is used and defined | 1033 | * ID of a message fragment that this client would like to see replayed. |
877 | * by the replay callback. FIXME: which replay callback? FIXME: use enum? | 1034 | * @param flags |
878 | * FIXME: why not pass reply cb here? | 1035 | * Additional flags for the replay request. |
879 | * @return Replay request handle, NULL on error. | 1036 | * It is used and defined by GNUNET_MULTICAST_ReplayFragmentCallback |
1037 | * @param result_cb | ||
1038 | * Function to call when the replayed message fragment arrives. | ||
1039 | * @param result_cls | ||
1040 | * Closure for @a result_cb. | ||
1041 | * | ||
1042 | * @return Replay request handle. | ||
880 | */ | 1043 | */ |
881 | struct GNUNET_MULTICAST_MemberReplayHandle * | 1044 | struct GNUNET_MULTICAST_MemberReplayHandle * |
882 | GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member, | 1045 | GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *mem, |
883 | uint64_t fragment_id, | 1046 | uint64_t fragment_id, |
884 | uint64_t flags) | 1047 | uint64_t flags, |
1048 | GNUNET_MULTICAST_ResultCallback result_cb, | ||
1049 | void *result_cls) | ||
885 | { | 1050 | { |
886 | return NULL; | 1051 | member_replay_request (mem, fragment_id, 0, 0, flags); |
887 | } | 1052 | } |
888 | 1053 | ||
889 | 1054 | ||
@@ -893,24 +1058,31 @@ GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member, | |||
893 | * Useful if messages below the @e max_known_fragment_id given when joining are | 1058 | * Useful if messages below the @e max_known_fragment_id given when joining are |
894 | * needed and not known to the client. | 1059 | * needed and not known to the client. |
895 | * | 1060 | * |
896 | * @param member Membership handle. | 1061 | * @param member |
897 | * @param message_id ID of the message this client would like to see replayed. | 1062 | * Membership handle. |
898 | * @param fragment_offset Offset of the fragment within the message to replay. | 1063 | * @param message_id |
899 | * @param flags Additional flags for the replay request. It is used & defined | 1064 | * ID of the message this client would like to see replayed. |
900 | * by the replay callback. | 1065 | * @param fragment_offset |
901 | * @param result_cb Function to be called for the replayed message. | 1066 | * Offset of the fragment within the message to replay. |
902 | * @param result_cb_cls Closure for @a result_cb. | 1067 | * @param flags |
1068 | * Additional flags for the replay request. | ||
1069 | * It is used & defined by GNUNET_MULTICAST_ReplayMessageCallback | ||
1070 | * @param result_cb | ||
1071 | * Function to call for each replayed message fragment. | ||
1072 | * @param result_cls | ||
1073 | * Closure for @a result_cb. | ||
1074 | * | ||
903 | * @return Replay request handle, NULL on error. | 1075 | * @return Replay request handle, NULL on error. |
904 | */ | 1076 | */ |
905 | struct GNUNET_MULTICAST_MemberReplayHandle * | 1077 | struct GNUNET_MULTICAST_MemberReplayHandle * |
906 | GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member, | 1078 | GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *mem, |
907 | uint64_t message_id, | 1079 | uint64_t message_id, |
908 | uint64_t fragment_offset, | 1080 | uint64_t fragment_offset, |
909 | uint64_t flags, | 1081 | uint64_t flags, |
910 | GNUNET_MULTICAST_ResultCallback result_cb, | 1082 | GNUNET_MULTICAST_ResultCallback result_cb, |
911 | void *result_cb_cls) | 1083 | void *result_cls) |
912 | { | 1084 | { |
913 | return NULL; | 1085 | member_replay_request (mem, 0, message_id, fragment_offset, flags); |
914 | } | 1086 | } |
915 | 1087 | ||
916 | 1088 | ||
diff --git a/src/multicast/test_multicast.c b/src/multicast/test_multicast.c index 528033452..d9b9ce0df 100644 --- a/src/multicast/test_multicast.c +++ b/src/multicast/test_multicast.c | |||
@@ -84,17 +84,21 @@ struct GNUNET_MessageHeader *join_req, *join_resp; | |||
84 | 84 | ||
85 | enum | 85 | enum |
86 | { | 86 | { |
87 | TEST_NONE = 0, | 87 | TEST_NONE = 0, |
88 | TEST_ORIGIN_START = 1, | 88 | TEST_ORIGIN_START = 1, |
89 | TEST_MEMBER_JOIN_REFUSE = 2, | 89 | TEST_MEMBER_JOIN_REFUSE = 2, |
90 | TEST_MEMBER_JOIN_ADMIT = 3, | 90 | TEST_MEMBER_JOIN_ADMIT = 3, |
91 | TEST_ORIGIN_TO_ALL = 4, | 91 | TEST_ORIGIN_TO_ALL = 4, |
92 | TEST_ORIGIN_TO_ALL_RECV = 5, | 92 | TEST_ORIGIN_TO_ALL_RECV = 5, |
93 | TEST_MEMBER_TO_ORIGIN = 6, | 93 | TEST_MEMBER_TO_ORIGIN = 6, |
94 | TEST_MEMBER_PART = 7, | 94 | TEST_MEMBER_REPLAY_ERROR = 7, |
95 | TEST_ORIGIN_STOP = 8, | 95 | TEST_MEMBER_REPLAY_OK = 8, |
96 | TEST_MEMBER_PART = 9, | ||
97 | TEST_ORIGIN_STOP = 10, | ||
96 | } test; | 98 | } test; |
97 | 99 | ||
100 | uint64_t replay_fragment_id; | ||
101 | uint64_t replay_flags; | ||
98 | 102 | ||
99 | static void | 103 | static void |
100 | member_join (int t); | 104 | member_join (int t); |
@@ -230,56 +234,6 @@ tmit_notify (void *cls, size_t *data_size, void *data) | |||
230 | 234 | ||
231 | 235 | ||
232 | static void | 236 | static void |
233 | origin_recv_replay_msg (void *cls, | ||
234 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
235 | uint64_t message_id, | ||
236 | uint64_t fragment_offset, | ||
237 | uint64_t flags, | ||
238 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
239 | { | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
241 | "Test #%u: origin_recv_replay_msg()\n", test); | ||
242 | } | ||
243 | |||
244 | |||
245 | static void | ||
246 | member_recv_replay_msg (void *cls, | ||
247 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
248 | uint64_t message_id, | ||
249 | uint64_t fragment_offset, | ||
250 | uint64_t flags, | ||
251 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
252 | { | ||
253 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
254 | "Test #%u: member_recv_replay_msg()\n", test); | ||
255 | } | ||
256 | |||
257 | |||
258 | static void | ||
259 | origin_recv_replay_frag (void *cls, | ||
260 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
261 | uint64_t fragment_id, | ||
262 | uint64_t flags, | ||
263 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
264 | { | ||
265 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
266 | "Test #%u: origin_recv_replay_frag()\n", test); | ||
267 | } | ||
268 | |||
269 | |||
270 | static void | ||
271 | member_recv_replay_frag (void *cls, | ||
272 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
273 | uint64_t fragment_id, | ||
274 | uint64_t flags, | ||
275 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
276 | { | ||
277 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
278 | "Test #%u: member_recv_replay_frag()\n", test); | ||
279 | } | ||
280 | |||
281 | |||
282 | static void | ||
283 | origin_recv_membership_test (void *cls, | 237 | origin_recv_membership_test (void *cls, |
284 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | 238 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, |
285 | uint64_t message_id, | 239 | uint64_t message_id, |
@@ -339,6 +293,7 @@ member_parted (void *cls) | |||
339 | { | 293 | { |
340 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 294 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
341 | "Test #%u: member_parted()\n", test); | 295 | "Test #%u: member_parted()\n", test); |
296 | member = NULL; | ||
342 | 297 | ||
343 | switch (test) | 298 | switch (test) |
344 | { | 299 | { |
@@ -359,20 +314,135 @@ member_parted (void *cls) | |||
359 | 314 | ||
360 | 315 | ||
361 | static void | 316 | static void |
317 | schedule_member_part (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
318 | { | ||
319 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
320 | "Test #%u: schedule_member_part()\n", test); | ||
321 | GNUNET_MULTICAST_member_part (member, member_parted, NULL); | ||
322 | } | ||
323 | |||
324 | |||
325 | static void | ||
362 | member_part () | 326 | member_part () |
363 | { | 327 | { |
364 | test = TEST_MEMBER_PART; | 328 | test = TEST_MEMBER_PART; |
365 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 329 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
366 | "Test #%u: member_part()\n", test); | 330 | "Test #%u: member_part()\n", test); |
367 | GNUNET_MULTICAST_member_part (member, member_parted, NULL); | 331 | GNUNET_SCHEDULER_add_now (schedule_member_part, NULL); |
368 | member = NULL; | ||
369 | } | 332 | } |
370 | 333 | ||
371 | 334 | ||
372 | static void | 335 | static void |
373 | schedule_member_part (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 336 | member_replay_ok () |
374 | { | 337 | { |
375 | GNUNET_MULTICAST_member_part (member, member_parted, NULL); | 338 | test = TEST_MEMBER_REPLAY_OK; |
339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "Test #%u: member_replay_ok()\n", test); | ||
341 | replay_fragment_id = 1; | ||
342 | replay_flags = 1 | 1<<11; | ||
343 | GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id, | ||
344 | replay_flags, NULL, NULL); | ||
345 | } | ||
346 | |||
347 | |||
348 | static void | ||
349 | member_replay_error () | ||
350 | { | ||
351 | test = TEST_MEMBER_REPLAY_ERROR; | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
353 | "Test #%u: member_replay_error()\n", test); | ||
354 | replay_fragment_id = 1234; | ||
355 | replay_flags = 11 | 1<<11; | ||
356 | GNUNET_MULTICAST_member_replay_fragment (member, replay_fragment_id, | ||
357 | replay_flags, NULL, NULL); | ||
358 | } | ||
359 | |||
360 | |||
361 | static void | ||
362 | origin_recv_replay_msg (void *cls, | ||
363 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
364 | uint64_t message_id, | ||
365 | uint64_t fragment_offset, | ||
366 | uint64_t flags, | ||
367 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
368 | { | ||
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
370 | "Test #%u: origin_recv_replay_msg()\n", test); | ||
371 | GNUNET_assert (0); | ||
372 | } | ||
373 | |||
374 | |||
375 | static void | ||
376 | member_recv_replay_msg (void *cls, | ||
377 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
378 | uint64_t message_id, | ||
379 | uint64_t fragment_offset, | ||
380 | uint64_t flags, | ||
381 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
382 | { | ||
383 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
384 | "Test #%u: member_recv_replay_msg()\n", test); | ||
385 | GNUNET_assert (0); | ||
386 | } | ||
387 | |||
388 | |||
389 | static void | ||
390 | origin_recv_replay_frag (void *cls, | ||
391 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
392 | uint64_t fragment_id, | ||
393 | uint64_t flags, | ||
394 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
395 | { | ||
396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
397 | "Test #%u: origin_recv_replay_frag()" | ||
398 | " - fragment_id=%" PRIu64 " flags=%" PRIu64 "\n", | ||
399 | test, fragment_id, flags); | ||
400 | GNUNET_assert (replay_fragment_id == fragment_id && replay_flags == flags); | ||
401 | switch (test) | ||
402 | { | ||
403 | case TEST_MEMBER_REPLAY_ERROR: | ||
404 | GNUNET_MULTICAST_replay_response (rh, NULL, GNUNET_SYSERR); | ||
405 | member_replay_ok (); | ||
406 | break; | ||
407 | |||
408 | case TEST_MEMBER_REPLAY_OK: | ||
409 | { | ||
410 | struct GNUNET_MULTICAST_MessageHeader mmsg = { | ||
411 | .header = { | ||
412 | .type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE), | ||
413 | .size = htons (sizeof (mmsg)), | ||
414 | }, | ||
415 | .fragment_id = GNUNET_htonll (1), | ||
416 | .message_id = GNUNET_htonll (1), | ||
417 | .fragment_offset = 0, | ||
418 | .group_generation = GNUNET_htonll (1), | ||
419 | .flags = 0, | ||
420 | }; | ||
421 | member_cls.n = 0; | ||
422 | member_cls.msgs_expected = 1; | ||
423 | GNUNET_MULTICAST_replay_response (rh, &mmsg.header, GNUNET_MULTICAST_REC_OK); | ||
424 | GNUNET_MULTICAST_replay_response_end (rh); | ||
425 | break; | ||
426 | } | ||
427 | |||
428 | default: | ||
429 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
430 | "Invalid test #%d in origin_recv_replay_frag()\n", test); | ||
431 | GNUNET_assert (0); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | |||
436 | static void | ||
437 | member_recv_replay_frag (void *cls, | ||
438 | const struct GNUNET_CRYPTO_EcdsaPublicKey *member_key, | ||
439 | uint64_t fragment_id, | ||
440 | uint64_t flags, | ||
441 | struct GNUNET_MULTICAST_ReplayHandle *rh) | ||
442 | { | ||
443 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
444 | "Test #%u: member_recv_replay_frag()\n", test); | ||
445 | GNUNET_assert (0); | ||
376 | } | 446 | } |
377 | 447 | ||
378 | 448 | ||
@@ -385,14 +455,14 @@ origin_recv_request (void *cls, | |||
385 | "Test #%u: origin_recv_request()\n", test); | 455 | "Test #%u: origin_recv_request()\n", test); |
386 | if (++ocls->n != ocls->msgs_expected) | 456 | if (++ocls->n != ocls->msgs_expected) |
387 | return; | 457 | return; |
388 | 458 | ||
389 | GNUNET_assert (0 == memcmp (&req->member_key, | 459 | GNUNET_assert (0 == memcmp (&req->member_key, |
390 | &member_pub_key, sizeof (member_pub_key))); | 460 | &member_pub_key, sizeof (member_pub_key))); |
391 | 461 | ||
392 | 462 | ||
393 | // FIXME: check message content | 463 | // FIXME: check message content |
394 | 464 | ||
395 | member_part (); | 465 | member_replay_error (); |
396 | } | 466 | } |
397 | 467 | ||
398 | 468 | ||
@@ -437,6 +507,11 @@ member_recv_message (void *cls, | |||
437 | member_to_origin (); | 507 | member_to_origin (); |
438 | break; | 508 | break; |
439 | 509 | ||
510 | case TEST_MEMBER_REPLAY_OK: | ||
511 | GNUNET_assert (replay_fragment_id == GNUNET_ntohll (msg->fragment_id)); | ||
512 | member_part (); | ||
513 | break; | ||
514 | |||
440 | default: | 515 | default: |
441 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 516 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
442 | "Invalid test #%d in origin_recv_message()\n", test); | 517 | "Invalid test #%d in origin_recv_message()\n", test); |
@@ -516,7 +591,7 @@ member_recv_join_decision (void *cls, | |||
516 | GNUNET_assert (0 == relay_count); | 591 | GNUNET_assert (0 == relay_count); |
517 | GNUNET_SCHEDULER_add_now (schedule_member_part, NULL); | 592 | GNUNET_SCHEDULER_add_now (schedule_member_part, NULL); |
518 | break; | 593 | break; |
519 | 594 | ||
520 | case TEST_MEMBER_JOIN_ADMIT: | 595 | case TEST_MEMBER_JOIN_ADMIT: |
521 | GNUNET_assert (1 == relay_count); | 596 | GNUNET_assert (1 == relay_count); |
522 | GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer))); | 597 | GNUNET_assert (0 == memcmp (relays, &this_peer, sizeof (this_peer))); |
@@ -551,13 +626,13 @@ origin_recv_join_request (void *cls, | |||
551 | join_resp->size = htons (sizeof (join_resp) + data_size); | 626 | join_resp->size = htons (sizeof (join_resp) + data_size); |
552 | join_resp->type = htons (456); | 627 | join_resp->type = htons (456); |
553 | memcpy (&join_resp[1], data, data_size); | 628 | memcpy (&join_resp[1], data, data_size); |
554 | 629 | ||
555 | switch (test) | 630 | switch (test) |
556 | { | 631 | { |
557 | case TEST_MEMBER_JOIN_REFUSE: | 632 | case TEST_MEMBER_JOIN_REFUSE: |
558 | GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp); | 633 | GNUNET_MULTICAST_join_decision (jh, GNUNET_NO, 0, NULL, join_resp); |
559 | break; | 634 | break; |
560 | 635 | ||
561 | case TEST_MEMBER_JOIN_ADMIT: | 636 | case TEST_MEMBER_JOIN_ADMIT: |
562 | GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp); | 637 | GNUNET_MULTICAST_join_decision (jh, GNUNET_YES, 1, &this_peer, join_resp); |
563 | break; | 638 | break; |