aboutsummaryrefslogtreecommitdiff
path: root/src/multicast
diff options
context:
space:
mode:
authorxrs <xrs@mail36.net>2018-01-02 17:12:39 +0100
committerxrs <xrs@mail36.net>2018-01-02 17:12:39 +0100
commit3611a5295f95fad5d9e1fdb3866e7db9ecf8f47e (patch)
treedb191de206319d924f1bb49e65cdf8a9612ba85c /src/multicast
parentcc90f1df695ccee3d35fe00fa179a856e4128009 (diff)
parent61f532f18450e0d7c72f0c17f4a20b5854cf53bf (diff)
downloadgnunet-3611a5295f95fad5d9e1fdb3866e7db9ecf8f47e.tar.gz
gnunet-3611a5295f95fad5d9e1fdb3866e7db9ecf8f47e.zip
Merge branch 'master' of ssh://gnunet.org/gnunet
Diffstat (limited to 'src/multicast')
-rw-r--r--src/multicast/Makefile.am2
-rw-r--r--src/multicast/gnunet-service-multicast.c248
-rw-r--r--src/multicast/multicast_api.c51
-rw-r--r--src/multicast/test_multicast_multipeer.c312
4 files changed, 342 insertions, 271 deletions
diff --git a/src/multicast/Makefile.am b/src/multicast/Makefile.am
index 13212bca3..48185e1a4 100644
--- a/src/multicast/Makefile.am
+++ b/src/multicast/Makefile.am
@@ -19,7 +19,7 @@ endif
19lib_LTLIBRARIES = libgnunetmulticast.la 19lib_LTLIBRARIES = libgnunetmulticast.la
20 20
21libgnunetmulticast_la_SOURCES = \ 21libgnunetmulticast_la_SOURCES = \
22 multicast_api.c 22 multicast_api.c multicast.h
23libgnunetmulticast_la_LIBADD = \ 23libgnunetmulticast_la_LIBADD = \
24 $(top_builddir)/src/util/libgnunetutil.la \ 24 $(top_builddir)/src/util/libgnunetutil.la \
25 $(GN_LIBINTL) $(XLIB) 25 $(GN_LIBINTL) $(XLIB)
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c
index 2f4dc8a14..ba1086cc5 100644
--- a/src/multicast/gnunet-service-multicast.c
+++ b/src/multicast/gnunet-service-multicast.c
@@ -137,6 +137,7 @@ struct Channel
137 */ 137 */
138 struct GNUNET_CADET_Channel *channel; 138 struct GNUNET_CADET_Channel *channel;
139 139
140 // FIXME: not used
140 /** 141 /**
141 * CADET transmission handle. 142 * CADET transmission handle.
142 */ 143 */
@@ -228,7 +229,7 @@ struct Group
228 /** 229 /**
229 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO 230 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
230 */ 231 */
231 uint8_t disconnected; 232 uint8_t is_disconnected;
232 233
233 /** 234 /**
234 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)? 235 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
@@ -365,6 +366,8 @@ client_send_join_decision (struct Member *mem,
365static void 366static void
366shutdown_task (void *cls) 367shutdown_task (void *cls)
367{ 368{
369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370 "shutting down\n");
368 if (NULL != cadet) 371 if (NULL != cadet)
369 { 372 {
370 GNUNET_CADET_disconnect (cadet); 373 GNUNET_CADET_disconnect (cadet);
@@ -420,6 +423,11 @@ cleanup_member (struct Member *mem)
420 GNUNET_free (mem->join_dcsn); 423 GNUNET_free (mem->join_dcsn);
421 mem->join_dcsn = NULL; 424 mem->join_dcsn = NULL;
422 } 425 }
426 if (NULL != mem->origin_channel)
427 {
428 GNUNET_CADET_channel_destroy (mem->origin_channel->channel);
429 mem->origin_channel = NULL;
430 }
423 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem); 431 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
424 GNUNET_free (mem); 432 GNUNET_free (mem);
425} 433}
@@ -553,36 +561,47 @@ client_send (struct GNUNET_SERVICE_Client *client,
553 * Send message to all clients connected to the group. 561 * Send message to all clients connected to the group.
554 */ 562 */
555static void 563static void
556client_send_group (const struct Group *grp, 564client_send_group_keep_envelope (const struct Group *grp,
557 const struct GNUNET_MessageHeader *msg) 565 struct GNUNET_MQ_Envelope *env)
558{ 566{
559 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 567 struct ClientList *cli = grp->clients_head;
560 "%p Sending message to all clients of the group.\n", grp);
561 568
562 struct ClientList *cl = grp->clients_head; 569 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
563 while (NULL != cl) 570 "%p Sending message to all clients of the group.\n",
571 grp);
572 while (NULL != cli)
564 { 573 {
565 struct GNUNET_MQ_Envelope * 574 GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
566 env = GNUNET_MQ_msg_copy (msg); 575 env);
567 576 cli = cli->next;
568 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cl->client),
569 env);
570 cl = cl->next;
571 } 577 }
572} 578}
573 579
574 580
575/** 581/**
582 * Send message to all clients connected to the group and
583 * takes care of freeing @env.
584 */
585static void
586client_send_group (const struct Group *grp,
587 struct GNUNET_MQ_Envelope *env)
588{
589 client_send_group_keep_envelope (grp, env);
590 GNUNET_MQ_discard (env);
591}
592
593
594/**
576 * Iterator callback for sending a message to origin clients. 595 * Iterator callback for sending a message to origin clients.
577 */ 596 */
578static int 597static int
579client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, 598client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
580 void *origin) 599 void *origin)
581{ 600{
582 const struct GNUNET_MessageHeader *msg = cls; 601 struct GNUNET_MQ_Envelope *env = cls;
583 struct Member *orig = origin; 602 struct Member *orig = origin;
584 603
585 client_send_group (&orig->group, msg); 604 client_send_group_keep_envelope (&orig->group, env);
586 return GNUNET_YES; 605 return GNUNET_YES;
587} 606}
588 607
@@ -594,12 +613,12 @@ static int
594client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, 613client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
595 void *member) 614 void *member)
596{ 615{
597 const struct GNUNET_MessageHeader *msg = cls; 616 struct GNUNET_MQ_Envelope *env = cls;
598 struct Member *mem = member; 617 struct Member *mem = member;
599 618
600 if (NULL != mem->join_dcsn) 619 if (NULL != mem->join_dcsn)
601 { /* Only send message to admitted members */ 620 { /* Only send message to admitted members */
602 client_send_group (&mem->group, msg); 621 client_send_group_keep_envelope (&mem->group, env);
603 } 622 }
604 return GNUNET_YES; 623 return GNUNET_YES;
605} 624}
@@ -615,15 +634,16 @@ client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
615 */ 634 */
616static int 635static int
617client_send_all (struct GNUNET_HashCode *pub_key_hash, 636client_send_all (struct GNUNET_HashCode *pub_key_hash,
618 const struct GNUNET_MessageHeader *msg) 637 struct GNUNET_MQ_Envelope *env)
619{ 638{
620 int n = 0; 639 int n = 0;
621 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, 640 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
622 client_send_origin_cb, 641 client_send_origin_cb,
623 (void *) msg); 642 (void *) env);
624 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash, 643 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
625 client_send_member_cb, 644 client_send_member_cb,
626 (void *) msg); 645 (void *) env);
646 GNUNET_MQ_discard (env);
627 return n; 647 return n;
628} 648}
629 649
@@ -636,14 +656,14 @@ client_send_all (struct GNUNET_HashCode *pub_key_hash,
636 */ 656 */
637static int 657static int
638client_send_random (struct GNUNET_HashCode *pub_key_hash, 658client_send_random (struct GNUNET_HashCode *pub_key_hash,
639 const struct GNUNET_MessageHeader *msg) 659 struct GNUNET_MQ_Envelope *env)
640{ 660{
641 int n = 0; 661 int n = 0;
642 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb, 662 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
643 (void *) msg); 663 (void *) env);
644 if (n <= 0) 664 if (n <= 0)
645 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb, 665 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
646 (void *) msg); 666 (void *) env);
647 return n; 667 return n;
648} 668}
649 669
@@ -658,12 +678,12 @@ client_send_random (struct GNUNET_HashCode *pub_key_hash,
658 */ 678 */
659static int 679static int
660client_send_origin (struct GNUNET_HashCode *pub_key_hash, 680client_send_origin (struct GNUNET_HashCode *pub_key_hash,
661 const struct GNUNET_MessageHeader *msg) 681 struct GNUNET_MQ_Envelope *env)
662{ 682{
663 int n = 0; 683 int n = 0;
664 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash, 684 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
665 client_send_origin_cb, 685 client_send_origin_cb,
666 (void *) msg); 686 (void *) env);
667 return n; 687 return n;
668} 688}
669 689
@@ -677,17 +697,12 @@ client_send_origin (struct GNUNET_HashCode *pub_key_hash,
677static void 697static void
678client_send_ack (struct GNUNET_HashCode *pub_key_hash) 698client_send_ack (struct GNUNET_HashCode *pub_key_hash)
679{ 699{
700 struct GNUNET_MQ_Envelope *env;
701
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 702 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
681 "Sending message ACK to client.\n"); 703 "Sending message ACK to client.\n");
682 704 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
683 static struct GNUNET_MessageHeader *msg = NULL; 705 client_send_all (pub_key_hash, env);
684 if (NULL == msg)
685 {
686 msg = GNUNET_malloc (sizeof (*msg));
687 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
688 msg->size = htons (sizeof (*msg));
689 }
690 client_send_all (pub_key_hash, msg);
691} 706}
692 707
693 708
@@ -983,7 +998,8 @@ handle_cadet_join_request (void *cls,
983 chn->peer = req->peer; 998 chn->peer = req->peer;
984 chn->join_status = JOIN_WAITING; 999 chn->join_status = JOIN_WAITING;
985 1000
986 client_send_all (&group_pub_hash, &req->header); 1001 client_send_all (&group_pub_hash,
1002 GNUNET_MQ_msg_copy (&req->header));
987} 1003}
988 1004
989 1005
@@ -1102,7 +1118,8 @@ handle_cadet_message (void *cls,
1102{ 1118{
1103 struct Channel *chn = cls; 1119 struct Channel *chn = cls;
1104 GNUNET_CADET_receive_done (chn->channel); 1120 GNUNET_CADET_receive_done (chn->channel);
1105 client_send_all (&chn->group_pub_hash, &msg->header); 1121 client_send_all (&chn->group_pub_hash,
1122 GNUNET_MQ_msg_copy (&msg->header));
1106} 1123}
1107 1124
1108 1125
@@ -1153,30 +1170,32 @@ handle_cadet_request (void *cls,
1153{ 1170{
1154 struct Channel *chn = cls; 1171 struct Channel *chn = cls;
1155 GNUNET_CADET_receive_done (chn->channel); 1172 GNUNET_CADET_receive_done (chn->channel);
1156 client_send_origin (&chn->group_pub_hash, &req->header); 1173 client_send_origin (&chn->group_pub_hash,
1174 GNUNET_MQ_msg_copy (&req->header));
1157} 1175}
1158 1176
1159 1177
1160static int 1178// FIXME: do checks in handle_cadet_replay_request
1161check_cadet_replay_request (void *cls, 1179//static int
1162 const struct MulticastReplayRequestMessage *req) 1180//check_cadet_replay_request (void *cls,
1163{ 1181// const struct MulticastReplayRequestMessage *req)
1164 uint16_t size = ntohs (req->header.size); 1182//{
1165 if (size < sizeof (*req)) 1183// uint16_t size = ntohs (req->header.size);
1166 { 1184// if (size < sizeof (*req))
1167 GNUNET_break_op (0); 1185// {
1168 return GNUNET_SYSERR; 1186// GNUNET_break_op (0);
1169 } 1187// return GNUNET_SYSERR;
1170 1188// }
1171 struct Channel *chn = cls; 1189//
1172 if (NULL == chn) 1190// struct Channel *chn = cls;
1173 { 1191// if (NULL == chn)
1174 GNUNET_break_op (0); 1192// {
1175 return GNUNET_SYSERR; 1193// GNUNET_break_op (0);
1176 } 1194// return GNUNET_SYSERR;
1177 1195// }
1178 return GNUNET_OK; 1196//
1179} 1197// return GNUNET_OK;
1198//}
1180 1199
1181 1200
1182/** 1201/**
@@ -1187,6 +1206,7 @@ handle_cadet_replay_request (void *cls,
1187 const struct MulticastReplayRequestMessage *req) 1206 const struct MulticastReplayRequestMessage *req)
1188{ 1207{
1189 struct Channel *chn = cls; 1208 struct Channel *chn = cls;
1209
1190 GNUNET_CADET_receive_done (chn->channel); 1210 GNUNET_CADET_receive_done (chn->channel);
1191 1211
1192 struct MulticastReplayRequestMessage rep = *req; 1212 struct MulticastReplayRequestMessage rep = *req;
@@ -1203,12 +1223,16 @@ handle_cadet_replay_request (void *cls,
1203 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1223 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1204 } 1224 }
1205 struct GNUNET_HashCode key_hash; 1225 struct GNUNET_HashCode key_hash;
1206 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset, 1226 replay_key_hash (rep.fragment_id,
1207 rep.flags, &key_hash); 1227 rep.message_id,
1228 rep.fragment_offset,
1229 rep.flags,
1230 &key_hash);
1208 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn, 1231 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1232 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1210 1233
1211 client_send_random (&chn->group_pub_hash, &rep.header); 1234 client_send_random (&chn->group_pub_hash,
1235 GNUNET_MQ_msg_copy (&rep.header));
1212} 1236}
1213 1237
1214 1238
@@ -1290,10 +1314,10 @@ cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1290 struct MulticastJoinDecisionMessageHeader, 1314 struct MulticastJoinDecisionMessageHeader,
1291 chn), 1315 chn),
1292 1316
1293 GNUNET_MQ_hd_var_size (cadet_replay_request, 1317 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1294 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1318 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1295 struct MulticastReplayRequestMessage, 1319 struct MulticastReplayRequestMessage,
1296 chn), 1320 chn),
1297 1321
1298 GNUNET_MQ_hd_var_size (cadet_replay_response, 1322 GNUNET_MQ_hd_var_size (cadet_replay_response,
1299 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 1323 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
@@ -1357,6 +1381,7 @@ handle_client_origin_start (void *cls,
1357 grp->is_origin = GNUNET_YES; 1381 grp->is_origin = GNUNET_YES;
1358 grp->pub_key = pub_key; 1382 grp->pub_key = pub_key;
1359 grp->pub_key_hash = pub_key_hash; 1383 grp->pub_key_hash = pub_key_hash;
1384 grp->is_disconnected = GNUNET_NO;
1360 1385
1361 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig, 1386 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1362 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1387 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
@@ -1379,10 +1404,10 @@ handle_client_origin_start (void *cls,
1379 struct MulticastJoinRequestMessage, 1404 struct MulticastJoinRequestMessage,
1380 grp), 1405 grp),
1381 1406
1382 GNUNET_MQ_hd_var_size (cadet_replay_request, 1407 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1383 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1408 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1384 struct MulticastReplayRequestMessage, 1409 struct MulticastReplayRequestMessage,
1385 grp), 1410 grp),
1386 1411
1387 GNUNET_MQ_hd_var_size (cadet_replay_response, 1412 GNUNET_MQ_hd_var_size (cadet_replay_response,
1388 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 1413 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
@@ -1484,6 +1509,7 @@ handle_client_member_join (void *cls,
1484 grp->is_origin = GNUNET_NO; 1509 grp->is_origin = GNUNET_NO;
1485 grp->pub_key = msg->group_pub_key; 1510 grp->pub_key = msg->group_pub_key;
1486 grp->pub_key_hash = pub_key_hash; 1511 grp->pub_key_hash = pub_key_hash;
1512 grp->is_disconnected = GNUNET_NO;
1487 group_set_cadet_port_hash (grp); 1513 group_set_cadet_port_hash (grp);
1488 1514
1489 if (NULL == grp_mem) 1515 if (NULL == grp_mem)
@@ -1494,7 +1520,8 @@ handle_client_member_join (void *cls,
1494 } 1520 }
1495 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem, 1521 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1496 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1522 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1497 1523
1524 // FIXME: should the members hash map have option UNIQUE_FAST?
1498 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem, 1525 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1499 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1526 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1500 } 1527 }
@@ -1509,10 +1536,11 @@ handle_client_member_join (void *cls,
1509 1536
1510 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key); 1537 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Client connected to group %s as member %s (%s).\n", 1539 "Client connected to group %s as member %s (%s). size = %d\n",
1513 GNUNET_h2s (&grp->pub_key_hash), 1540 GNUNET_h2s (&grp->pub_key_hash),
1514 GNUNET_h2s2 (&mem->pub_key_hash), 1541 GNUNET_h2s2 (&mem->pub_key_hash),
1515 str); 1542 str,
1543 GNUNET_CONTAINER_multihashmap_size (members));
1516 GNUNET_free (str); 1544 GNUNET_free (str);
1517 1545
1518 if (NULL != mem->join_dcsn) 1546 if (NULL != mem->join_dcsn)
@@ -1567,7 +1595,9 @@ handle_client_member_join (void *cls,
1567 GNUNET_free (mem->join_req); 1595 GNUNET_free (mem->join_req);
1568 mem->join_req = req; 1596 mem->join_req = req;
1569 1597
1570 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header)) 1598 if (0 ==
1599 client_send_origin (&grp->pub_key_hash,
1600 GNUNET_MQ_msg_copy (&mem->join_req->header)))
1571 { /* No local origins, send to remote origin */ 1601 { /* No local origins, send to remote origin */
1572 cadet_send_join_request (mem); 1602 cadet_send_join_request (mem);
1573 } 1603 }
@@ -1580,7 +1610,7 @@ static void
1580client_send_join_decision (struct Member *mem, 1610client_send_join_decision (struct Member *mem,
1581 const struct MulticastJoinDecisionMessageHeader *hdcsn) 1611 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1582{ 1612{
1583 client_send_group (&mem->group, &hdcsn->header); 1613 client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
1584 1614
1585 const struct MulticastJoinDecisionMessage * 1615 const struct MulticastJoinDecisionMessage *
1586 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1]; 1616 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
@@ -1621,8 +1651,9 @@ handle_client_join_decision (void *cls,
1621 GNUNET_SERVICE_client_drop (client); 1651 GNUNET_SERVICE_client_drop (client);
1622 return; 1652 return;
1623 } 1653 }
1654 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1655 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1625 "%p Got join decision from client for group %s..\n", 1656 "%p got join decision from client for group %s..\n",
1626 grp, GNUNET_h2s (&grp->pub_key_hash)); 1657 grp, GNUNET_h2s (&grp->pub_key_hash));
1627 1658
1628 struct GNUNET_CONTAINER_MultiHashMap * 1659 struct GNUNET_CONTAINER_MultiHashMap *
@@ -1652,6 +1683,32 @@ handle_client_join_decision (void *cls,
1652} 1683}
1653 1684
1654 1685
1686static void
1687handle_client_part_request (void *cls,
1688 const struct GNUNET_MessageHeader *msg)
1689{
1690 struct Client *c = cls;
1691 struct GNUNET_SERVICE_Client *client = c->client;
1692 struct Group *grp = c->group;
1693 struct GNUNET_MQ_Envelope *env;
1694
1695 if (NULL == grp)
1696 {
1697 GNUNET_break (0);
1698 GNUNET_SERVICE_client_drop (client);
1699 return;
1700 }
1701 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1703 "%p got part request from client for group %s.\n",
1704 grp, GNUNET_h2s (&grp->pub_key_hash));
1705 grp->is_disconnected = GNUNET_YES;
1706 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
1707 client_send_group (grp, env);
1708 GNUNET_SERVICE_client_continue (client);
1709}
1710
1711
1655static int 1712static int
1656check_client_multicast_message (void *cls, 1713check_client_multicast_message (void *cls,
1657 const struct GNUNET_MULTICAST_MessageHeader *msg) 1714 const struct GNUNET_MULTICAST_MessageHeader *msg)
@@ -1667,6 +1724,7 @@ static void
1667handle_client_multicast_message (void *cls, 1724handle_client_multicast_message (void *cls,
1668 const struct GNUNET_MULTICAST_MessageHeader *msg) 1725 const struct GNUNET_MULTICAST_MessageHeader *msg)
1669{ 1726{
1727 // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
1670 struct Client *c = cls; 1728 struct Client *c = cls;
1671 struct GNUNET_SERVICE_Client *client = c->client; 1729 struct GNUNET_SERVICE_Client *client = c->client;
1672 struct Group *grp = c->group; 1730 struct Group *grp = c->group;
@@ -1680,6 +1738,7 @@ handle_client_multicast_message (void *cls,
1680 GNUNET_assert (GNUNET_YES == grp->is_origin); 1738 GNUNET_assert (GNUNET_YES == grp->is_origin);
1681 struct Origin *orig = grp->origin; 1739 struct Origin *orig = grp->origin;
1682 1740
1741 // FIXME: use GNUNET_MQ_msg_copy
1683 /* FIXME: yucky, should use separate message structs for P2P and CS! */ 1742 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1684 struct GNUNET_MULTICAST_MessageHeader * 1743 struct GNUNET_MULTICAST_MessageHeader *
1685 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header); 1744 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
@@ -1696,7 +1755,7 @@ handle_client_multicast_message (void *cls,
1696 GNUNET_assert (0); 1755 GNUNET_assert (0);
1697 } 1756 }
1698 1757
1699 client_send_all (&grp->pub_key_hash, &out->header); 1758 client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
1700 cadet_send_children (&grp->pub_key_hash, &out->header); 1759 cadet_send_children (&grp->pub_key_hash, &out->header);
1701 client_send_ack (&grp->pub_key_hash); 1760 client_send_ack (&grp->pub_key_hash);
1702 GNUNET_free (out); 1761 GNUNET_free (out);
@@ -1730,6 +1789,7 @@ handle_client_multicast_request (void *cls,
1730 GNUNET_SERVICE_client_drop (client); 1789 GNUNET_SERVICE_client_drop (client);
1731 return; 1790 return;
1732 } 1791 }
1792 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1733 GNUNET_assert (GNUNET_NO == grp->is_origin); 1793 GNUNET_assert (GNUNET_NO == grp->is_origin);
1734 struct Member *mem = grp->member; 1794 struct Member *mem = grp->member;
1735 1795
@@ -1751,7 +1811,9 @@ handle_client_multicast_request (void *cls,
1751 } 1811 }
1752 1812
1753 uint8_t send_ack = GNUNET_YES; 1813 uint8_t send_ack = GNUNET_YES;
1754 if (0 == client_send_origin (&grp->pub_key_hash, &out->header)) 1814 if (0 ==
1815 client_send_origin (&grp->pub_key_hash,
1816 GNUNET_MQ_msg_copy (&out->header)))
1755 { /* No local origins, send to remote origin */ 1817 { /* No local origins, send to remote origin */
1756 if (NULL != mem->origin_channel) 1818 if (NULL != mem->origin_channel)
1757 { 1819 {
@@ -1792,6 +1854,7 @@ handle_client_replay_request (void *cls,
1792 GNUNET_SERVICE_client_drop (client); 1854 GNUNET_SERVICE_client_drop (client);
1793 return; 1855 return;
1794 } 1856 }
1857 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1795 GNUNET_assert (GNUNET_NO == grp->is_origin); 1858 GNUNET_assert (GNUNET_NO == grp->is_origin);
1796 struct Member *mem = grp->member; 1859 struct Member *mem = grp->member;
1797 1860
@@ -1812,7 +1875,9 @@ handle_client_replay_request (void *cls,
1812 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client, 1875 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1813 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1876 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1814 1877
1815 if (0 == client_send_origin (&grp->pub_key_hash, &rep->header)) 1878 if (0 ==
1879 client_send_origin (&grp->pub_key_hash,
1880 GNUNET_MQ_msg_copy (&rep->header)))
1816 { /* No local origin, replay from remote members / origin. */ 1881 { /* No local origin, replay from remote members / origin. */
1817 if (NULL != mem->origin_channel) 1882 if (NULL != mem->origin_channel)
1818 { 1883 {
@@ -1821,6 +1886,7 @@ handle_client_replay_request (void *cls,
1821 else 1886 else
1822 { 1887 {
1823 /* FIXME: not yet connected to origin */ 1888 /* FIXME: not yet connected to origin */
1889 GNUNET_assert (0);
1824 GNUNET_SERVICE_client_drop (client); 1890 GNUNET_SERVICE_client_drop (client);
1825 return; 1891 return;
1826 } 1892 }
@@ -1880,6 +1946,7 @@ handle_client_replay_response_end (void *cls,
1880 GNUNET_SERVICE_client_drop (client); 1946 GNUNET_SERVICE_client_drop (client);
1881 return; 1947 return;
1882 } 1948 }
1949 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1883 1950
1884 struct GNUNET_HashCode key_hash; 1951 struct GNUNET_HashCode key_hash;
1885 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset, 1952 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
@@ -1939,6 +2006,7 @@ handle_client_replay_response (void *cls,
1939 GNUNET_SERVICE_client_drop (client); 2006 GNUNET_SERVICE_client_drop (client);
1940 return; 2007 return;
1941 } 2008 }
2009 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1942 2010
1943 const struct GNUNET_MessageHeader *msg = &res->header; 2011 const struct GNUNET_MessageHeader *msg = &res->header;
1944 if (GNUNET_MULTICAST_REC_OK == res->error_code) 2012 if (GNUNET_MULTICAST_REC_OK == res->error_code)
@@ -2033,9 +2101,14 @@ client_notify_disconnect (void *cls,
2033 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member", 2101 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2034 GNUNET_h2s (&grp->pub_key_hash)); 2102 GNUNET_h2s (&grp->pub_key_hash));
2035 2103
2104 // FIXME (due to protocol change): here we must not remove all clients,
2105 // only the one we were notified about!
2036 struct ClientList *cl = grp->clients_head; 2106 struct ClientList *cl = grp->clients_head;
2037 while (NULL != cl) 2107 while (NULL != cl)
2038 { 2108 {
2109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2110 "iterating clients for group %p\n",
2111 grp);
2039 if (cl->client == client) 2112 if (cl->client == client)
2040 { 2113 {
2041 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl); 2114 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
@@ -2049,16 +2122,7 @@ client_notify_disconnect (void *cls,
2049 2122
2050 if (NULL == grp->clients_head) 2123 if (NULL == grp->clients_head)
2051 { /* Last client disconnected. */ 2124 { /* Last client disconnected. */
2052#if FIXME 2125 cleanup_group (grp);
2053 if (NULL != grp->tmit_head)
2054 { /* Send pending messages via CADET before cleanup. */
2055 transmit_message (grp);
2056 }
2057 else
2058#endif
2059 {
2060 cleanup_group (grp);
2061 }
2062 } 2126 }
2063} 2127}
2064 2128
@@ -2103,9 +2167,9 @@ run (void *cls,
2103GNUNET_SERVICE_MAIN 2167GNUNET_SERVICE_MAIN
2104("multicast", 2168("multicast",
2105 GNUNET_SERVICE_OPTION_NONE, 2169 GNUNET_SERVICE_OPTION_NONE,
2106 run, 2170 &run,
2107 client_notify_connect, 2171 &client_notify_connect,
2108 client_notify_disconnect, 2172 &client_notify_disconnect,
2109 NULL, 2173 NULL,
2110 GNUNET_MQ_hd_fixed_size (client_origin_start, 2174 GNUNET_MQ_hd_fixed_size (client_origin_start,
2111 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 2175 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
@@ -2119,6 +2183,10 @@ GNUNET_SERVICE_MAIN
2119 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 2183 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2120 struct MulticastJoinDecisionMessageHeader, 2184 struct MulticastJoinDecisionMessageHeader,
2121 NULL), 2185 NULL),
2186 GNUNET_MQ_hd_fixed_size (client_part_request,
2187 GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
2188 struct GNUNET_MessageHeader,
2189 NULL),
2122 GNUNET_MQ_hd_var_size (client_multicast_message, 2190 GNUNET_MQ_hd_var_size (client_multicast_message,
2123 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 2191 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2124 struct GNUNET_MULTICAST_MessageHeader, 2192 struct GNUNET_MULTICAST_MessageHeader,
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c
index a8b1dee40..3c911f48a 100644
--- a/src/multicast/multicast_api.c
+++ b/src/multicast/multicast_api.c
@@ -542,31 +542,12 @@ group_cleanup (struct GNUNET_MULTICAST_Group *grp)
542 542
543 543
544static void 544static void
545group_disconnect (struct GNUNET_MULTICAST_Group *grp, 545handle_group_part_ack (void *cls,
546 GNUNET_ContinuationCallback cb, 546 const struct GNUNET_MessageHeader *msg)
547 void *cls)
548{ 547{
549 grp->is_disconnecting = GNUNET_YES; 548 struct GNUNET_MULTICAST_Group *grp = cls;
550 grp->disconnect_cb = cb;
551 grp->disconnect_cls = cls;
552 549
553 if (NULL != grp->mq) 550 group_cleanup (grp);
554 {
555 struct GNUNET_MQ_Envelope *last = GNUNET_MQ_get_last_envelope (grp->mq);
556 if (NULL != last)
557 {
558 GNUNET_MQ_notify_sent (last,
559 (GNUNET_SCHEDULER_TaskCallback) group_cleanup, grp);
560 }
561 else
562 {
563 group_cleanup (grp);
564 }
565 }
566 else
567 {
568 group_cleanup (grp);
569 }
570} 551}
571 552
572 553
@@ -779,6 +760,10 @@ origin_connect (struct GNUNET_MULTICAST_Origin *orig)
779 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 760 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
780 struct MulticastJoinRequestMessage, 761 struct MulticastJoinRequestMessage,
781 grp), 762 grp),
763 GNUNET_MQ_hd_fixed_size (group_part_ack,
764 GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK,
765 struct GNUNET_MessageHeader,
766 grp),
782 GNUNET_MQ_hd_fixed_size (group_replay_request, 767 GNUNET_MQ_hd_fixed_size (group_replay_request,
783 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 768 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
784 struct MulticastReplayRequestMessage, 769 struct MulticastReplayRequestMessage,
@@ -879,8 +864,13 @@ GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig,
879 void *stop_cls) 864 void *stop_cls)
880{ 865{
881 struct GNUNET_MULTICAST_Group *grp = &orig->grp; 866 struct GNUNET_MULTICAST_Group *grp = &orig->grp;
867 struct GNUNET_MQ_Envelope *env;
882 868
883 group_disconnect (grp, stop_cb, stop_cls); 869 grp->is_disconnecting = GNUNET_YES;
870 grp->disconnect_cb = stop_cb;
871 grp->disconnect_cls = stop_cls;
872 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST);
873 GNUNET_MQ_send (grp->mq, env);
884} 874}
885 875
886 876
@@ -1065,6 +1055,10 @@ member_connect (struct GNUNET_MULTICAST_Member *mem)
1065 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 1055 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1066 struct MulticastJoinDecisionMessageHeader, 1056 struct MulticastJoinDecisionMessageHeader,
1067 mem), 1057 mem),
1058 GNUNET_MQ_hd_fixed_size (group_part_ack,
1059 GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK,
1060 struct GNUNET_MessageHeader,
1061 grp),
1068 GNUNET_MQ_hd_fixed_size (group_replay_request, 1062 GNUNET_MQ_hd_fixed_size (group_replay_request,
1069 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 1063 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1070 struct MulticastReplayRequestMessage, 1064 struct MulticastReplayRequestMessage,
@@ -1198,16 +1192,19 @@ GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem,
1198 GNUNET_ContinuationCallback part_cb, 1192 GNUNET_ContinuationCallback part_cb,
1199 void *part_cls) 1193 void *part_cls)
1200{ 1194{
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Member parting.\n", mem);
1202 struct GNUNET_MULTICAST_Group *grp = &mem->grp; 1195 struct GNUNET_MULTICAST_Group *grp = &mem->grp;
1196 struct GNUNET_MQ_Envelope *env;
1203 1197
1204 mem->join_dcsn_cb = NULL; 1198 mem->join_dcsn_cb = NULL;
1205 grp->join_req_cb = NULL; 1199 grp->join_req_cb = NULL;
1206 grp->message_cb = NULL; 1200 grp->message_cb = NULL;
1207 grp->replay_msg_cb = NULL; 1201 grp->replay_msg_cb = NULL;
1208 grp->replay_frag_cb = NULL; 1202 grp->replay_frag_cb = NULL;
1209 1203 grp->is_disconnecting = GNUNET_YES;
1210 group_disconnect (grp, part_cb, part_cls); 1204 grp->disconnect_cb = part_cb;
1205 grp->disconnect_cls = part_cls;
1206 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST);
1207 GNUNET_MQ_send (grp->mq, env);
1211} 1208}
1212 1209
1213 1210
diff --git a/src/multicast/test_multicast_multipeer.c b/src/multicast/test_multicast_multipeer.c
index 0fb515f54..65c51c2e3 100644
--- a/src/multicast/test_multicast_multipeer.c
+++ b/src/multicast/test_multicast_multipeer.c
@@ -35,9 +35,10 @@
35 35
36#define PEERS_REQUESTED 12 36#define PEERS_REQUESTED 12
37 37
38struct multicast_peer 38struct MulticastPeerContext
39{ 39{
40 int peer; /* peer number */ 40 int peer; /* peer number */
41 struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
41 const struct GNUNET_PeerIdentity *id; 42 const struct GNUNET_PeerIdentity *id;
42 struct GNUNET_TESTBED_Operation *op; /* not yet in use */ 43 struct GNUNET_TESTBED_Operation *op; /* not yet in use */
43 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */ 44 struct GNUNET_TESTBED_Operation *pi_op; /* not yet in use */
@@ -61,7 +62,7 @@ static void service_connect (void *cls,
61 void *ca_result, 62 void *ca_result,
62 const char *emsg); 63 const char *emsg);
63 64
64static struct multicast_peer **mc_peers; 65static struct MulticastPeerContext **multicast_peers;
65static struct GNUNET_TESTBED_Peer **peers; 66static struct GNUNET_TESTBED_Peer **peers;
66 67
67// FIXME: refactor 68// FIXME: refactor
@@ -69,18 +70,14 @@ static struct GNUNET_TESTBED_Operation *op[PEERS_REQUESTED];
69static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED]; 70static struct GNUNET_TESTBED_Operation *pi_op[PEERS_REQUESTED];
70 71
71static struct GNUNET_MULTICAST_Origin *origin; 72static struct GNUNET_MULTICAST_Origin *origin;
72static struct GNUNET_MULTICAST_Member *member[PEERS_REQUESTED]; /* first element always empty */ 73static struct GNUNET_MULTICAST_Member *members[PEERS_REQUESTED]; /* first element always empty */
73 74
74static struct GNUNET_SCHEDULER_Task *timeout_tid; 75static struct GNUNET_SCHEDULER_Task *timeout_tid;
75 76
76static struct GNUNET_CRYPTO_EddsaPrivateKey group_key; 77//static struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
77static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key; 78static struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
78static struct GNUNET_HashCode group_pub_key_hash; 79static struct GNUNET_HashCode group_pub_key_hash;
79 80
80static struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key[PEERS_REQUESTED];
81static struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key[PEERS_REQUESTED];
82
83
84/** 81/**
85 * Global result for testcase. 82 * Global result for testcase.
86 */ 83 */
@@ -93,6 +90,8 @@ static int result;
93static void 90static void
94shutdown_task (void *cls) 91shutdown_task (void *cls)
95{ 92{
93 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
94 "shutdown_task!\n");
96 for (int i=0;i<PEERS_REQUESTED;i++) 95 for (int i=0;i<PEERS_REQUESTED;i++)
97 { 96 {
98 if (NULL != op[i]) 97 if (NULL != op[i])
@@ -107,14 +106,16 @@ shutdown_task (void *cls)
107 } 106 }
108 } 107 }
109 108
110 if (NULL != mc_peers) 109 if (NULL != multicast_peers)
111 { 110 {
112 for (int i=0; i < PEERS_REQUESTED; i++) 111 for (int i=0; i < PEERS_REQUESTED; i++)
113 { 112 {
114 GNUNET_free (mc_peers[i]); 113 GNUNET_free (multicast_peers[i]->key);
115 mc_peers[i] = NULL; 114 GNUNET_free (multicast_peers[i]);
115 multicast_peers[i] = NULL;
116 } 116 }
117 GNUNET_free (mc_peers); 117 GNUNET_free (multicast_peers);
118 multicast_peers = NULL;
118 } 119 }
119 120
120 if (NULL != timeout_tid) 121 if (NULL != timeout_tid)
@@ -141,11 +142,11 @@ member_join_request (void *cls,
141 const struct GNUNET_MessageHeader *join_msg, 142 const struct GNUNET_MessageHeader *join_msg,
142 struct GNUNET_MULTICAST_JoinHandle *jh) 143 struct GNUNET_MULTICAST_JoinHandle *jh)
143{ 144{
144 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 145 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
145 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 146 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
146 "Peer #%u (%s) sent a join request.\n", 147 "Peer #%u (%s) sent a join request.\n",
147 mc_peer->peer, 148 mc_peer->peer,
148 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 149 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
149} 150}
150 151
151 152
@@ -154,7 +155,7 @@ notify (void *cls,
154 size_t *data_size, 155 size_t *data_size,
155 void *data) 156 void *data)
156{ 157{
157 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 158 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
158 159
159 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg); 160 struct pingpong_msg *pp_msg = GNUNET_new (struct pingpong_msg);
160 pp_msg->peer = mc_peer->peer; 161 pp_msg->peer = mc_peer->peer;
@@ -178,18 +179,18 @@ member_join_decision (void *cls,
178 const struct GNUNET_PeerIdentity *relays, 179 const struct GNUNET_PeerIdentity *relays,
179 const struct GNUNET_MessageHeader *join_msg) 180 const struct GNUNET_MessageHeader *join_msg)
180{ 181{
181 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 182 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
182 struct GNUNET_MULTICAST_MemberTransmitHandle *req; 183 struct GNUNET_MULTICAST_MemberTransmitHandle *req;
183 184
184 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 185 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
185 "Peer #%u (%s) received a decision from origin: %s\n", 186 "Peer #%u (%s) received a decision from origin: %s\n",
186 mc_peer->peer, 187 mc_peer->peer,
187 GNUNET_i2s (mc_peers[mc_peer->peer]->id), 188 GNUNET_i2s (multicast_peers[mc_peer->peer]->id),
188 (GNUNET_YES == is_admitted)?"accepted":"rejected"); 189 (GNUNET_YES == is_admitted)?"accepted":"rejected");
189 190
190 if (GNUNET_YES == is_admitted) 191 if (GNUNET_YES == is_admitted)
191 { 192 {
192 req = GNUNET_MULTICAST_member_to_origin (member[mc_peer->peer], 193 req = GNUNET_MULTICAST_member_to_origin (members[mc_peer->peer],
193 0, 194 0,
194 notify, 195 notify,
195 cls); 196 cls);
@@ -215,10 +216,32 @@ member_replay_msg ()
215 216
216 217
217static void 218static void
219origin_disconnected_cb (void *cls)
220{
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Origin disconnected. Shutting down.\n");
223 result = GNUNET_YES;
224 GNUNET_SCHEDULER_shutdown ();
225}
226
227
228static void
229member_disconnected_cb (void *cls)
230{
231 for (int i = 1; i < PEERS_REQUESTED; ++i)
232 if (GNUNET_NO == multicast_peers[i]->test_ok)
233 return;
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
235 "All member disconnected. Stopping origin.\n");
236 GNUNET_MULTICAST_origin_stop (origin, origin_disconnected_cb, cls);
237}
238
239
240static void
218member_message (void *cls, 241member_message (void *cls,
219 const struct GNUNET_MULTICAST_MessageHeader *msg) 242 const struct GNUNET_MULTICAST_MessageHeader *msg)
220{ 243{
221 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 244 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
222 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]); 245 struct pingpong_msg *pp_msg = (struct pingpong_msg*) &(msg[1]);
223 246
224 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer) 247 if (PONG == pp_msg->msg && mc_peer->peer == pp_msg->peer)
@@ -226,18 +249,15 @@ member_message (void *cls,
226 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 249 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
227 "peer #%i (%s) receives a pong\n", 250 "peer #%i (%s) receives a pong\n",
228 mc_peer->peer, 251 mc_peer->peer,
229 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 252 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
230
231 mc_peer->test_ok = GNUNET_OK; 253 mc_peer->test_ok = GNUNET_OK;
232 } 254 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
233 255 "peer #%u (%s) parting from multicast group\n",
234 // Test for completeness of received PONGs 256 mc_peer->peer,
235 for (int i=1; i<PEERS_REQUESTED; i++) 257 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
236 if (GNUNET_NO == mc_peers[i]->test_ok)
237 return;
238 258
239 result = GNUNET_YES; 259 GNUNET_MULTICAST_member_part (members[mc_peer->peer], member_disconnected_cb, cls);
240 GNUNET_SCHEDULER_shutdown(); 260 }
241} 261}
242 262
243 263
@@ -349,81 +369,53 @@ origin_message (void *cls,
349 369
350 370
351static void 371static void
352multicast_da (void *cls, 372multicast_disconnect (void *cls,
353 void *op_result) 373 void *op_result)
354{ 374{
355 struct multicast_peer *mc_peer = (struct multicast_peer*)cls;
356 375
357 if (0 == mc_peer->peer)
358 {
359 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
360 "Origin closes multicast group\n");
361
362 GNUNET_MULTICAST_origin_stop (origin, NULL, cls);
363 }
364 else
365 {
366 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
367 "peer #%u (%s) parting from multicast group\n",
368 mc_peer->peer,
369 GNUNET_i2s (mc_peers[mc_peer->peer]->id));
370
371 GNUNET_MULTICAST_member_part (member[mc_peer->peer], NULL, cls);
372 }
373} 376}
374 377
375 378
376static void * 379static void *
377multicast_ca (void *cls, 380multicast_connect (void *cls,
378 const struct GNUNET_CONFIGURATION_Handle *cfg) 381 const struct GNUNET_CONFIGURATION_Handle *cfg)
379{ 382{
380 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 383 struct MulticastPeerContext *multicast_peer = cls;
381 struct GNUNET_MessageHeader *join_msg; 384 struct GNUNET_MessageHeader *join_msg;
382 char data[64]; 385 char data[64];
383 386
384 if (0 == mc_peer->peer) 387 multicast_peer->key = GNUNET_CRYPTO_ecdsa_key_create ();
388 if (0 == multicast_peer->peer)
385 { 389 {
386 struct GNUNET_CRYPTO_EddsaPrivateKey *key = GNUNET_CRYPTO_eddsa_key_create (); 390 GNUNET_CRYPTO_eddsa_key_get_public (multicast_peer->key, &group_pub_key);
387 GNUNET_CRYPTO_eddsa_key_get_public (key, &group_pub_key);
388 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash); 391 GNUNET_CRYPTO_hash (&group_pub_key, sizeof (group_pub_key), &group_pub_key_hash);
389
390 group_key = *key;
391
392 origin = GNUNET_MULTICAST_origin_start (cfg, 392 origin = GNUNET_MULTICAST_origin_start (cfg,
393 &group_key, 393 multicast_peer->key,
394 0, 394 0,
395 origin_join_request, 395 origin_join_request,
396 origin_replay_frag, 396 origin_replay_frag,
397 origin_replay_msg, 397 origin_replay_msg,
398 origin_request, 398 origin_request,
399 origin_message, 399 origin_message,
400 cls); 400 cls);
401 401 if (NULL == origin)
402 if (NULL == origin) { 402 {
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 403 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
404 "Peer #%u could not create a multicast group", 404 "Peer #%u could not create a multicast group",
405 mc_peer->peer); 405 multicast_peer->peer);
406 return NULL; 406 return NULL;
407 } 407 }
408
409 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 408 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
410 "Peer #%u connected as origin to group %s\n", 409 "Peer #%u connected as origin to group %s\n",
411 mc_peer->peer, 410 multicast_peer->peer,
412 GNUNET_h2s (&group_pub_key_hash)); 411 GNUNET_h2s (&group_pub_key_hash));
413
414 return origin; 412 return origin;
415 } 413 }
416 else 414 else
417 { 415 {
418 // Get members keys
419 member_pub_key[mc_peer->peer] = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
420 member_key[mc_peer->peer] = GNUNET_CRYPTO_ecdsa_key_create ();
421 GNUNET_CRYPTO_ecdsa_key_get_public (member_key[mc_peer->peer],
422 member_pub_key[mc_peer->peer]);
423
424 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?", 416 sprintf(data, "Hi, I am peer #%u (%s). Can I enter?",
425 mc_peer->peer, 417 multicast_peer->peer,
426 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 418 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id));
427 uint8_t data_size = strlen (data) + 1; 419 uint8_t data_size = strlen (data) + 1;
428 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size); 420 join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
429 join_msg->size = htons (sizeof (join_msg) + data_size); 421 join_msg->size = htons (sizeof (join_msg) + data_size);
@@ -432,24 +424,25 @@ multicast_ca (void *cls,
432 424
433 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 425 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
434 "Peer #%u (%s) tries to join multicast group %s\n", 426 "Peer #%u (%s) tries to join multicast group %s\n",
435 mc_peer->peer, 427 multicast_peer->peer,
436 GNUNET_i2s (mc_peers[mc_peer->peer]->id), 428 GNUNET_i2s (multicast_peers[multicast_peer->peer]->id),
437 GNUNET_h2s (&group_pub_key_hash)); 429 GNUNET_h2s (&group_pub_key_hash));
438 430
439 member[mc_peer->peer] = GNUNET_MULTICAST_member_join (cfg, 431 members[multicast_peer->peer] =
440 &group_pub_key, 432 GNUNET_MULTICAST_member_join (cfg,
441 member_key[mc_peer->peer], 433 &group_pub_key,
442 mc_peers[0]->id, 434 multicast_peer->key,
443 0, 435 multicast_peers[0]->id,
444 NULL, 436 0,
445 join_msg, /* join message */ 437 NULL,
446 member_join_request, 438 join_msg, /* join message */
447 member_join_decision, 439 member_join_request,
448 member_replay_frag, 440 member_join_decision,
449 member_replay_msg, 441 member_replay_frag,
450 member_message, 442 member_replay_msg,
451 cls); 443 member_message,
452 return member[mc_peer->peer]; 444 cls);
445 return members[multicast_peer->peer];
453 } 446 }
454} 447}
455 448
@@ -460,7 +453,7 @@ peer_information_cb (void *cls,
460 const struct GNUNET_TESTBED_PeerInformation *pinfo, 453 const struct GNUNET_TESTBED_PeerInformation *pinfo,
461 const char *emsg) 454 const char *emsg)
462{ 455{
463 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 456 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
464 457
465 if (NULL == pinfo) { 458 if (NULL == pinfo) {
466 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n"); 459 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got no peer information\n");
@@ -468,7 +461,7 @@ peer_information_cb (void *cls,
468 GNUNET_SCHEDULER_shutdown (); 461 GNUNET_SCHEDULER_shutdown ();
469 } 462 }
470 463
471 mc_peers[mc_peer->peer]->id = pinfo->result.id; 464 multicast_peers[mc_peer->peer]->id = pinfo->result.id;
472 465
473 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 466 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
474 "Got peer information of %s (%s)\n", 467 "Got peer information of %s (%s)\n",
@@ -478,22 +471,28 @@ peer_information_cb (void *cls,
478 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 471 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
479 "Create peer #%u (%s)\n", 472 "Create peer #%u (%s)\n",
480 mc_peer->peer, 473 mc_peer->peer,
481 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 474 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
482 475
483 if (0 != mc_peer->peer) 476 if (0 != mc_peer->peer)
484 { 477 {
485 /* connect to multicast service of members */ 478 /* connect to multicast service of members */
486 op[mc_peer->peer] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ 479 op[mc_peer->peer] =
487 peers[mc_peer->peer], /* The peer whose service to connect to */ 480 GNUNET_TESTBED_service_connect (/* Closure for operation */
488 "multicast", /* The name of the service */ 481 NULL,
489 service_connect, /* callback to call after a handle to service 482 /* The peer whose service to connect to */
490 is opened */ 483 peers[mc_peer->peer],
491 cls, /* closure for the above callback */ 484 /* The name of the service */
492 multicast_ca, /* callback to call with peer's configuration; 485 "multicast",
493 this should open the needed service connection */ 486 /* called after a handle to service is opened */
494 multicast_da, /* callback to be called when closing the 487 service_connect,
495 opened service connection */ 488 /* closure for the above callback */
496 cls); /* closure for the above two callbacks */ 489 cls,
490 /* called when opening the service connection */
491 multicast_connect,
492 /* called when closing the service connection */
493 multicast_disconnect,
494 /* closure for the above two callbacks */
495 cls);
497 } 496 }
498} 497}
499 498
@@ -504,14 +503,14 @@ service_connect (void *cls,
504 void *ca_result, 503 void *ca_result,
505 const char *emsg) 504 const char *emsg)
506{ 505{
507 struct multicast_peer *mc_peer = (struct multicast_peer*)cls; 506 struct MulticastPeerContext *mc_peer = (struct MulticastPeerContext*)cls;
508 507
509 if (NULL == ca_result) 508 if (NULL == ca_result)
510 { 509 {
511 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 510 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
512 "Connection adapter not created for peer #%u (%s)\n", 511 "Connection adapter not created for peer #%u (%s)\n",
513 mc_peer->peer, 512 mc_peer->peer,
514 GNUNET_i2s (mc_peers[mc_peer->peer]->id)); 513 GNUNET_i2s (multicast_peers[mc_peer->peer]->id));
515 514
516 result = GNUNET_SYSERR; 515 result = GNUNET_SYSERR;
517 GNUNET_SCHEDULER_shutdown(); 516 GNUNET_SCHEDULER_shutdown();
@@ -525,7 +524,7 @@ service_connect (void *cls,
525 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i], 524 pi_op[i] = GNUNET_TESTBED_peer_get_information (peers[i],
526 GNUNET_TESTBED_PIT_IDENTITY, 525 GNUNET_TESTBED_PIT_IDENTITY,
527 peer_information_cb, 526 peer_information_cb,
528 mc_peers[i]); 527 multicast_peers[i]);
529 } 528 }
530 } 529 }
531} 530}
@@ -550,50 +549,51 @@ service_connect (void *cls,
550 */ 549 */
551static void 550static void
552testbed_master (void *cls, 551testbed_master (void *cls,
553 struct GNUNET_TESTBED_RunHandle *h, 552 struct GNUNET_TESTBED_RunHandle *h,
554 unsigned int num_peers, 553 unsigned int num_peers,
555 struct GNUNET_TESTBED_Peer **p, 554 struct GNUNET_TESTBED_Peer **p,
556 unsigned int links_succeeded, 555 unsigned int links_succeeded,
557 unsigned int links_failed) 556 unsigned int links_failed)
558{ 557{
559 /* Testbed is ready with peers running and connected in a pre-defined overlay 558 /* Testbed is ready with peers running and connected in a pre-defined overlay
560 topology (FIXME) */ 559 topology (FIXME) */
561
562 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
563 "Connected to testbed_master()\n");
564
565 peers = p; 560 peers = p;
566 561 multicast_peers = GNUNET_new_array (PEERS_REQUESTED, struct MulticastPeerContext*);
567 mc_peers = GNUNET_new_array (PEERS_REQUESTED, struct multicast_peer*);
568 562
569 // Create test contexts for members 563 // Create test contexts for members
570 for (int i = 0; i<PEERS_REQUESTED; i++) 564 for (int i = 0; i<PEERS_REQUESTED; i++)
571 { 565 {
572 mc_peers[i] = GNUNET_new (struct multicast_peer); 566 multicast_peers[i] = GNUNET_new (struct MulticastPeerContext);
573 mc_peers[i]->peer = i; 567 multicast_peers[i]->peer = i;
574 mc_peers[i]->test_ok = GNUNET_NO; 568 multicast_peers[i]->test_ok = GNUNET_NO;
575 } 569 }
576
577 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 570 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
578 "Create origin peer\n"); 571 "Create origin peer\n");
579 572 op[0] =
580 op[0] = GNUNET_TESTBED_service_connect (NULL, /* Closure for operation */ 573 GNUNET_TESTBED_service_connect (/* Closure for operation */
581 peers[0], /* The peer whose service to connect to */ 574 NULL,
582 "multicast", /* The name of the service */ 575 /* The peer whose service to connect to */
583 service_connect, /* callback to call after a handle to service 576 peers[0],
584 is opened */ 577 /* The name of the service */
585 mc_peers[0], /* closure for the above callback */ 578 "multicast",
586 multicast_ca, /* callback to call with peer's configuration; 579 /* called after a handle to service is opened */
587 this should open the needed service connection */ 580 service_connect,
588 multicast_da, /* callback to be called when closing the 581 /* closure for the above callback */
589 opened service connection */ 582 multicast_peers[0],
590 mc_peers[0]); /* closure for the above two callbacks */ 583 /* called when opening the service connection */
591 584 multicast_connect,
592 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */ 585 /* called when closing the service connection */
593 586 multicast_disconnect,
587 /* closure for the above two callbacks */
588 multicast_peers[0]);
589 /* Schedule a new task on shutdown */
590 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
594 /* Schedule the shutdown task with a delay of a few Seconds */ 591 /* Schedule the shutdown task with a delay of a few Seconds */
595 timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 400), 592 timeout_tid =
596 &timeout_task, NULL); 593 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
594 (GNUNET_TIME_UNIT_SECONDS, 400),
595 &timeout_task,
596 NULL);
597} 597}
598 598
599 599
@@ -617,15 +617,21 @@ main (int argc, char *argv[])
617 } 617 }
618 618
619 result = GNUNET_SYSERR; 619 result = GNUNET_SYSERR;
620 ret = GNUNET_TESTBED_test_run 620 ret =
621 ("test-multicast-multipeer", /* test case name */ 621 GNUNET_TESTBED_test_run ("test-multicast-multipeer",
622 config_file, /* template configuration */ 622 config_file,
623 PEERS_REQUESTED, /* number of peers to start */ 623 /* number of peers to start */
624 0LL, /* Event mask - set to 0 for no event notifications */ 624 PEERS_REQUESTED,
625 NULL, /* Controller event callback */ 625 /* Event mask - set to 0 for no event notifications */
626 NULL, /* Closure for controller event callback */ 626 0LL,
627 testbed_master, /* continuation callback to be called when testbed setup is complete */ 627 /* Controller event callback */
628 NULL); /* Closure for the test_master callback */ 628 NULL,
629 /* Closure for controller event callback */
630 NULL,
631 /* called when testbed setup is complete */
632 testbed_master,
633 /* Closure for the test_master callback */
634 NULL);
629 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) 635 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
630 return 1; 636 return 1;
631 return 0; 637 return 0;