aboutsummaryrefslogtreecommitdiff
path: root/src/multicast/gnunet-service-multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/multicast/gnunet-service-multicast.c')
-rw-r--r--src/multicast/gnunet-service-multicast.c562
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;
88static struct GNUNET_CONTAINER_MultiHashMap *group_members; 88static 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 */
94static struct GNUNET_CONTAINER_MultiHashMap *channels_in; 94static 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 */
100static struct GNUNET_CONTAINER_MultiHashMap *channels_out; 100static 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 */
107static 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 */
114static 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 */
105enum JoinStatus 120enum JoinStatus
@@ -294,6 +309,15 @@ struct Member
294}; 309};
295 310
296 311
312struct 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
402void
403replay_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 */
426static int
427replay_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 */
463static int
464replay_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 */
554static void
555client_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 */
439static void 569static void
440client_send_msg (const struct Group *grp, 570client_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 */
646static int
647client_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 */
556static void 703static void
557cadet_send_msg (struct Channel *chn, const struct GNUNET_MessageHeader *msg) 704cadet_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
604cadet_send_join_request (struct Member *mem) 751cadet_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 */
653static int 800static int
654cadet_send_members_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, 801cadet_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 */
665static int 815static int
666cadet_send_members (struct GNUNET_HashCode *pub_key_hash, 816cadet_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 */
830static int
831cadet_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
866client_send_join_decision (struct Member *mem, 1031client_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 */
1208static void
1209client_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
1258static int
1259cadet_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
1271static int
1272client_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 */
1287static void
1288client_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 */
1329static void
1330client_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 */
1387static void
1388client_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 */
1398static void
1399client_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 */
1044static void 1409static 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 */
1055static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { 1420static 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 */
1708int
1709cadet_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 */
1750int
1751cadet_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 */
1763int
1764cadet_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 */
1325static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { 1780static 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,