aboutsummaryrefslogtreecommitdiff
path: root/src/multicast
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2014-05-17 10:16:15 +0000
committerGabor X Toth <*@tg-x.net>2014-05-17 10:16:15 +0000
commit83c058a5ea11b6d7aa05cb71963c6063cb373603 (patch)
tree30921098e391d492cf52311983348232d41d9634 /src/multicast
parentd78b7d8a3f6cdaee244557667350da443ca76db5 (diff)
downloadgnunet-83c058a5ea11b6d7aa05cb71963c6063cb373603.tar.gz
gnunet-83c058a5ea11b6d7aa05cb71963c6063cb373603.zip
multicast, psyc: client connections, join requests
Diffstat (limited to 'src/multicast')
-rw-r--r--src/multicast/gnunet-service-multicast.c399
-rw-r--r--src/multicast/multicast.h8
-rw-r--r--src/multicast/multicast_api.c99
3 files changed, 393 insertions, 113 deletions
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c
index 0265660e1..0394ee19e 100644
--- a/src/multicast/gnunet-service-multicast.c
+++ b/src/multicast/gnunet-service-multicast.c
@@ -46,22 +46,40 @@ static struct GNUNET_SERVER_NotificationContext *nc;
46 46
47/** 47/**
48 * All connected origins. 48 * All connected origins.
49 * Group's pub_key_hash -> struct Group 49 * Group's pub_key_hash -> struct Origin
50 */ 50 */
51static struct GNUNET_CONTAINER_MultiHashMap *origins; 51static struct GNUNET_CONTAINER_MultiHashMap *origins;
52 52
53/** 53/**
54 * All connected members. 54 * All connected members.
55 * Group's pub_key_hash -> struct Group 55 * Group's pub_key_hash -> struct Member
56 */ 56 */
57static struct GNUNET_CONTAINER_MultiHashMap *members; 57static struct GNUNET_CONTAINER_MultiHashMap *members;
58 58
59/** 59/**
60 * Connected members per group.
61 * Group's pub_key_hash -> Member's pub_key -> struct Member
62 */
63static struct GNUNET_CONTAINER_MultiHashMap *group_members;
64
65
66/**
67 * List of connected clients.
68 */
69struct ClientList
70{
71 struct ClientList *prev;
72 struct ClientList *next;
73 struct GNUNET_SERVER_Client *client;
74};
75
76/**
60 * Common part of the client context for both an origin and member. 77 * Common part of the client context for both an origin and member.
61 */ 78 */
62struct Group 79struct Group
63{ 80{
64 struct GNUNET_SERVER_Client *client; 81 struct ClientList *clients_head;
82 struct ClientList *clients_tail;
65 83
66 /** 84 /**
67 * Public key of the group. 85 * Public key of the group.
@@ -117,6 +135,29 @@ struct Member
117 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; 135 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
118 136
119 /** 137 /**
138 * Public key of the member.
139 */
140 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
141
142 /**
143 * Hash of @a pub_key.
144 */
145 struct GNUNET_HashCode pub_key_hash;
146
147 /**
148 * Join request sent to the origin / members.
149 */
150 struct GNUNET_MULTICAST_JoinRequest *join_request;
151
152 /**
153 * Join decision sent in reply to our request.
154 *
155 * Only a positive decision is stored here, in case of a negative decision the
156 * client is disconnected.
157 */
158 struct MulticastJoinDecisionMessage *join_decision;
159
160 /**
120 * Last request fragment ID sent to the origin. 161 * Last request fragment ID sent to the origin.
121 */ 162 */
122 uint64_t max_fragment_id; 163 uint64_t max_fragment_id;
@@ -135,23 +176,161 @@ cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
135 /* FIXME: do clean up here */ 176 /* FIXME: do clean up here */
136} 177}
137 178
179/**
180 * Clean up origin data structures after a client disconnected.
181 */
182static void
183cleanup_origin (struct Origin *orig)
184{
185 struct Group *grp = &orig->grp;
186 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
187}
188
189
190/**
191 * Clean up member data structures after a client disconnected.
192 */
193static void
194cleanup_member (struct Member *mem)
195{
196 struct Group *grp = &mem->grp;
197 struct GNUNET_CONTAINER_MultiHashMap *
198 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
199 &grp->pub_key_hash);
200 GNUNET_assert (NULL != grp_mem);
201 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
202
203 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
204 {
205 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
206 grp_mem);
207 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
208 }
209 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
210}
211
212
213/**
214 * Clean up group data structures after a client disconnected.
215 */
216static void
217cleanup_group (struct Group *grp)
218{
219 (GNUNET_YES == grp->is_origin)
220 ? cleanup_origin ((struct Origin *) grp)
221 : cleanup_member ((struct Member *) grp);
222
223 GNUNET_free (grp);
224}
225
226
227/**
228 * Called whenever a client is disconnected.
229 *
230 * Frees our resources associated with that client.
231 *
232 * @param cls Closure.
233 * @param client Client handle.
234 */
235static void
236client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
237{
238 if (NULL == client)
239 return;
240
241 struct Group *grp
242 = GNUNET_SERVER_client_get_user_context (client, struct Group);
243
244 if (NULL == grp)
245 {
246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
247 "%p User context is NULL in client_disconnect()\n", grp);
248 GNUNET_assert (0);
249 return;
250 }
251
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "%p Client (%s) disconnected from group %s\n",
254 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
255 GNUNET_h2s (&grp->pub_key_hash));
256
257 struct ClientList *cl = grp->clients_head;
258 while (NULL != cl)
259 {
260 if (cl->client == client)
261 {
262 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
263 GNUNET_free (cl);
264 break;
265 }
266 cl = cl->next;
267 }
268
269 if (NULL == grp->clients_head)
270 { /* Last client disconnected. */
271#if FIXME
272 if (NULL != grp->tmit_head)
273 { /* Send pending messages via CADET before cleanup. */
274 transmit_message (grp);
275 }
276 else
277#endif
278 {
279 cleanup_group (grp);
280 }
281 }
282}
283
138 284
139/** 285/**
140 * Iterator callback for sending a message to clients. 286 * Send message to all clients connected to the group.
287 */
288static void
289message_to_clients (const struct Group *grp,
290 const struct GNUNET_MessageHeader *msg)
291{
292 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
293 "%p Sending message to clients.\n", grp);
294
295 struct ClientList *cl = grp->clients_head;
296 while (NULL != cl)
297 {
298 GNUNET_SERVER_notification_context_add (nc, cl->client);
299 GNUNET_SERVER_notification_context_unicast (nc, cl->client, msg, GNUNET_NO);
300 cl = cl->next;
301 }
302}
303
304
305/**
306 * Iterator callback for sending a message to origin clients.
141 */ 307 */
142static int 308static int
143message_callback (void *cls, const struct GNUNET_HashCode *pub_key_hash, 309origin_message_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
144 void *group) 310 void *origin)
145{ 311{
146 const struct GNUNET_MessageHeader *msg = cls; 312 const struct GNUNET_MessageHeader *msg = cls;
147 struct Group *grp = group; 313 struct Member *orig = origin;
148 314
149 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 315 message_to_clients (&orig->grp, msg);
150 "%p Sending message to client.\n", grp); 316 return GNUNET_YES;
317}
151 318
152 GNUNET_SERVER_notification_context_add (nc, grp->client);
153 GNUNET_SERVER_notification_context_unicast (nc, grp->client, msg, GNUNET_NO);
154 319
320/**
321 * Iterator callback for sending a message to member clients.
322 */
323static int
324member_message_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
325 void *member)
326{
327 const struct GNUNET_MessageHeader *msg = cls;
328 struct Member *mem = member;
329
330 if (NULL != mem->join_decision)
331 { /* Only send message to admitted members */
332 message_to_clients (&mem->grp, msg);
333 }
155 return GNUNET_YES; 334 return GNUNET_YES;
156} 335}
157 336
@@ -167,10 +346,10 @@ message_to_group (struct Group *grp, const struct GNUNET_MessageHeader *msg)
167{ 346{
168 if (origins != NULL) 347 if (origins != NULL)
169 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash, 348 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
170 message_callback, (void *) msg); 349 origin_message_cb, (void *) msg);
171 if (members != NULL) 350 if (members != NULL)
172 GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash, 351 GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
173 message_callback, (void *) msg); 352 member_message_cb, (void *) msg);
174} 353}
175 354
176 355
@@ -185,7 +364,7 @@ message_to_origin (struct Group *grp, const struct GNUNET_MessageHeader *msg)
185{ 364{
186 if (origins != NULL) 365 if (origins != NULL)
187 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash, 366 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
188 message_callback, (void *) msg); 367 origin_message_cb, (void *) msg);
189} 368}
190 369
191 370
@@ -199,38 +378,47 @@ handle_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
199 const struct MulticastOriginStartMessage * 378 const struct MulticastOriginStartMessage *
200 msg = (const struct MulticastOriginStartMessage *) m; 379 msg = (const struct MulticastOriginStartMessage *) m;
201 380
202 struct Origin *orig = GNUNET_new (struct Origin); 381 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
203 orig->priv_key = msg->group_key; 382 struct GNUNET_HashCode pub_key_hash;
204 383
205 struct Group *grp = &orig->grp; 384 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
206 grp->is_origin = GNUNET_YES; 385 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
207 grp->client = client; 386
387 struct Origin *
388 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
389 struct Group *grp;
390
391 if (NULL == orig)
392 {
393 orig = GNUNET_new (struct Origin);
394 orig->priv_key = msg->group_key;
395 grp = &orig->grp;
396 grp->is_origin = GNUNET_YES;
397 grp->pub_key = pub_key;
398 grp->pub_key_hash = pub_key_hash;
399
400 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
401 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
402 }
403 else
404 {
405 grp = &orig->grp;
406 }
208 407
209 GNUNET_CRYPTO_eddsa_key_get_public (&orig->priv_key, &grp->pub_key); 408 struct ClientList *cl = GNUNET_new (struct ClientList);
210 GNUNET_CRYPTO_hash (&grp->pub_key, sizeof (grp->pub_key), &grp->pub_key_hash); 409 cl->client = client;
410 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
211 411
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "%p Client connected as origin to group %s.\n", 413 "%p Client connected as origin to group %s.\n",
214 orig, GNUNET_h2s (&grp->pub_key_hash)); 414 orig, GNUNET_h2s (&grp->pub_key_hash));
215 415
216 GNUNET_SERVER_client_set_user_context (client, grp); 416 GNUNET_SERVER_client_set_user_context (client, grp);
217 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
218 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
219 GNUNET_SERVER_receive_done (client, GNUNET_OK); 417 GNUNET_SERVER_receive_done (client, GNUNET_OK);
220} 418}
221 419
222 420
223/** 421/**
224 * Handle a client stopping an origin.
225 */
226static void
227handle_origin_stop (void *cls, struct GNUNET_SERVER_Client *client,
228 const struct GNUNET_MessageHeader *msg)
229{
230}
231
232
233/**
234 * Handle a connecting client joining a group. 422 * Handle a connecting client joining a group.
235 */ 423 */
236static void 424static void
@@ -240,34 +428,113 @@ handle_member_join (void *cls, struct GNUNET_SERVER_Client *client,
240 struct MulticastMemberJoinMessage * 428 struct MulticastMemberJoinMessage *
241 msg = (struct MulticastMemberJoinMessage *) m; 429 msg = (struct MulticastMemberJoinMessage *) m;
242 430
243 struct Member *mem = GNUNET_new (struct Member); 431 struct GNUNET_CRYPTO_EddsaPublicKey mem_pub_key;
244 mem->priv_key = msg->member_key; 432 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
245 433
246 struct Group *grp = &mem->grp; 434 GNUNET_CRYPTO_eddsa_key_get_public (&msg->member_key, &mem_pub_key);
247 grp->is_origin = GNUNET_NO; 435 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
248 grp->client = client; 436 GNUNET_CRYPTO_hash (&msg->group_key, sizeof (msg->group_key), &pub_key_hash);
249 grp->pub_key = msg->group_key; 437
250 GNUNET_CRYPTO_hash (&grp->pub_key, sizeof (grp->pub_key), &grp->pub_key_hash); 438 struct GNUNET_CONTAINER_MultiHashMap *
439 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
440 struct Member *mem = NULL;
441 struct Group *grp;
442
443 if (NULL == grp_mem)
444 {
445 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
446 GNUNET_CONTAINER_multihashmap_put (group_members, &pub_key_hash, grp_mem,
447 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
448 }
449 else
450 {
451 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
452 }
453
454 if (NULL == mem)
455 {
456 mem = GNUNET_new (struct Member);
457 mem->priv_key = msg->member_key;
458 mem->pub_key = mem_pub_key;
459 mem->pub_key_hash = mem_pub_key_hash;
460
461 grp = &mem->grp;
462 grp->is_origin = GNUNET_NO;
463 grp->pub_key = msg->group_key;
464 grp->pub_key_hash = pub_key_hash;
465
466 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem_pub_key_hash, mem,
467 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
468 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
469 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
470 }
471 else
472 {
473 grp = &mem->grp;
474 }
475
476 struct ClientList *cl = GNUNET_new (struct ClientList);
477 cl->client = client;
478 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
251 479
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "%p Client connected as member to group %s.\n", 481 "%p Client connected as member to group %s.\n",
254 mem, GNUNET_h2s (&grp->pub_key_hash)); 482 mem, GNUNET_h2s (&grp->pub_key_hash));
255 483
256 GNUNET_SERVER_client_set_user_context (client, grp); 484 GNUNET_SERVER_client_set_user_context (client, grp);
257 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
258 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
259 GNUNET_SERVER_receive_done (client, GNUNET_OK);
260}
261
262
263/**
264 * Handle a client parting a group.
265 */
266static void
267handle_member_part (void *cls, struct GNUNET_SERVER_Client *client,
268 const struct GNUNET_MessageHeader *msg)
269{
270 485
486 if (NULL != mem->join_decision)
487 { /* Already got a join decision, send it to client. */
488 GNUNET_SERVER_notification_context_add (nc, client);
489 GNUNET_SERVER_notification_context_unicast (nc, client,
490 (struct GNUNET_MessageHeader *)
491 mem->join_decision,
492 GNUNET_NO);
493 }
494 else if (grp->clients_head == grp->clients_tail)
495 { /* First client, send join request. */
496 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
497 uint32_t relay_count = ntohs (msg->relay_count);
498 struct GNUNET_MessageHeader *
499 join_req = ((struct GNUNET_MessageHeader *)
500 ((char *) &msg[1]) + relay_count * sizeof (*relays));
501 uint16_t join_req_size = ntohs (join_req->size);
502
503 struct MulticastJoinRequestMessage *
504 req = GNUNET_malloc (sizeof (*req) + join_req_size);
505 req->header.size = htons (sizeof (*req) + join_req_size);
506 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
507 req->group_key = grp->pub_key;
508 GNUNET_CRYPTO_eddsa_key_get_public (&mem->priv_key, &req->member_key);
509 memcpy (&req[1], join_req, join_req_size);
510
511 req->purpose.size = htonl (sizeof (*req) + join_req_size
512 - sizeof (req->header)
513 - sizeof (req->signature));
514 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
515
516 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->priv_key, &req->purpose,
517 &req->signature))
518 {
519 /* FIXME: handle error */
520 GNUNET_assert (0);
521 }
522
523 if (NULL != mem->join_request)
524 GNUNET_free (mem->join_request);
525 mem->join_request = req;
526
527 if (GNUNET_YES
528 == GNUNET_CONTAINER_multihashmap_contains (origins, &grp->pub_key_hash))
529 { /* Local origin */
530 message_to_origin (grp, (struct GNUNET_MessageHeader *) mem->join_request);
531 }
532 else
533 {
534 /* FIXME: send join request to remote origin / members */
535 }
536 }
537 GNUNET_SERVER_receive_done (client, GNUNET_OK);
271} 538}
272 539
273 540
@@ -296,7 +563,7 @@ handle_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
296 &msg->signature)) 563 &msg->signature))
297 { 564 {
298 /* FIXME: handle error */ 565 /* FIXME: handle error */
299 return; 566 GNUNET_assert (0);
300 } 567 }
301 568
302 /* FIXME: send to remote members */ 569 /* FIXME: send to remote members */
@@ -327,18 +594,24 @@ handle_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
327 - sizeof (req->header) 594 - sizeof (req->header)
328 - sizeof (req->member_key) 595 - sizeof (req->member_key)
329 - sizeof (req->signature)); 596 - sizeof (req->signature));
330 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE); 597 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
331 598
332 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->priv_key, &req->purpose, 599 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->priv_key, &req->purpose,
333 &req->signature)) 600 &req->signature))
334 { 601 {
335 /* FIXME: handle error */ 602 /* FIXME: handle error */
336 return; 603 GNUNET_assert (0);
337 } 604 }
338 605
339 /* FIXME: send to remote origin */ 606 if (GNUNET_YES
340 607 == GNUNET_CONTAINER_multihashmap_contains (origins, &grp->pub_key_hash))
341 message_to_origin (grp, m); 608 { /* Local origin */
609 message_to_origin (grp, m);
610 }
611 else
612 {
613 /* FIXME: send to remote origin */
614 }
342 GNUNET_SERVER_receive_done (client, GNUNET_OK); 615 GNUNET_SERVER_receive_done (client, GNUNET_OK);
343} 616}
344 617
@@ -357,15 +630,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
357 { &handle_origin_start, NULL, 630 { &handle_origin_start, NULL,
358 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 }, 631 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
359 632
360 { &handle_origin_stop, NULL,
361 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_STOP, 0 },
362
363 { &handle_member_join, NULL, 633 { &handle_member_join, NULL,
364 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 }, 634 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
365 635
366 { &handle_member_part, NULL,
367 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_PART, 0 },
368
369 { &handle_multicast_message, NULL, 636 { &handle_multicast_message, NULL,
370 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, 637 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
371 638
@@ -379,9 +646,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
379 stats = GNUNET_STATISTICS_create ("multicast", cfg); 646 stats = GNUNET_STATISTICS_create ("multicast", cfg);
380 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 647 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
381 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 648 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
649 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
382 nc = GNUNET_SERVER_notification_context_create (server, 1); 650 nc = GNUNET_SERVER_notification_context_create (server, 1);
383 651
384 GNUNET_SERVER_add_handlers (server, handlers); 652 GNUNET_SERVER_add_handlers (server, handlers);
653 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
385 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, 654 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
386 NULL); 655 NULL);
387} 656}
diff --git a/src/multicast/multicast.h b/src/multicast/multicast.h
index daa79e260..5b0fc647c 100644
--- a/src/multicast/multicast.h
+++ b/src/multicast/multicast.h
@@ -33,7 +33,7 @@ GNUNET_NETWORK_STRUCT_BEGIN
33/** 33/**
34 * Header of a join request sent to the origin or another member. 34 * Header of a join request sent to the origin or another member.
35 */ 35 */
36struct GNUNET_MULTICAST_JoinRequest 36struct MulticastJoinRequestMessage
37{ 37{
38 /** 38 /**
39 * Header for the join request. 39 * Header for the join request.
@@ -67,7 +67,7 @@ struct GNUNET_MULTICAST_JoinRequest
67 */ 67 */
68 struct GNUNET_PeerIdentity member_peer; 68 struct GNUNET_PeerIdentity member_peer;
69 69
70 /* Followed by request body. */ 70 /* Followed by struct GNUNET_MessageHeader join_request */
71}; 71};
72 72
73 73
@@ -97,9 +97,9 @@ struct MulticastJoinDecisionMessage
97 */ 97 */
98 uint32_t relay_count; 98 uint32_t relay_count;
99 99
100 /* followed by 'relay_count' peer identities */ 100 /* Followed by relay_count peer identities */
101 101
102 /* followed by the join response message */ 102 /* Followed by the join response message */
103 103
104}; 104};
105 105
diff --git a/src/multicast/multicast_api.c b/src/multicast/multicast_api.c
index d42f438ae..84dac0545 100644
--- a/src/multicast/multicast_api.c
+++ b/src/multicast/multicast_api.c
@@ -196,6 +196,17 @@ struct GNUNET_MULTICAST_Member
196 */ 196 */
197struct GNUNET_MULTICAST_JoinHandle 197struct GNUNET_MULTICAST_JoinHandle
198{ 198{
199 struct GNUNET_MULTICAST_Group *group;
200
201 /**
202 * Public key of the joining member.
203 */
204 struct GNUNET_CRYPTO_EddsaPublicKey member_key;
205
206 /**
207 * Peer identity of the joining member.
208 */
209 struct GNUNET_PeerIdentity member_peer;
199}; 210};
200 211
201 212
@@ -437,8 +448,7 @@ disconnect (void *g)
437 * Iterator callback for calling message callbacks for all groups. 448 * Iterator callback for calling message callbacks for all groups.
438 */ 449 */
439static int 450static int
440message_callback (void *cls, const struct GNUNET_HashCode *pub_key_hash, 451message_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, void *group)
441 void *group)
442{ 452{
443 const struct GNUNET_MessageHeader *msg = cls; 453 const struct GNUNET_MessageHeader *msg = cls;
444 struct GNUNET_MULTICAST_Group *grp = group; 454 struct GNUNET_MULTICAST_Group *grp = group;
@@ -456,32 +466,10 @@ message_callback (void *cls, const struct GNUNET_HashCode *pub_key_hash,
456 466
457 467
458/** 468/**
459 * Handle a multicast message from the service.
460 *
461 * Call message callbacks of all origins and members of the destination group.
462 *
463 * @param grp Destination group of the message.
464 * @param msg The message.
465 */
466static void
467handle_multicast_message (struct GNUNET_MULTICAST_Group *grp,
468 const struct GNUNET_MULTICAST_MessageHeader *msg)
469{
470 if (origins != NULL)
471 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
472 message_callback, (void *) msg);
473 if (members != NULL)
474 GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
475 message_callback, (void *) msg);
476}
477
478
479/**
480 * Iterator callback for calling request callbacks of origins. 469 * Iterator callback for calling request callbacks of origins.
481 */ 470 */
482static int 471static int
483request_callback (void *cls, const struct GNUNET_HashCode *chan_key_hash, 472request_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash, void *origin)
484 void *origin)
485{ 473{
486 const struct GNUNET_MULTICAST_RequestHeader *req = cls; 474 const struct GNUNET_MULTICAST_RequestHeader *req = cls;
487 struct GNUNET_MULTICAST_Origin *orig = origin; 475 struct GNUNET_MULTICAST_Origin *orig = origin;
@@ -497,20 +485,26 @@ request_callback (void *cls, const struct GNUNET_HashCode *chan_key_hash,
497 485
498 486
499/** 487/**
500 * Handle a multicast request from the service. 488 * Iterator callback for calling join request callbacks of origins.
501 *
502 * Call request callbacks of all origins of the destination group.
503 *
504 * @param grp Destination group of the message.
505 * @param msg The message.
506 */ 489 */
507static void 490static int
508handle_multicast_request (struct GNUNET_MULTICAST_Group *grp, 491join_request_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
509 const struct GNUNET_MULTICAST_RequestHeader *req) 492 void *group)
510{ 493{
511 if (NULL != origins) 494 const struct MulticastJoinRequestMessage *req = cls;
512 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash, 495 struct GNUNET_MULTICAST_Group *grp = group;
513 request_callback, (void *) req); 496
497 struct GNUNET_MULTICAST_JoinHandle *jh = GNUNET_malloc (sizeof (*jh));
498 jh->group = grp;
499 jh->member_key = req->member_key;
500 jh->member_peer = req->member_peer;
501
502 const struct GNUNET_MessageHeader *msg = NULL;
503 if (sizeof (*req) + sizeof (*msg) <= ntohs (req->header.size))
504 msg =(const struct GNUNET_MessageHeader *) &req[1];
505
506 grp->join_cb (grp->cb_cls, &req->member_key, msg, jh);
507 return GNUNET_YES;
514} 508}
515 509
516 510
@@ -551,22 +545,31 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
551 size_min = sizeof (struct GNUNET_MULTICAST_RequestHeader); 545 size_min = sizeof (struct GNUNET_MULTICAST_RequestHeader);
552 break; 546 break;
553 547
548 case GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST:
549 size_min = sizeof (struct MulticastJoinRequestMessage);
550 break;
551
554 default: 552 default:
555 GNUNET_break_op (0); 553 GNUNET_break_op (0);
556 return; 554 type = 0;
557 } 555 }
558 556
559 if (! ((0 < size_eq && size == size_eq) 557 if (! ((0 < size_eq && size == size_eq)
560 || (0 < size_min && size_min <= size))) 558 || (0 < size_min && size_min <= size)))
561 { 559 {
562 GNUNET_break_op (0); 560 GNUNET_break_op (0);
563 return; 561 type = 0;
564 } 562 }
565 563
566 switch (type) 564 switch (type)
567 { 565 {
568 case GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE: 566 case GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE:
569 handle_multicast_message (grp, (struct GNUNET_MULTICAST_MessageHeader *) msg); 567 if (origins != NULL)
568 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
569 message_cb, (void *) msg);
570 if (members != NULL)
571 GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
572 message_cb, (void *) msg);
570 break; 573 break;
571 574
572 case GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST: 575 case GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST:
@@ -576,12 +579,19 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
576 break; 579 break;
577 } 580 }
578 581
579 handle_multicast_request (grp, (struct GNUNET_MULTICAST_RequestHeader *) msg); 582 if (NULL != origins)
583 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
584 request_cb, (void *) msg);
580 break; 585 break;
581 586
582 default: 587 case GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST:
583 GNUNET_break_op (0); 588 if (NULL != origins)
584 return; 589 GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
590 join_request_cb, (void *) msg);
591 if (NULL != members)
592 GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
593 join_request_cb, (void *) msg);
594 break;
585 } 595 }
586 596
587 if (NULL != grp->client) 597 if (NULL != grp->client)
@@ -621,6 +631,7 @@ GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *jh,
621 const struct GNUNET_PeerIdentity *relays, 631 const struct GNUNET_PeerIdentity *relays,
622 const struct GNUNET_MessageHeader *join_response) 632 const struct GNUNET_MessageHeader *join_response)
623{ 633{
634 GNUNET_free (jh);
624 return NULL; 635 return NULL;
625} 636}
626 637