diff options
Diffstat (limited to 'src/multicast/gnunet-service-multicast.c')
-rw-r--r-- | src/multicast/gnunet-service-multicast.c | 562 |
1 files changed, 517 insertions, 45 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, |