aboutsummaryrefslogtreecommitdiff
path: root/src/social
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2014-07-23 16:19:49 +0000
committerGabor X Toth <*@tg-x.net>2014-07-23 16:19:49 +0000
commit3cf8ba0b60f8495892fa76635e9c23555d0a304c (patch)
tree5f27648bdb3cf3409628e4e5edc26f811cbd03a5 /src/social
parent252b5599987b7ba03b879a8c2d1c455ad4c9834a (diff)
downloadgnunet-3cf8ba0b60f8495892fa76635e9c23555d0a304c.tar.gz
gnunet-3cf8ba0b60f8495892fa76635e9c23555d0a304c.zip
social: implement enter/leave/messaging; psyc: improvements and fixes
- social: implement enter/leave, send/receive messages, slicer - psyc, social: add struct GNUNET_PSYC_Message for single-fragment join messages - psyc: add message callback in addition to message part callback - client_manager, social, psyc, multicast: add disconnect callback
Diffstat (limited to 'src/social')
-rw-r--r--src/social/Makefile.am5
-rw-r--r--src/social/gnunet-service-social.c1219
-rw-r--r--src/social/social.h85
-rw-r--r--src/social/social_api.c1259
-rw-r--r--src/social/test_social.c686
5 files changed, 3037 insertions, 217 deletions
diff --git a/src/social/Makefile.am b/src/social/Makefile.am
index 04184dbc6..02b1bf823 100644
--- a/src/social/Makefile.am
+++ b/src/social/Makefile.am
@@ -24,6 +24,11 @@ libgnunetsocial_la_SOURCES = \
24libgnunetsocial_la_LIBADD = \ 24libgnunetsocial_la_LIBADD = \
25 $(top_builddir)/src/util/libgnunetutil.la \ 25 $(top_builddir)/src/util/libgnunetutil.la \
26 $(top_builddir)/src/env/libgnunetenv.la \ 26 $(top_builddir)/src/env/libgnunetenv.la \
27 $(top_builddir)/src/psyc/libgnunetpsycutil.la \
28 $(top_builddir)/src/core/libgnunetcore.la \
29 $(top_builddir)/src/identity/libgnunetidentity.la \
30 $(top_builddir)/src/gns/libgnunetgns.la \
31 $(top_builddir)/src/namestore/libgnunetnamestore.la \
27 $(GN_LIBINTL) $(XLIB) 32 $(GN_LIBINTL) $(XLIB)
28libgnunetsocial_la_LDFLAGS = \ 33libgnunetsocial_la_LDFLAGS = \
29 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 34 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c
index ab67bedd6..90d12200d 100644
--- a/src/social/gnunet-service-social.c
+++ b/src/social/gnunet-service-social.c
@@ -32,6 +32,7 @@
32#include "gnunet_protocols.h" 32#include "gnunet_protocols.h"
33#include "gnunet_statistics_service.h" 33#include "gnunet_statistics_service.h"
34#include "gnunet_psyc_service.h" 34#include "gnunet_psyc_service.h"
35#include "gnunet_psyc_util_lib.h"
35#include "gnunet_social_service.h" 36#include "gnunet_social_service.h"
36#include "social.h" 37#include "social.h"
37 38
@@ -71,41 +72,56 @@ static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
71 72
72 73
73/** 74/**
74 * Message in the transmission queue. 75 * Message fragment transmission queue.
75 */ 76 */
76struct TransmitMessage 77struct FragmentTransmitQueue
77{ 78{
78 struct TransmitMessage *prev; 79 struct FragmentTransmitQueue *prev;
79 struct TransmitMessage *next; 80 struct FragmentTransmitQueue *next;
80 81
81 struct GNUNET_SERVER_Client *client; 82 struct GNUNET_SERVER_Client *client;
82 83
83 /** 84 /**
84 * ID assigned to the message. 85 * Pointer to the next message part inside the data after this struct.
85 */ 86 */
86 uint64_t id; 87 struct GNUNET_MessageHeader *next_part;
87 88
88 /** 89 /**
89 * Size of @a buf 90 * Size of message.
90 */ 91 */
91 uint16_t size; 92 uint16_t size;
92 93
93 /** 94 /**
94 * @see enum MessageState 95 * @see enum GNUNET_PSYC_MessageState
95 */ 96 */
96 uint8_t state; 97 uint8_t state;
97 98
98 /* Followed by message */ 99 /* Followed by one or more message parts. */
99}; 100};
100 101
101 102
102/** 103/**
104 * Message transmission queue.
105 */
106struct MessageTransmitQueue
107{
108 struct MessageTransmitQueue *prev;
109 struct MessageTransmitQueue *next;
110
111 struct FragmentTransmitQueue *frags_head;
112 struct FragmentTransmitQueue *frags_tail;
113
114 struct GNUNET_SERVER_Client *client;
115};
116
117/**
103 * List of connected clients. 118 * List of connected clients.
104 */ 119 */
105struct ClientList 120struct ClientListItem
106{ 121{
107 struct ClientList *prev; 122 struct ClientListItem *prev;
108 struct ClientList *next; 123 struct ClientListItem *next;
124
109 struct GNUNET_SERVER_Client *client; 125 struct GNUNET_SERVER_Client *client;
110}; 126};
111 127
@@ -115,11 +131,11 @@ struct ClientList
115 */ 131 */
116struct Place 132struct Place
117{ 133{
118 struct ClientList *clients_head; 134 struct ClientListItem *clients_head;
119 struct ClientList *clients_tail; 135 struct ClientListItem *clients_tail;
120 136
121 struct TransmitMessage *tmit_head; 137 struct MessageTransmitQueue *tmit_msgs_head;
122 struct TransmitMessage *tmit_tail; 138 struct MessageTransmitQueue *tmit_msgs_tail;
123 139
124 /** 140 /**
125 * Public key of the channel. 141 * Public key of the channel.
@@ -132,9 +148,27 @@ struct Place
132 struct GNUNET_HashCode pub_key_hash; 148 struct GNUNET_HashCode pub_key_hash;
133 149
134 /** 150 /**
151 * Last message ID received for the place.
152 * 0 if there is no such message.
153 */
154 uint64_t max_message_id;
155
156 /**
135 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)? 157 * Is this a host (#GNUNET_YES), or guest (#GNUNET_NO)?
136 */ 158 */
137 uint8_t is_host; 159 uint8_t is_host;
160
161 /**
162 * Is this place ready to receive messages from client?
163 * #GNUNET_YES or #GNUNET_NO
164 */
165 uint8_t is_ready;
166
167 /**
168 * Is the client disconnected?
169 * #GNUNET_YES or #GNUNET_NO
170 */
171 uint8_t is_disconnected;
138}; 172};
139 173
140 174
@@ -146,7 +180,7 @@ struct Host
146 /** 180 /**
147 * Place struct common for Host and Guest 181 * Place struct common for Host and Guest
148 */ 182 */
149 struct Place pl; 183 struct Place plc;
150 184
151 /** 185 /**
152 * Private key of the channel. 186 * Private key of the channel.
@@ -184,17 +218,17 @@ struct Guest
184 /** 218 /**
185 * Place struct common for Host and Guest. 219 * Place struct common for Host and Guest.
186 */ 220 */
187 struct Place pl; 221 struct Place plc;
188 222
189 /** 223 /**
190 * Private key of the slave. 224 * Private key of the slave.
191 */ 225 */
192 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; 226 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
193 227
194 /** 228 /**
195 * Public key of the slave. 229 * Public key of the slave.
196 */ 230 */
197 struct GNUNET_CRYPTO_EddsaPublicKey pub_key; 231 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
198 232
199 /** 233 /**
200 * Hash of @a pub_key. 234 * Hash of @a pub_key.
@@ -230,11 +264,32 @@ struct Guest
230 * Join request to be transmitted to the master on join. 264 * Join request to be transmitted to the master on join.
231 */ 265 */
232 struct GNUNET_MessageHeader *join_req; 266 struct GNUNET_MessageHeader *join_req;
267
268 /**
269 * Join decision received from PSYC.
270 */
271 struct GNUNET_PSYC_JoinDecisionMessage *join_dcsn;
272
273};
274
275
276struct Client
277{
278 /**
279 * Place where the client entered.
280 */
281 struct Place *plc;
282
283 /**
284 * Message queue for the message currently being transmitted
285 * by this client.
286 */
287 struct MessageTransmitQueue *tmit_msg;
233}; 288};
234 289
235 290
236static inline void 291static int
237transmit_message (struct Place *pl); 292psyc_transmit_message (struct Place *plc);
238 293
239 294
240/** 295/**
@@ -265,12 +320,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
265static void 320static void
266cleanup_host (struct Host *hst) 321cleanup_host (struct Host *hst)
267{ 322{
268 struct Place *pl = &hst->pl; 323 struct Place *plc = &hst->plc;
269 324
270 if (NULL != hst->master) 325 if (NULL != hst->master)
271 GNUNET_PSYC_master_stop (hst->master); 326 GNUNET_PSYC_master_stop (hst->master, GNUNET_NO, NULL, NULL); // FIXME
272 GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs); 327 GNUNET_CONTAINER_multihashmap_destroy (hst->join_reqs);
273 GNUNET_CONTAINER_multihashmap_remove (hosts, &pl->pub_key_hash, pl); 328 GNUNET_CONTAINER_multihashmap_remove (hosts, &plc->pub_key_hash, plc);
274} 329}
275 330
276 331
@@ -280,28 +335,28 @@ cleanup_host (struct Host *hst)
280static void 335static void
281cleanup_guest (struct Guest *gst) 336cleanup_guest (struct Guest *gst)
282{ 337{
283 struct Place *pl = &gst->pl; 338 struct Place *plc = &gst->plc;
284 struct GNUNET_CONTAINER_MultiHashMap * 339 struct GNUNET_CONTAINER_MultiHashMap *
285 pl_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, 340 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
286 &pl->pub_key_hash); 341 &plc->pub_key_hash);
287 GNUNET_assert (NULL != pl_gst); 342 GNUNET_assert (NULL != plc_gst);
288 GNUNET_CONTAINER_multihashmap_remove (pl_gst, &gst->pub_key_hash, gst); 343 GNUNET_CONTAINER_multihashmap_remove (plc_gst, &gst->pub_key_hash, gst);
289 344
290 if (0 == GNUNET_CONTAINER_multihashmap_size (pl_gst)) 345 if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
291 { 346 {
292 GNUNET_CONTAINER_multihashmap_remove (place_guests, &pl->pub_key_hash, 347 GNUNET_CONTAINER_multihashmap_remove (place_guests, &plc->pub_key_hash,
293 pl_gst); 348 plc_gst);
294 GNUNET_CONTAINER_multihashmap_destroy (pl_gst); 349 GNUNET_CONTAINER_multihashmap_destroy (plc_gst);
295 } 350 }
296 GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, gst); 351 GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, gst);
297 352
298 if (NULL != gst->join_req) 353 if (NULL != gst->join_req)
299 GNUNET_free (gst->join_req); 354 GNUNET_free (gst->join_req);
300 if (NULL != gst->relays) 355 if (NULL != gst->relays)
301 GNUNET_free (gst->relays); 356 GNUNET_free (gst->relays);
302 if (NULL != gst->slave) 357 if (NULL != gst->slave)
303 GNUNET_PSYC_slave_part (gst->slave); 358 GNUNET_PSYC_slave_part (gst->slave, GNUNET_NO, NULL, NULL); // FIXME
304 GNUNET_CONTAINER_multihashmap_remove (guests, &pl->pub_key_hash, pl); 359 GNUNET_CONTAINER_multihashmap_remove (guests, &plc->pub_key_hash, plc);
305} 360}
306 361
307 362
@@ -309,12 +364,23 @@ cleanup_guest (struct Guest *gst)
309 * Clean up place data structures after a client disconnected. 364 * Clean up place data structures after a client disconnected.
310 */ 365 */
311static void 366static void
312cleanup_place (struct Place *pl) 367cleanup_place (struct Place *plc)
313{ 368{
314 (GNUNET_YES == pl->is_host) 369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 ? cleanup_host ((struct Host *) pl) 370 "%p Cleaning up place %s\n",
316 : cleanup_guest ((struct Guest *) pl); 371 plc, GNUNET_h2s (&plc->pub_key_hash));
317 GNUNET_free (pl); 372
373 (GNUNET_YES == plc->is_host)
374 ? cleanup_host ((struct Host *) plc)
375 : cleanup_guest ((struct Guest *) plc);
376 GNUNET_free (plc);
377}
378
379
380static void
381schedule_cleanup_place (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
382{
383 cleanup_place (cls);
318} 384}
319 385
320 386
@@ -331,76 +397,1073 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
331 if (NULL == client) 397 if (NULL == client)
332 return; 398 return;
333 399
334 struct Place * 400 struct Client *
335 pl = GNUNET_SERVER_client_get_user_context (client, struct Place); 401 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 402 if (NULL == ctx)
337 "%p Client (%s) disconnected from place %s\n",
338 pl, (GNUNET_YES == pl->is_host) ? "host" : "guest",
339 GNUNET_h2s (&pl->pub_key_hash));
340
341 if (NULL == pl)
342 { 403 {
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 "%p User context is NULL in client_disconnect()\n", pl); 405 "%p User context is NULL in client_disconnect()\n", ctx);
345 GNUNET_break (0); 406 GNUNET_break (0);
346 return; 407 return;
347 } 408 }
348 409
349 struct ClientList *cl = pl->clients_head; 410 struct Place *plc = ctx->plc;
350 while (NULL != cl) 411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
412 "%p Client (%s) disconnected from place %s\n",
413 plc, (GNUNET_YES == plc->is_host) ? "host" : "guest",
414 GNUNET_h2s (&plc->pub_key_hash));
415
416 struct ClientListItem *cli = plc->clients_head;
417 while (NULL != cli)
351 { 418 {
352 if (cl->client == client) 419 if (cli->client == client)
353 { 420 {
354 GNUNET_CONTAINER_DLL_remove (pl->clients_head, pl->clients_tail, cl); 421 GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli);
355 GNUNET_free (cl); 422 GNUNET_free (cli);
356 break; 423 break;
357 } 424 }
358 cl = cl->next; 425 cli = cli->next;
359 } 426 }
360 427
361 if (NULL == pl->clients_head) 428 if (NULL == plc->clients_head)
362 { /* Last client disconnected. */ 429 { /* Last client disconnected. */
363 if (NULL != pl->tmit_head) 430 if (GNUNET_YES != plc->is_disconnected)
364 { /* Send pending messages to PSYC before cleanup. */ 431 {
365 //FIXME: transmit_message (pl); 432 plc->is_disconnected = GNUNET_YES;
433 if (NULL != plc->tmit_msgs_head)
434 { /* Send pending messages to PSYC before cleanup. */
435 psyc_transmit_message (plc);
436 }
437 else
438 {
439 cleanup_place (plc);
440 }
366 } 441 }
367 else 442 }
443}
444
445
446/**
447 * Send message to all clients connected to the channel.
448 */
449static void
450client_send_msg (const struct Place *plc,
451 const struct GNUNET_MessageHeader *msg)
452{
453 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
454 "%p Sending message to clients.\n", plc);
455
456 struct ClientListItem *cli = plc->clients_head;
457 while (NULL != cli)
458 {
459 GNUNET_SERVER_notification_context_add (nc, cli->client);
460 GNUNET_SERVER_notification_context_unicast (nc, cli->client, msg, GNUNET_NO);
461 cli = cli->next;
462 }
463}
464
465
466/**
467 * Called after a PSYC master is started.
468 */
469static void
470psyc_master_started (void *cls, uint64_t max_message_id)
471{
472 struct Host *hst = cls;
473 struct Place *plc = &hst->plc;
474 plc->max_message_id = max_message_id;
475 plc->is_ready = GNUNET_YES;
476
477 struct CountersResult res;
478 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
479 res.header.size = htons (sizeof (res));
480 res.result_code = htonl (GNUNET_OK);
481 res.max_message_id = GNUNET_htonll (plc->max_message_id);
482
483 client_send_msg (plc, &res.header);
484}
485
486
487/**
488 * Called when a PSYC master receives a join request.
489 */
490static void
491psyc_recv_join_request (void *cls,
492 const struct GNUNET_PSYC_JoinRequestMessage *req,
493 const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
494 const struct GNUNET_PSYC_Message *join_msg,
495 struct GNUNET_PSYC_JoinHandle *jh)
496{
497 struct Host *hst = cls;
498 struct GNUNET_HashCode slave_key_hash;
499 GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
500 GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
502 client_send_msg (&hst->plc, &req->header);
503}
504
505
506/**
507 * Called after a PSYC slave is connected.
508 */
509static void
510psyc_slave_connected (void *cls, uint64_t max_message_id)
511{
512 struct Guest *gst = cls;
513 struct Place *plc = &gst->plc;
514 plc->max_message_id = max_message_id;
515 plc->is_ready = GNUNET_YES;
516
517 struct CountersResult res;
518 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
519 res.header.size = htons (sizeof (res));
520 res.result_code = htonl (GNUNET_OK);
521 res.max_message_id = GNUNET_htonll (plc->max_message_id);
522
523 client_send_msg (plc, &res.header);
524}
525
526
527/**
528 * Called when a PSYC slave receives a join decision.
529 */
530static void
531psyc_recv_join_dcsn (void *cls,
532 const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
533 int is_admitted,
534 const struct GNUNET_PSYC_Message *join_msg)
535{
536 struct Guest *gst = cls;
537 client_send_msg (&gst->plc, &dcsn->header);
538}
539
540
541/**
542 * Called when a PSYC master or slave receives a message.
543 */
544static void
545psyc_recv_message (void *cls,
546 uint64_t message_id,
547 uint32_t flags,
548 const struct GNUNET_PSYC_MessageHeader *msg)
549{
550 struct Place *plc = cls;
551 client_send_msg (plc, &msg->header);
552
553 /* FIXME: further processing */
554}
555
556
557/**
558 * Initialize place data structure.
559 */
560static void
561place_init (struct Place *plc)
562{
563
564}
565
566
567/**
568 * Handle a connecting client entering a place as host.
569 */
570static void
571client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
572 const struct GNUNET_MessageHeader *msg)
573{
574 const struct HostEnterRequest *req
575 = (const struct HostEnterRequest *) msg;
576
577 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
578 struct GNUNET_HashCode pub_key_hash;
579
580 GNUNET_CRYPTO_eddsa_key_get_public (&req->place_key, &pub_key);
581 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
582
583 struct Host *
584 hst = GNUNET_CONTAINER_multihashmap_get (hosts, &pub_key_hash);
585 struct Place *plc;
586
587 if (NULL == hst)
588 {
589 hst = GNUNET_new (struct Host);
590 hst->policy = ntohl (req->policy);
591 hst->priv_key = req->place_key;
592 hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
593
594 plc = &hst->plc;
595 plc->is_host = GNUNET_YES;
596 plc->pub_key = pub_key;
597 plc->pub_key_hash = pub_key_hash;
598 place_init (plc);
599
600 GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
601 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
602 hst->master = GNUNET_PSYC_master_start (cfg, &hst->priv_key, hst->policy,
603 &psyc_master_started,
604 &psyc_recv_join_request,
605 &psyc_recv_message, NULL, hst);
606 }
607 else
608 {
609 plc = &hst->plc;
610
611 struct CountersResult res;
612 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
613 res.header.size = htons (sizeof (res));
614 res.result_code = htonl (GNUNET_OK);
615 res.max_message_id = GNUNET_htonll (plc->max_message_id);
616
617 GNUNET_SERVER_notification_context_add (nc, client);
618 GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
619 GNUNET_NO);
620 }
621
622 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
623 "%p Client connected as host to place %s.\n",
624 hst, GNUNET_h2s (&plc->pub_key_hash));
625
626 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
627 cli->client = client;
628 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
629
630 struct Client *ctx = GNUNET_new (struct Client);
631 ctx->plc = plc;
632 GNUNET_SERVER_client_set_user_context (client, ctx);
633 GNUNET_SERVER_receive_done (client, GNUNET_OK);
634}
635
636
637/**
638 * Handle a connecting client entering a place as guest.
639 */
640static void
641client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
642 const struct GNUNET_MessageHeader *msg)
643{
644 const struct GuestEnterRequest *req
645 = (const struct GuestEnterRequest *) msg;
646 uint16_t req_size = ntohs (req->header.size);
647
648 struct GNUNET_CRYPTO_EcdsaPublicKey gst_pub_key;
649 struct GNUNET_HashCode pub_key_hash, gst_pub_key_hash;
650
651 GNUNET_CRYPTO_ecdsa_key_get_public (&req->guest_key, &gst_pub_key);
652 GNUNET_CRYPTO_hash (&gst_pub_key, sizeof (gst_pub_key), &gst_pub_key_hash);
653 GNUNET_CRYPTO_hash (&req->place_key, sizeof (req->place_key), &pub_key_hash);
654
655 struct GNUNET_CONTAINER_MultiHashMap *
656 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &pub_key_hash);
657 struct Guest *gst = NULL;
658 struct Place *plc;
659
660 if (NULL != plc_gst)
661 {
662 gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &gst_pub_key_hash);
663 }
664 if (NULL == gst || NULL == gst->slave)
665 {
666 gst = GNUNET_new (struct Guest);
667 gst->priv_key = req->guest_key;
668 gst->pub_key = gst_pub_key;
669 gst->pub_key_hash = gst_pub_key_hash;
670 gst->origin = req->origin;
671 gst->relay_count = ntohl (req->relay_count);
672
673 const struct GNUNET_PeerIdentity *
674 relays = (const struct GNUNET_PeerIdentity *) &req[1];
675 uint16_t relay_size = gst->relay_count * sizeof (*relays);
676 struct GNUNET_PSYC_Message *join_msg = NULL;
677 uint16_t join_msg_size = 0;
678
679 if (sizeof (*req) + relay_size + sizeof (struct GNUNET_MessageHeader)
680 <= req_size)
681 {
682 join_msg = (struct GNUNET_PSYC_Message *)
683 (((char *) &req[1]) + relay_size);
684 join_msg_size = ntohs (join_msg->header.size);
685 }
686 if (sizeof (*req) + relay_size + join_msg_size != req_size)
687 {
688 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
689 "%u + %u + %u != %u\n",
690 sizeof (*req), relay_size, join_msg_size, req_size);
691 GNUNET_break (0);
692 GNUNET_SERVER_client_disconnect (client);
693 return;
694 }
695 if (0 < gst->relay_count)
696 {
697 gst->relays = GNUNET_malloc (relay_size);
698 memcpy (gst->relays, &req[1], relay_size);
699 }
700
701 plc = &gst->plc;
702 plc->is_host = GNUNET_NO;
703 plc->pub_key = req->place_key;
704 plc->pub_key_hash = pub_key_hash;
705 place_init (plc);
706
707 if (NULL == plc_gst)
708 {
709 plc_gst = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
710 GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
711 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
712 }
713 GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, plc,
714 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
715 GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, plc,
716 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
717 gst->slave
718 = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key,
719 &gst->origin, gst->relay_count, gst->relays,
720 &psyc_recv_message, NULL, &psyc_slave_connected,
721 &psyc_recv_join_dcsn, gst, join_msg);
722 }
723 else
724 {
725 plc = &gst->plc;
726
727 struct CountersResult res;
728 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK);
729 res.header.size = htons (sizeof (res));
730 res.result_code = htonl (GNUNET_OK);
731 res.max_message_id = GNUNET_htonll (plc->max_message_id);
732
733 GNUNET_SERVER_notification_context_add (nc, client);
734 GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
735 GNUNET_NO);
736 if (NULL != gst->join_dcsn)
368 { 737 {
369 cleanup_place (pl); 738 GNUNET_SERVER_notification_context_add (nc, client);
739 GNUNET_SERVER_notification_context_unicast (nc, client,
740 &gst->join_dcsn->header,
741 GNUNET_NO);
370 } 742 }
371 } 743 }
744
745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
746 "%p Client connected as guest to place %s.\n",
747 gst, GNUNET_h2s (&plc->pub_key_hash));
748
749 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
750 cli->client = client;
751 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
752
753 struct Client *ctx = GNUNET_new (struct Client);
754 ctx->plc = plc;
755 GNUNET_SERVER_client_set_user_context (client, ctx);
756 GNUNET_SERVER_receive_done (client, GNUNET_OK);
372} 757}
373 758
374 759
760struct JoinDecisionClosure
761{
762 int32_t is_admitted;
763 struct GNUNET_PSYC_Message *msg;
764};
765
766
767/**
768 * Iterator callback for responding to join requests.
769 */
770static int
771psyc_send_join_decision (void *cls, const struct GNUNET_HashCode *pub_key_hash,
772 void *value)
773{
774 struct JoinDecisionClosure *jcls = cls;
775 struct GNUNET_PSYC_JoinHandle *jh = value;
776 // FIXME: add relays
777 GNUNET_PSYC_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
778 return GNUNET_YES;
779}
780
781
782/**
783 * Handle an entry decision from a host client.
784 */
375static void 785static void
376client_home_enter (void *cls, struct GNUNET_SERVER_Client *client, 786client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
377 const struct GNUNET_MessageHeader *msg) 787 const struct GNUNET_MessageHeader *msg)
378{ 788{
789 struct Client *
790 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
791 GNUNET_assert (NULL != ctx);
792 struct Place *plc = ctx->plc;
793 GNUNET_assert (GNUNET_YES == plc->is_host);
794 struct Host *hst = (struct Host *) plc;
795
796 struct GNUNET_PSYC_JoinDecisionMessage *
797 dcsn = (struct GNUNET_PSYC_JoinDecisionMessage *) msg;
798 struct JoinDecisionClosure jcls;
799 jcls.is_admitted = ntohl (dcsn->is_admitted);
800 jcls.msg
801 = (sizeof (*dcsn) + sizeof (*jcls.msg) <= ntohs (msg->size))
802 ? (struct GNUNET_PSYC_Message *) &dcsn[1]
803 : NULL;
804
805 struct GNUNET_HashCode slave_key_hash;
806 GNUNET_CRYPTO_hash (&dcsn->slave_key, sizeof (dcsn->slave_key),
807 &slave_key_hash);
379 808
809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
810 "%p Got join decision (%d) from client for place %s..\n",
811 hst, jcls.is_admitted, GNUNET_h2s (&plc->pub_key_hash));
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
813 "%p ..and slave %s.\n",
814 hst, GNUNET_h2s (&slave_key_hash));
815
816 GNUNET_CONTAINER_multihashmap_get_multiple (hst->join_reqs, &slave_key_hash,
817 &psyc_send_join_decision, &jcls);
818 GNUNET_CONTAINER_multihashmap_remove_all (hst->join_reqs, &slave_key_hash);
819 GNUNET_SERVER_receive_done (client, GNUNET_OK);
380} 820}
381 821
382 822
823/**
824 * Send acknowledgement to a client.
825 *
826 * Sent after a message fragment has been passed on to multicast.
827 *
828 * @param plc The place struct for the client.
829 */
383static void 830static void
384client_place_enter (void *cls, struct GNUNET_SERVER_Client *client, 831send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client)
385 const struct GNUNET_MessageHeader *msg) 832{
833 struct GNUNET_MessageHeader res;
834 res.size = htons (sizeof (res));
835 res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
836
837 GNUNET_SERVER_notification_context_add (nc, client);
838 GNUNET_SERVER_notification_context_unicast (nc, client, &res, GNUNET_NO);
839}
840
841
842/**
843 * Proceed to the next message part in the transmission queue.
844 *
845 * @param plc
846 * Place where the transmission is going on.
847 * @param tmit_msg
848 * Currently transmitted message.
849 * @param tmit_frag
850 * Currently transmitted message fragment.
851 *
852 * @return @a tmit_frag, or NULL if reached the end of fragment.
853 */
854static struct FragmentTransmitQueue *
855psyc_transmit_queue_next_part (struct Place *plc,
856 struct MessageTransmitQueue *tmit_msg,
857 struct FragmentTransmitQueue *tmit_frag)
858{
859 uint16_t psize = ntohs (tmit_frag->next_part->size);
860 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
861 "%p psyc_transmit_queue_next_part: %x + %u - %x = %u < %u\n",
862 plc, tmit_frag->next_part, psize, &tmit_frag[1],
863 (char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1]),
864 tmit_frag->size);
865 if ((char *) tmit_frag->next_part + psize - ((char *) &tmit_frag[1])
866 < tmit_frag->size)
867 {
868 tmit_frag->next_part
869 = (struct GNUNET_MessageHeader *) ((char *) tmit_frag->next_part + psize);
870 }
871 else /* Reached end of current fragment. */
872 {
873 if (NULL != tmit_frag->client)
874 send_message_ack (plc, tmit_frag->client);
875 GNUNET_CONTAINER_DLL_remove (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
876 GNUNET_free (tmit_frag);
877 tmit_frag = NULL;
878 }
879 return tmit_frag;
880}
881
882
883/**
884 * Proceed to next message in transmission queue.
885 *
886 * @param plc
887 * Place where the transmission is going on.
888 * @param tmit_msg
889 * Currently transmitted message.
890 *
891 * @return The next message in queue, or NULL if queue is empty.
892 */
893static struct MessageTransmitQueue *
894psyc_transmit_queue_next_msg (struct Place *plc,
895 struct MessageTransmitQueue *tmit_msg)
896{
897 GNUNET_CONTAINER_DLL_remove (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
898 GNUNET_free (tmit_msg);
899 return plc->tmit_msgs_head;
900}
901
902
903/**
904 * Callback for data transmission to PSYC.
905 */
906static int
907psyc_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
386{ 908{
909 struct Place *plc = cls;
910 struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
911 GNUNET_assert (NULL != tmit_msg);
912 struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
913 if (NULL == tmit_frag)
914 { /* Rest of the message have not arrived yet, pause transmission */
915 *data_size = 0;
916 return GNUNET_NO;
917 }
918 struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
919 if (NULL == pmsg)
920 {
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "%p psyc_transmit_notify_data: nothing to send.\n", plc);
923 *data_size = 0;
924 return GNUNET_NO;
925 }
387 926
927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
928 "%p psyc_transmit_notify_data()\n", plc);
929 GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
930
931 uint16_t ptype = ntohs (pmsg->type);
932 uint16_t pdata_size = ntohs (pmsg->size) - sizeof (*pmsg);
933 int ret;
934
935 switch (ptype)
936 {
937 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
938 if (*data_size < pdata_size)
939 {
940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
941 "%p psyc_transmit_notify_data: buffer size too small for data.\n", plc);
942 *data_size = 0;
943 return GNUNET_NO;
944 }
945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
946 "%p psyc_transmit_notify_data: sending %u bytes.\n",
947 plc, pdata_size);
948
949 *data_size = pdata_size;
950 memcpy (data, &pmsg[1], *data_size);
951 ret = GNUNET_NO;
952 break;
953
954 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
955 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
956 *data_size = 0;
957 ret = GNUNET_YES;
958 break;
959
960 default:
961 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
962 "%p psyc_transmit_notify_data: unexpected message part of type %u.\n",
963 plc, ptype);
964 ret = GNUNET_SYSERR;
965 }
966
967 if (GNUNET_SYSERR == ret)
968 {
969 *data_size = 0;
970 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
971 plc->is_disconnected = GNUNET_YES;
972 GNUNET_SERVER_client_disconnect (tmit_frag->client);
973 GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
974 return ret;
975 }
976 else
977 {
978 psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
979
980 if (NULL == tmit_msg->frags_head
981 && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
982 { /* Reached end of current message. */
983 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
984 }
985 }
986
987 if (ret != GNUNET_NO)
988 {
989 if (NULL != tmit_msg)
990 {
991 psyc_transmit_message (plc);
992 }
993 else if (GNUNET_YES == plc->is_disconnected)
994 {
995 /* FIXME: handle partial message (when still in_transmit) */
996 cleanup_place (plc);
997 }
998 }
999 return ret;
388} 1000}
389 1001
390 1002
1003/**
1004 * Callback for modifier transmission to PSYC.
1005 */
1006static int
1007psyc_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
1008 uint8_t *oper, uint32_t *full_value_size)
1009{
1010 struct Place *plc = cls;
1011 struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
1012 GNUNET_assert (NULL != tmit_msg);
1013 struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
1014 if (NULL == tmit_frag)
1015 { /* Rest of the message have not arrived yet, pause transmission */
1016 *data_size = 0;
1017 return GNUNET_NO;
1018 }
1019 struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
1020 if (NULL == pmsg)
1021 {
1022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 "%p psyc_transmit_notify_mod: nothing to send.\n", plc);
1024 *data_size = 0;
1025 return GNUNET_NO;
1026 }
1027
1028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1029 "%p psyc_transmit_notify_mod()\n", plc);
1030 GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg);
1031
1032 uint16_t ptype = ntohs (pmsg->type);
1033 int ret;
1034
1035 switch (ptype)
1036 {
1037 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
1038 {
1039 if (NULL == oper)
1040 {
1041 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1042 "%p psyc_transmit_notify_mod: oper is NULL.\n", plc);
1043 ret = GNUNET_SYSERR;
1044 break;
1045 }
1046 struct GNUNET_PSYC_MessageModifier *
1047 pmod = (struct GNUNET_PSYC_MessageModifier *) tmit_frag->next_part;
1048 uint16_t mod_size = ntohs (pmod->header.size) - sizeof (*pmod);
1049
1050 if (*data_size < mod_size)
1051 {
1052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053 "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
1054 *data_size = 0;
1055 return GNUNET_NO;
1056 }
1057
1058 *full_value_size = ntohl (pmod->value_size);
1059 *oper = pmod->oper;
1060 *data_size = mod_size;
1061 memcpy (data, &pmod[1], mod_size);
1062 ret = GNUNET_NO;
1063#if REMOVE // FIXME
1064 ret = (mod_size - strnlen ((char *) &pmod[1], mod_size) - 1
1065 == *full_value_size)
1066 ? GNUNET_YES
1067 : GNUNET_NO;
1068#endif
1069 break;
1070 }
1071
1072 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
1073 {
1074 if (NULL != oper)
1075 {
1076 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1077 "%p psyc_transmit_notify_mod: oper is not NULL.\n", plc);
1078 ret = GNUNET_SYSERR;
1079 break;
1080 }
1081 uint16_t mod_size = ntohs (pmsg->size) - sizeof (*pmsg);
1082 if (*data_size < mod_size)
1083 {
1084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1085 "%p psyc_transmit_notify_mod: buffer size too small for data.\n", plc);
1086 *data_size = 0;
1087 return GNUNET_NO;
1088 }
1089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090 "%p psyc_transmit_notify_mod: sending %u bytes.\n", plc, mod_size);
1091
1092 *data_size = mod_size;
1093 memcpy (data, &pmsg[1], *data_size);
1094 ret = GNUNET_NO;
1095 break;
1096 }
1097
1098 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
1099 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
1100 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
1101 *data_size = 0;
1102 ret = GNUNET_YES;
1103 break;
1104
1105 default:
1106 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1107 "%p psyc_transmit_notify_mod: unexpected message part of type %u.\n",
1108 plc, ptype);
1109 ret = GNUNET_SYSERR;
1110 }
1111
1112 if (GNUNET_SYSERR == ret)
1113 {
1114 *data_size = 0;
1115 ret = GNUNET_SYSERR;
1116 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
1117 plc->is_disconnected = GNUNET_YES;
1118 GNUNET_SERVER_client_disconnect (tmit_frag->client);
1119 GNUNET_SCHEDULER_add_now (&schedule_cleanup_place, plc);
1120 }
1121 else
1122 {
1123 psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
1124
1125 if (NULL == tmit_msg->frags_head
1126 && GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
1127 { /* Reached end of current message. */
1128 tmit_msg = psyc_transmit_queue_next_msg (plc, tmit_msg);
1129 }
1130 }
1131 return ret;
1132}
1133
1134/**
1135 * Callback for data transmission from a host to PSYC.
1136 */
1137static int
1138host_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
1139{
1140 int ret = psyc_transmit_notify_data (cls, data_size, data);
1141
1142 if (GNUNET_NO != ret)
1143 {
1144 struct Host *hst = cls;
1145 hst->tmit_handle = NULL;
1146 }
1147 return ret;
1148}
1149
1150
1151/**
1152 * Callback for the transmit functions of multicast.
1153 */
1154static int
1155guest_transmit_notify_data (void *cls, uint16_t *data_size, void *data)
1156{
1157 int ret = psyc_transmit_notify_data (cls, data_size, data);
1158
1159 if (GNUNET_NO != ret)
1160 {
1161 struct Guest *gst = cls;
1162 gst->tmit_handle = NULL;
1163 }
1164 return ret;
1165}
1166
1167
1168/**
1169 * Callback for modifier transmission from a host to PSYC.
1170 */
1171static int
1172host_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
1173 uint8_t *oper, uint32_t *full_value_size)
1174{
1175 int ret = psyc_transmit_notify_mod (cls, data_size, data,
1176 oper, full_value_size);
1177 if (GNUNET_SYSERR == ret)
1178 {
1179 struct Host *hst = cls;
1180 hst->tmit_handle = NULL;
1181 }
1182 return ret;
1183}
1184
1185
1186/**
1187 * Callback for modifier transmission from a guest to PSYC.
1188 */
1189static int
1190guest_transmit_notify_mod (void *cls, uint16_t *data_size, void *data,
1191 uint8_t *oper, uint32_t *full_value_size)
1192{
1193 int ret = psyc_transmit_notify_mod (cls, data_size, data,
1194 oper, full_value_size);
1195 if (GNUNET_SYSERR == ret)
1196 {
1197 struct Guest *gst = cls;
1198 gst->tmit_handle = NULL;
1199 }
1200 return ret;
1201}
1202
1203
1204/**
1205 * Get method part of next message from transmission queue.
1206 *
1207 * @param tmit_msg
1208 * Next item in message transmission queue.
1209 * @param[out] pmeth
1210 * The message method is returned here.
1211 *
1212 * @return #GNUNET_OK on success
1213 * #GNUNET_NO if there are no more messages in queue.
1214 * #GNUNET_SYSERR if the next message is malformed.
1215 */
1216static int
1217psyc_transmit_queue_next_method (struct Place *plc,
1218 struct GNUNET_PSYC_MessageMethod **pmeth)
1219{
1220 struct MessageTransmitQueue *tmit_msg = plc->tmit_msgs_head;
1221 if (NULL == tmit_msg)
1222 return GNUNET_NO;
1223
1224 struct FragmentTransmitQueue *tmit_frag = tmit_msg->frags_head;
1225 if (NULL == tmit_frag)
1226 {
1227 GNUNET_break (0);
1228 return GNUNET_NO;
1229 }
1230
1231 struct GNUNET_MessageHeader *pmsg = tmit_frag->next_part;
1232 if (NULL == pmsg
1233 || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD != ntohs (pmsg->type))
1234 {
1235 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1236 "%p psyc_transmit_queue_next_method: unexpected message part of type %u.\n",
1237 plc, ntohs (pmsg->type));
1238 GNUNET_break (0);
1239 return GNUNET_SYSERR;
1240 }
1241
1242 uint16_t psize = ntohs (pmsg->size);
1243 *pmeth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
1244
1245 if (psize < sizeof (**pmeth) + 1 || '\0' != *((char *) *pmeth + psize - 1))
1246 {
1247 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1248 "%p psyc_transmit_queue_next_method: invalid method name.\n",
1249 plc, ntohs (pmsg->type));
1250 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1251 "%u <= %u || NUL != %u\n",
1252 sizeof (**pmeth), psize, *((char *) *pmeth + psize - 1));
1253 GNUNET_break (0);
1254 return GNUNET_SYSERR;
1255 }
1256 psyc_transmit_queue_next_part (plc, tmit_msg, tmit_frag);
1257 return GNUNET_OK;
1258}
1259
1260
1261/**
1262 * Transmit the next message in queue from the host to the PSYC channel.
1263 */
1264static int
1265psyc_master_transmit_message (struct Host *hst)
1266{
1267
1268 if (NULL == hst->tmit_handle)
1269 {
1270 struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
1271 int ret = psyc_transmit_queue_next_method (&hst->plc, &pmeth);
1272 if (GNUNET_OK != ret)
1273 return ret;
1274
1275 hst->tmit_handle
1276 = GNUNET_PSYC_master_transmit (hst->master, (const char *) &pmeth[1],
1277 &host_transmit_notify_mod,
1278 &host_transmit_notify_data, hst,
1279 pmeth->flags);
1280 }
1281 else
1282 {
1283 GNUNET_PSYC_master_transmit_resume (hst->tmit_handle);
1284 }
1285 return GNUNET_OK;
1286}
1287
1288
1289/**
1290 * Transmit the next message in queue from a guest to the PSYC channel.
1291 */
1292static int
1293psyc_slave_transmit_message (struct Guest *gst)
1294{
1295 if (NULL == gst->tmit_handle)
1296 {
1297 struct GNUNET_PSYC_MessageMethod *pmeth = NULL;
1298 int ret = psyc_transmit_queue_next_method (&gst->plc, &pmeth);
1299 if (GNUNET_OK != ret)
1300 return ret;
1301
1302 gst->tmit_handle
1303 = GNUNET_PSYC_slave_transmit (gst->slave, (const char *) &pmeth[1],
1304 &guest_transmit_notify_mod,
1305 &guest_transmit_notify_data, gst,
1306 pmeth->flags);
1307 }
1308 else
1309 {
1310 GNUNET_PSYC_slave_transmit_resume (gst->tmit_handle);
1311 }
1312 return GNUNET_OK;
1313}
1314
1315
1316/**
1317 * Transmit a message to PSYC.
1318 */
1319static int
1320psyc_transmit_message (struct Place *plc)
1321{
1322 return
1323 (plc->is_host)
1324 ? psyc_master_transmit_message ((struct Host *) plc)
1325 : psyc_slave_transmit_message ((struct Guest *) plc);
1326}
1327
1328
1329/**
1330 * Queue message parts for sending to PSYC.
1331 *
1332 * @param plc Place to send to.
1333 * @param client Client the message originates from.
1334 * @param data_size Size of @a data.
1335 * @param data Concatenated message parts.
1336 * @param first_ptype First message part type in @a data.
1337 * @param last_ptype Last message part type in @a data.
1338 */
1339static struct MessageTransmitQueue *
1340psyc_transmit_queue_message (struct Place *plc,
1341 struct GNUNET_SERVER_Client *client,
1342 size_t data_size,
1343 const void *data,
1344 uint16_t first_ptype, uint16_t last_ptype,
1345 struct MessageTransmitQueue *tmit_msg)
1346{
1347 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == first_ptype)
1348 {
1349 tmit_msg = GNUNET_malloc (sizeof (*tmit_msg));
1350 GNUNET_CONTAINER_DLL_insert_tail (plc->tmit_msgs_head, plc->tmit_msgs_tail, tmit_msg);
1351 }
1352 else if (NULL == tmit_msg)
1353 {
1354 return NULL;
1355 }
1356
1357 struct FragmentTransmitQueue *
1358 tmit_frag = GNUNET_malloc (sizeof (*tmit_frag) + data_size);
1359 memcpy (&tmit_frag[1], data, data_size);
1360 tmit_frag->next_part = (struct GNUNET_MessageHeader *) &tmit_frag[1];
1361 tmit_frag->client = client;
1362 tmit_frag->size = data_size;
1363
1364 GNUNET_CONTAINER_DLL_insert_tail (tmit_msg->frags_head, tmit_msg->frags_tail, tmit_frag);
1365 tmit_msg->client = client;
1366 return tmit_msg;
1367}
1368
1369
1370/**
1371 * Cancel transmission of current message to PSYC.
1372 *
1373 * @param plc Place to send to.
1374 * @param client Client the message originates from.
1375 */
391static void 1376static void
392client_join_decision (void *cls, struct GNUNET_SERVER_Client *client, 1377psyc_transmit_cancel (struct Place *plc, struct GNUNET_SERVER_Client *client)
393 const struct GNUNET_MessageHeader *msg)
394{ 1378{
1379 uint16_t type = GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL;
1380
1381 struct GNUNET_MessageHeader msg;
1382 msg.size = htons (sizeof (msg));
1383 msg.type = htons (type);
395 1384
1385 psyc_transmit_queue_message (plc, client, sizeof (msg), &msg, type, type, NULL);
1386 psyc_transmit_message (plc);
1387
1388 /* FIXME: cleanup */
396} 1389}
397 1390
398 1391
1392/**
1393 * Handle an incoming message from a client, to be transmitted to the place.
1394 */
399static void 1395static void
400client_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, 1396client_recv_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
401 const struct GNUNET_MessageHeader *msg) 1397 const struct GNUNET_MessageHeader *msg)
402{ 1398{
1399 struct Client *
1400 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
1401 GNUNET_assert (NULL != ctx);
1402 struct Place *plc = ctx->plc;
1403 int ret = GNUNET_SYSERR;
403 1404
1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1406 "%p Received message from client.\n", plc);
1407 GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg);
1408
1409 if (GNUNET_YES != plc->is_ready)
1410 {
1411 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1412 "%p Place is not ready yet, disconnecting client.\n", plc);
1413 GNUNET_break (0);
1414 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1415 return;
1416 }
1417
1418 uint16_t size = ntohs (msg->size);
1419 uint16_t psize = size - sizeof (*msg);
1420 if (psize < sizeof (struct GNUNET_MessageHeader)
1421 || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < psize)
1422 {
1423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1424 "%p Received message with invalid payload size (%u) from client.\n",
1425 plc, psize);
1426 GNUNET_break (0);
1427 psyc_transmit_cancel (plc, client);
1428 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1429 return;
1430 }
1431
1432 uint16_t first_ptype = 0, last_ptype = 0;
1433 if (GNUNET_SYSERR
1434 == GNUNET_PSYC_receive_check_parts (psize, (const char *) &msg[1],
1435 &first_ptype, &last_ptype))
1436 {
1437 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1438 "%p Received invalid message part from client.\n", plc);
1439 GNUNET_break (0);
1440 psyc_transmit_cancel (plc, client);
1441 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1442 return;
1443 }
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1445 "%p Received message with first part type %u and last part type %u.\n",
1446 plc, first_ptype, last_ptype);
1447
1448 ctx->tmit_msg
1449 = psyc_transmit_queue_message (plc, client, psize, &msg[1],
1450 first_ptype, last_ptype, ctx->tmit_msg);
1451 if (NULL != ctx->tmit_msg)
1452 {
1453 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= last_ptype)
1454 ctx->tmit_msg = NULL;
1455 ret = psyc_transmit_message (plc);
1456 }
1457
1458 if (GNUNET_OK != ret)
1459 {
1460 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1461 "%p Received invalid message part from client.\n", plc);
1462 GNUNET_break (0);
1463 psyc_transmit_cancel (plc, client);
1464 ret = GNUNET_SYSERR;
1465 }
1466 GNUNET_SERVER_receive_done (client, ret);
404} 1467}
405 1468
406 1469
@@ -416,16 +1479,16 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
416 const struct GNUNET_CONFIGURATION_Handle *c) 1479 const struct GNUNET_CONFIGURATION_Handle *c)
417{ 1480{
418 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 1481 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
419 { &client_home_enter, NULL, 1482 { &client_recv_host_enter, NULL,
420 GNUNET_MESSAGE_TYPE_SOCIAL_HOME_ENTER, 0 }, 1483 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 },
421 1484
422 { &client_place_enter, NULL, 1485 { &client_recv_guest_enter, NULL,
423 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_ENTER, 0 }, 1486 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 },
424 1487
425 { &client_join_decision, NULL, 1488 { &client_recv_join_decision, NULL,
426 GNUNET_MESSAGE_TYPE_SOCIAL_JOIN_DECISION, 0 }, 1489 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 },
427 1490
428 { &client_psyc_message, NULL, 1491 { &client_recv_psyc_message, NULL,
429 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 } 1492 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }
430 }; 1493 };
431 1494
diff --git a/src/social/social.h b/src/social/social.h
index 7f854eed8..00edaefd1 100644
--- a/src/social/social.h
+++ b/src/social/social.h
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21/** 21/**
22 * @file psyc/psyc.h 22 * @file social/social.h
23 * @brief Common type definitions for the Social service and API. 23 * @brief Common type definitions for the Social service and API.
24 * @author Gabor X Toth 24 * @author Gabor X Toth
25 */ 25 */
@@ -30,16 +30,99 @@
30#include "platform.h" 30#include "platform.h"
31#include "gnunet_social_service.h" 31#include "gnunet_social_service.h"
32 32
33enum MessageState
34{
35 MSG_STATE_START = 0,
36 MSG_STATE_HEADER = 1,
37 MSG_STATE_METHOD = 2,
38 MSG_STATE_MODIFIER = 3,
39 MSG_STATE_MOD_CONT = 4,
40 MSG_STATE_DATA = 5,
41 MSG_STATE_END = 6,
42 MSG_STATE_CANCEL = 7,
43 MSG_STATE_ERROR = 8,
44};
45
33 46
34GNUNET_NETWORK_STRUCT_BEGIN 47GNUNET_NETWORK_STRUCT_BEGIN
35 48
36/**** library -> service ****/ 49/**** library -> service ****/
37 50
38 51
52struct HostEnterRequest
53{
54 /**
55 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER
56 */
57 struct GNUNET_MessageHeader header;
58
59 uint32_t policy GNUNET_PACKED;
60
61 struct GNUNET_CRYPTO_EcdsaPrivateKey host_key;
62
63 struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
64};
65
66
67struct GuestEnterRequest
68{
69 /**
70 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ADDR
71 */
72 struct GNUNET_MessageHeader header;
73
74 uint32_t relay_count GNUNET_PACKED;
75
76 struct GNUNET_CRYPTO_EcdsaPrivateKey guest_key;
77
78 struct GNUNET_CRYPTO_EddsaPublicKey place_key;
79
80 struct GNUNET_PeerIdentity origin;
81
82 /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */
83
84 /* Followed by struct GNUNET_MessageHeader join_msg */
85};
86
39 87
40/**** service -> library ****/ 88/**** service -> library ****/
41 89
42 90
91struct CountersResult
92{
93 /**
94 * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS
95 */
96 struct GNUNET_MessageHeader header;
97
98 /**
99 * Status code for the operation.
100 */
101 int32_t result_code GNUNET_PACKED;
102
103 /**
104 * Last message ID sent to the channel.
105 */
106 uint64_t max_message_id;
107};
108
109
110#if REMOVE
111struct NymEnterRequest
112{
113 /**
114 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER
115 */
116 struct GNUNET_MessageHeader header;
117 /**
118 * Public key of the joining slave.
119 */
120 struct GNUNET_CRYPTO_EcdsaPublicKey nym_key;
121
122 /* Followed by struct GNUNET_MessageHeader join_request */
123};
124#endif
125
43 126
44GNUNET_NETWORK_STRUCT_END 127GNUNET_NETWORK_STRUCT_END
45 128
diff --git a/src/social/social_api.c b/src/social/social_api.c
index ee13c7d61..d19f83e89 100644
--- a/src/social/social_api.c
+++ b/src/social/social_api.c
@@ -1,4 +1,4 @@
1/* 1 /*
2 * This file is part of GNUnet 2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors) 3 * (C) 2013 Christian Grothoff (and other contributing authors)
4 * 4 *
@@ -25,30 +25,93 @@
25 */ 25 */
26 26
27#include <inttypes.h> 27#include <inttypes.h>
28#include <string.h>
28 29
29#include "platform.h" 30#include "platform.h"
30#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
31#include "gnunet_env_lib.h" 32#include "gnunet_env_lib.h"
33#include "gnunet_core_service.h"
34#include "gnunet_identity_service.h"
35#include "gnunet_namestore_service.h"
36#include "gnunet_gns_service.h"
32#include "gnunet_psyc_service.h" 37#include "gnunet_psyc_service.h"
38#include "gnunet_psyc_util_lib.h"
33#include "gnunet_social_service.h" 39#include "gnunet_social_service.h"
34#include "social.h" 40#include "social.h"
35 41
42#define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__)
36 43
37/**
38 * Handle for a pseudonym of another user in the network.
39 */
40struct GNUNET_SOCIAL_Nym
41{
42
43};
44 44
45static struct GNUNET_CORE_Handle *core;
46static struct GNUNET_GNS_Handle *gns;
47static struct GNUNET_NAMESTORE_Handle *namestore;
48static struct GNUNET_PeerIdentity this_peer;
45 49
46/** 50/**
47 * Handle for a place where social interactions happen. 51 * Handle for a place where social interactions happen.
48 */ 52 */
49struct GNUNET_SOCIAL_Place 53struct GNUNET_SOCIAL_Place
50{ 54{
51 55 /**
56 * Configuration to use.
57 */
58 const struct GNUNET_CONFIGURATION_Handle *cfg;
59
60 /**
61 * Client connection to the service.
62 */
63 struct GNUNET_CLIENT_MANAGER_Connection *client;
64
65 /**
66 * Transmission handle;
67 */
68 struct GNUNET_PSYC_TransmitHandle *tmit;
69
70 /**
71 * Receipt handle;
72 */
73 struct GNUNET_PSYC_ReceiveHandle *recv;
74
75 /**
76 * Message to send on reconnect.
77 */
78 struct GNUNET_MessageHeader *connect_msg;
79
80 /**
81 * Slicer for processing incoming methods.
82 */
83 struct GNUNET_SOCIAL_Slicer *slicer;
84
85 /**
86 * Function called after disconnected from the service.
87 */
88 GNUNET_ContinuationCallback disconnect_cb;
89
90 /**
91 * Closure for @a disconnect_cb.
92 */
93 void *disconnect_cls;
94
95 /**
96 * Public key of the place.
97 */
98 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
99
100 /**
101 * Private key of the ego.
102 */
103 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
104
105 /**
106 * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)?
107 */
108 uint8_t is_host;
109
110 /**
111 * Is this place in the process of disconnecting from the service?
112 * #GNUNET_YES or #GNUNET_NO
113 */
114 uint8_t is_disconnecting;
52}; 115};
53 116
54 117
@@ -57,7 +120,20 @@ struct GNUNET_SOCIAL_Place
57 */ 120 */
58struct GNUNET_SOCIAL_Host 121struct GNUNET_SOCIAL_Host
59{ 122{
123 struct GNUNET_SOCIAL_Place plc;
60 124
125 struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
126
127 GNUNET_SOCIAL_HostEnterCallback enter_cb;
128
129 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb;
130
131 GNUNET_SOCIAL_FarewellCallback farewell_cb;
132
133 /**
134 * Closure for callbacks.
135 */
136 void *cb_cls;
61}; 137};
62 138
63 139
@@ -66,16 +142,91 @@ struct GNUNET_SOCIAL_Host
66 */ 142 */
67struct GNUNET_SOCIAL_Guest 143struct GNUNET_SOCIAL_Guest
68{ 144{
145 struct GNUNET_SOCIAL_Place plc;
69 146
147 GNUNET_SOCIAL_GuestEnterCallback enter_cb;
148
149 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb;
150
151 /**
152 * Closure for callbacks.
153 */
154 void *cb_cls;
70}; 155};
71 156
72 157
73/** 158/**
74 * Handle to an implementation of try-and-slice. 159 * Handle for a pseudonym of another user in the network.
160 */
161struct GNUNET_SOCIAL_Nym
162{
163 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
164 struct GNUNET_HashCode pub_key_hash;
165};
166
167
168/**
169 * Hash map of all nyms.
170 * pub_key_hash -> struct GNUNET_SOCIAL_Nym *
171 */
172struct GNUNET_CONTAINER_MultiHashMap *nyms;
173
174
175/**
176 * Handle for a try-and-slice instance.
75 */ 177 */
76struct GNUNET_SOCIAL_Slicer 178struct GNUNET_SOCIAL_Slicer
77{ 179{
180 /**
181 * Message handlers: method_name -> SlicerCallbacks
182 */
183 struct GNUNET_CONTAINER_MultiHashMap *handlers;
184
185
186 /**
187 * Currently being processed message part.
188 */
189 const struct GNUNET_MessageHeader *msg;
190
191 /**
192 * ID of currently being received message.
193 */
194 uint64_t message_id;
195
196 /**
197 * Method name of currently being received message.
198 */
199 char *method_name;
200
201 /**
202 * Public key of the nym the current message originates from.
203 */
204 struct GNUNET_CRYPTO_EcdsaPublicKey nym_key;
205
206 /**
207 * Size of @a method_name (including terminating \0).
208 */
209 uint16_t method_name_size;
210};
211
78 212
213/**
214 * Callbacks for a slicer method handler.
215 */
216struct SlicerCallbacks
217{
218 GNUNET_SOCIAL_MethodCallback method_cb;
219 GNUNET_SOCIAL_ModifierCallback modifier_cb;
220 GNUNET_SOCIAL_DataCallback data_cb;
221 GNUNET_SOCIAL_EndOfMessageCallback eom_cb;
222 void *cls;
223};
224
225
226struct SlicerRemoveClosure
227{
228 struct GNUNET_SOCIAL_Slicer *slicer;
229 struct SlicerCallbacks rm_cbs;
79}; 230};
80 231
81 232
@@ -118,6 +269,181 @@ struct GNUNET_SOCIAL_HistoryLesson
118}; 269};
119 270
120 271
272static struct GNUNET_SOCIAL_Nym *
273nym_get_or_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key)
274{
275 struct GNUNET_SOCIAL_Nym *nym = NULL;
276 struct GNUNET_HashCode pub_key_hash;
277
278 if (NULL == pub_key)
279 return NULL;
280
281 GNUNET_CRYPTO_hash (pub_key, sizeof (*pub_key), &pub_key_hash);
282
283 if (NULL == nyms)
284 nyms = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
285 else
286 nym = GNUNET_CONTAINER_multihashmap_get (nyms, &pub_key_hash);
287
288 if (NULL == nym)
289 {
290 nym = GNUNET_new (struct GNUNET_SOCIAL_Nym);
291 nym->pub_key = *pub_key;
292 nym->pub_key_hash = pub_key_hash;
293 GNUNET_CONTAINER_multihashmap_put (nyms, &nym->pub_key_hash, nym,
294 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
295 }
296 return nym;
297}
298
299
300static void
301nym_destroy (struct GNUNET_SOCIAL_Nym *nym)
302{
303 GNUNET_CONTAINER_multihashmap_remove (nyms, &nym->pub_key_hash, nym);
304 GNUNET_free (nym);
305}
306
307
308/**
309 * Call a handler for an incoming message part.
310 *
311 * @param cls
312 * @param key
313 * @param value
314 *
315 * @return
316 */
317int
318slicer_handler_notify (void *cls, const struct GNUNET_HashCode *key,
319 void *value)
320{
321 struct GNUNET_SOCIAL_Slicer *slicer = cls;
322 const struct GNUNET_MessageHeader *msg = slicer->msg;
323 struct SlicerCallbacks *cbs = value;
324 uint16_t ptype = ntohs (msg->type);
325
326 switch (ptype)
327 {
328 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
329 {
330 if (NULL == cbs->method_cb)
331 break;
332 struct GNUNET_PSYC_MessageMethod *
333 meth = (struct GNUNET_PSYC_MessageMethod *) msg;
334 cbs->method_cb (cbs->cls, meth, slicer->message_id,
335 ntohl (meth->flags),
336 nym_get_or_create (&slicer->nym_key),
337 slicer->method_name);
338 break;
339 }
340
341 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
342 {
343 if (NULL == cbs->modifier_cb)
344 break;
345 struct GNUNET_PSYC_MessageModifier *
346 mod = (struct GNUNET_PSYC_MessageModifier *) msg;
347 cbs->modifier_cb (cbs->cls, mod, slicer->message_id,
348 mod->oper, (const char *) &mod[1],
349 (const void *) &mod[1] + ntohs (mod->name_size),
350 ntohs (mod->value_size));
351 break;
352 }
353
354 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
355 {
356 if (NULL == cbs->modifier_cb)
357 break;
358 /* FIXME: concatenate until done */
359 break;
360 }
361
362 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
363 {
364 if (NULL == cbs->data_cb)
365 break;
366 uint64_t data_offset = 0; // FIXME
367 cbs->data_cb (cbs->cls, msg, slicer->message_id,
368 data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg));
369 break;
370 }
371
372 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
373 if (NULL == cbs->eom_cb)
374 break;
375 cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO);
376 break;
377
378 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
379 if (NULL == cbs->eom_cb)
380 break;
381 cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES);
382 break;
383 }
384 return GNUNET_YES;
385}
386
387
388/**
389 * Process an incoming message part and call matching handlers.
390 *
391 * @param cls
392 * Closure.
393 * @param message_id
394 * ID of the message.
395 * @param flags
396 * Flags for the message.
397 * @see enum GNUNET_PSYC_MessageFlags
398 * @param msg
399 * The message part. as it arrived from the network.
400 */
401static void
402slicer_message (void *cls, uint64_t message_id, uint64_t fragment_offset,
403 uint32_t flags, const struct GNUNET_MessageHeader *msg)
404{
405 struct GNUNET_SOCIAL_Slicer *slicer = cls;
406 uint16_t ptype = ntohs (msg->type);
407 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
408 {
409 struct GNUNET_PSYC_MessageMethod *
410 meth = (struct GNUNET_PSYC_MessageMethod *) msg;
411 slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
412 slicer->method_name = GNUNET_malloc (slicer->method_name_size);
413 memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
414 slicer->message_id = message_id;
415 }
416 else
417 {
418 GNUNET_assert (message_id == slicer->message_id);
419 }
420
421 LOG (GNUNET_ERROR_TYPE_WARNING,
422 "Slicer received message of type %u and size %u, "
423 "with ID %" PRIu64 " and method %s\n",
424 ptype, ntohs (msg->size), message_id, slicer->method_name);
425
426 slicer->msg = msg;
427 char *name = GNUNET_malloc (slicer->method_name_size);
428 memcpy (name, slicer->method_name, slicer->method_name_size);
429 do
430 {
431 struct GNUNET_HashCode key;
432 uint16_t name_len = strlen (name);
433 GNUNET_CRYPTO_hash (name, name_len, &key);
434 GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
435 &slicer_handler_notify, slicer);
436 char *p = strrchr (name, '_');
437 if (NULL == p)
438 break;
439 *p = '\0';
440 } while (1);
441 GNUNET_free (name);
442 slicer->msg = NULL;
443
444 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
445 GNUNET_free (slicer->method_name);
446}
121 447
122 448
123/** 449/**
@@ -128,7 +454,9 @@ struct GNUNET_SOCIAL_HistoryLesson
128struct GNUNET_SOCIAL_Slicer * 454struct GNUNET_SOCIAL_Slicer *
129GNUNET_SOCIAL_slicer_create (void) 455GNUNET_SOCIAL_slicer_create (void)
130{ 456{
131 return NULL; 457 struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
458 slicer->handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
459 return slicer;
132} 460}
133 461
134 462
@@ -148,36 +476,338 @@ void
148GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer, 476GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer,
149 const char *method_name, 477 const char *method_name,
150 GNUNET_SOCIAL_MethodCallback method_cb, 478 GNUNET_SOCIAL_MethodCallback method_cb,
479 GNUNET_SOCIAL_ModifierCallback modifier_cb,
480 GNUNET_SOCIAL_DataCallback data_cb,
481 GNUNET_SOCIAL_EndOfMessageCallback eom_cb,
151 void *cls) 482 void *cls)
152{ 483{
484 struct GNUNET_HashCode key;
485 GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
486
487 struct SlicerCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
488 cbs->method_cb = method_cb;
489 cbs->modifier_cb = modifier_cb;
490 cbs->data_cb = data_cb;
491 cbs->eom_cb = eom_cb;
492 cbs->cls = cls;
493
494 GNUNET_CONTAINER_multihashmap_put (slicer->handlers, &key, cbs,
495 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
496}
153 497
498
499int
500slicer_remove_handler (void *cls, const struct GNUNET_HashCode *key, void *value)
501{
502 struct SlicerRemoveClosure *rm_cls = cls;
503 struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer;
504 struct SlicerCallbacks *rm_cbs = &rm_cls->rm_cbs;
505 struct SlicerCallbacks *cbs = value;
506
507 if (cbs->method_cb == rm_cbs->method_cb
508 && cbs->modifier_cb == rm_cbs->modifier_cb
509 && cbs->data_cb == rm_cbs->data_cb
510 && cbs->eom_cb == rm_cbs->eom_cb)
511 {
512 GNUNET_CONTAINER_multihashmap_remove (slicer->handlers, key, cbs);
513 GNUNET_free (cbs);
514 return GNUNET_NO;
515 }
516 return GNUNET_YES;
154} 517}
155 518
156 519
157/** 520/**
158 * Remove a registered method from the try-and-slice instance. 521 * Remove a registered method from the try-and-slice instance.
159 * 522 *
523 * Removes the first matching handler registered with @a method and the given callbacks.
524 *
160 * @param slicer The try-and-slice instance. 525 * @param slicer The try-and-slice instance.
161 * @param method_name Name of the method to remove. 526 * @param method_name Name of the method to remove.
162 * @param method Method handler. 527 * @param method Method handler.
528 *
529 * @return #GNUNET_OK if a method handler was removed,
530 * #GNUNET_NO if no handler matched the given method name and callbacks.
163 */ 531 */
164void 532int
165GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer, 533GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer,
166 const char *method_name, 534 const char *method_name,
167 GNUNET_SOCIAL_MethodCallback method_cb) 535 GNUNET_SOCIAL_MethodCallback method_cb,
536 GNUNET_SOCIAL_ModifierCallback modifier_cb,
537 GNUNET_SOCIAL_DataCallback data_cb,
538 GNUNET_SOCIAL_EndOfMessageCallback eom_cb)
168{ 539{
540 struct GNUNET_HashCode key;
541 GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
542
543 struct SlicerRemoveClosure rm_cls;
544 rm_cls.slicer = slicer;
545 struct SlicerCallbacks *rm_cbs = &rm_cls.rm_cbs;
546 rm_cbs->method_cb = method_cb;
547 rm_cbs->modifier_cb = modifier_cb;
548 rm_cbs->data_cb = data_cb;
549 rm_cbs->eom_cb = eom_cb;
550
551 return
552 (GNUNET_SYSERR
553 == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
554 &slicer_remove_handler,
555 &rm_cls))
556 ? GNUNET_NO
557 : GNUNET_OK;
558}
559
169 560
561int
562slicer_free_handler (void *cls, const struct GNUNET_HashCode *key, void *value)
563{
564 struct SlicerCallbacks *cbs = value;
565 GNUNET_free (cbs);
566 return GNUNET_YES;
170} 567}
171 568
569
172/** 570/**
173 * Destroy a given try-and-slice instance. 571 * Destroy a given try-and-slice instance.
174 * 572 *
175 * @param slicer slicer to destroy 573 * @param slicer
574 * Slicer to destroy
176 */ 575 */
177void 576void
178GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer) 577GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
179{ 578{
579 GNUNET_CONTAINER_multihashmap_iterate (slicer->handlers, &slicer_free_handler,
580 NULL);
581 GNUNET_CONTAINER_multihashmap_destroy (slicer->handlers);
582 GNUNET_free (slicer);
583}
584
585
586static void
587place_send_connect_msg (struct GNUNET_SOCIAL_Place *plc)
588{
589 uint16_t cmsg_size = ntohs (plc->connect_msg->size);
590 struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
591 memcpy (cmsg, plc->connect_msg, cmsg_size);
592 GNUNET_CLIENT_MANAGER_transmit_now (plc->client, cmsg);
593}
594
595
596static void
597place_recv_message_ack (void *cls,
598 struct GNUNET_CLIENT_MANAGER_Connection *client,
599 const struct GNUNET_MessageHeader *msg)
600{
601 struct GNUNET_SOCIAL_Place *
602 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
603 GNUNET_PSYC_transmit_got_ack (plc->tmit);
604}
605
606
607static void
608place_recv_message (void *cls,
609 struct GNUNET_CLIENT_MANAGER_Connection *client,
610 const struct GNUNET_MessageHeader *msg)
611{
612 struct GNUNET_SOCIAL_Place *
613 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
614 GNUNET_PSYC_receive_message (plc->recv,
615 (const struct GNUNET_PSYC_MessageHeader *) msg);
616}
617
618
619static void
620place_recv_disconnect (void *cls,
621 struct GNUNET_CLIENT_MANAGER_Connection *client,
622 const struct GNUNET_MessageHeader *msg)
623{
624 struct GNUNET_SOCIAL_Place *
625 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
626
627 GNUNET_CLIENT_MANAGER_reconnect (client);
628 place_send_connect_msg (plc);
629}
630
631
632static void
633host_recv_enter_ack (void *cls,
634 struct GNUNET_CLIENT_MANAGER_Connection *client,
635 const struct GNUNET_MessageHeader *msg)
636{
637 struct GNUNET_SOCIAL_Host *
638 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
639 sizeof (struct GNUNET_SOCIAL_Place));
640
641 struct GNUNET_PSYC_CountersResultMessage *
642 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
643 if (NULL != hst->enter_cb)
644 hst->enter_cb (hst->cb_cls, GNUNET_ntohll (cres->max_message_id));
645}
646
647
648static void
649host_recv_enter_request (void *cls,
650 struct GNUNET_CLIENT_MANAGER_Connection *client,
651 const struct GNUNET_MessageHeader *msg)
652{
653 struct GNUNET_SOCIAL_Host *
654 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
655 sizeof (struct GNUNET_SOCIAL_Place));
656 if (NULL == hst->answer_door_cb)
657 return;
658
659 const char *method_name = NULL;
660 struct GNUNET_ENV_Environment *env = NULL;
661 const void *data = NULL;
662 uint16_t data_size = 0;
663
664 const struct GNUNET_PSYC_JoinRequestMessage *
665 req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
666 const struct GNUNET_PSYC_Message *entry_msg = NULL;
667 if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size))
668 {
669 entry_msg = (struct GNUNET_PSYC_Message *) &req[1];
670 LOG (GNUNET_ERROR_TYPE_DEBUG,
671 "Received entry_msg of type %u and size %u.\n",
672 ntohs (entry_msg->header.type), ntohs (entry_msg->header.size));
673
674 env = GNUNET_ENV_environment_create ();
675 if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_msg, &method_name, env,
676 &data, &data_size))
677 {
678 LOG (GNUNET_ERROR_TYPE_WARNING,
679 "Ignoring invalid entry request from nym %s.\n",
680 GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key));
681 GNUNET_break_op (0);
682 GNUNET_ENV_environment_destroy (env);
683 return;
684 }
685 }
686
687 struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_key);
688 hst->answer_door_cb (hst->cb_cls, nym, method_name, env,
689 data_size, data);
690
691 if (NULL != env)
692 GNUNET_ENV_environment_destroy (env);
693}
694
695
696static void
697guest_recv_enter_ack (void *cls,
698 struct GNUNET_CLIENT_MANAGER_Connection *client,
699 const struct GNUNET_MessageHeader *msg)
700{
701 struct GNUNET_SOCIAL_Guest *
702 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
703 sizeof (struct GNUNET_SOCIAL_Place));
704
705 struct GNUNET_PSYC_CountersResultMessage *
706 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
707 if (NULL != gst->enter_cb)
708 gst->enter_cb (gst->cb_cls, ntohl (cres->result_code),
709 GNUNET_ntohll (cres->max_message_id));
710}
711
712
713static void
714guest_recv_join_decision (void *cls,
715 struct GNUNET_CLIENT_MANAGER_Connection *client,
716 const struct GNUNET_MessageHeader *msg)
717{
718 struct GNUNET_SOCIAL_Guest *
719 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
720 sizeof (struct GNUNET_SOCIAL_Place));
721 const struct GNUNET_PSYC_JoinDecisionMessage *
722 dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg;
723
724 struct GNUNET_PSYC_Message *pmsg = NULL;
725 if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
726 pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1];
727
728 if (NULL != gst->entry_dcsn_cb)
729 gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg);
730}
731
732
733static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
734{
735 { &host_recv_enter_ack, NULL,
736 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
737 sizeof (struct CountersResult), GNUNET_NO },
738
739 { &host_recv_enter_request, NULL,
740 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
741 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
742
743 { &place_recv_message, NULL,
744 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
745 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
746
747 { &place_recv_message_ack, NULL,
748 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
749 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
750
751 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
752
753 { NULL, NULL, 0, 0, GNUNET_NO }
754};
755
756
757static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
758{
759 { &guest_recv_enter_ack, NULL,
760 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
761 sizeof (struct CountersResult), GNUNET_NO },
762
763 { &host_recv_enter_request, NULL,
764 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
765 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
766
767 { &place_recv_message, NULL,
768 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
769 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
770
771 { &place_recv_message_ack, NULL,
772 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
773 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
774
775 { &guest_recv_join_decision, NULL,
776 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
777 sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES },
778
779 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
780
781 { NULL, NULL, 0, 0, GNUNET_NO }
782};
783
784
785static void
786place_cleanup (struct GNUNET_SOCIAL_Place *plc)
787{
788 GNUNET_PSYC_transmit_destroy (plc->tmit);
789 GNUNET_PSYC_receive_destroy (plc->recv);
790 GNUNET_free (plc->connect_msg);
791 if (NULL != plc->disconnect_cb)
792 plc->disconnect_cb (plc->disconnect_cls);
793}
794
795
796static void
797host_cleanup (void *cls)
798{
799 struct GNUNET_SOCIAL_Host *hst = cls;
800 place_cleanup (&hst->plc);
801 GNUNET_free (hst);
802}
803
180 804
805static void
806guest_cleanup (void *cls)
807{
808 struct GNUNET_SOCIAL_Guest *gst = cls;
809 place_cleanup (&gst->plc);
810 GNUNET_free (gst);
181} 811}
182 812
183 813
@@ -187,46 +817,179 @@ GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
187 * A place is created upon first entering, and it is active until permanently 817 * A place is created upon first entering, and it is active until permanently
188 * left using GNUNET_SOCIAL_host_leave(). 818 * left using GNUNET_SOCIAL_host_leave().
189 * 819 *
190 * @param cfg Configuration to contact the social service. 820 * @param cfg
191 * @param place_keyfile File with the private-public key pair of the place, 821 * Configuration to contact the social service.
192 * created if the file does not exist; pass NULL for ephemeral places. 822 * @param ego
193 * @param policy Policy specifying entry and history restrictions of the place. 823 * Identity of the host.
194 * @param ego Identity of the host. 824 * @param place_key
195 * @param slicer Slicer to handle incoming messages. 825 * Private-public key pair of the place.
196 * @param listener_cb Function to handle new nyms that want to enter. 826 * NULL for ephemeral places.
197 * @param farewell_cb Function to handle departing nyms. 827 * @param policy
198 * @param cls Closure for @a listener_cb and @a farewell_cb. 828 * Policy specifying entry and history restrictions for the place.
829 * @param slicer
830 * Slicer to handle incoming messages.
831 * @param answer_door_cb
832 * Function to handle new nyms that want to enter.
833 * @param farewell_cb
834 * Function to handle departing nyms.
835 * @param cls
836 * Closure for the callbacks.
199 * 837 *
200 * @return Handle for the host. 838 * @return Handle for the host.
201 */ 839 */
202struct GNUNET_SOCIAL_Host * 840struct GNUNET_SOCIAL_Host *
203GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, 841GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
204 const char *place_keyfile, 842 const struct GNUNET_IDENTITY_Ego *ego,
843 const struct GNUNET_CRYPTO_EddsaPrivateKey *place_key,
205 enum GNUNET_PSYC_Policy policy, 844 enum GNUNET_PSYC_Policy policy,
206 struct GNUNET_IDENTITY_Ego *ego,
207 struct GNUNET_SOCIAL_Slicer *slicer, 845 struct GNUNET_SOCIAL_Slicer *slicer,
208 GNUNET_SOCIAL_AnswerDoorCallback listener_cb, 846 GNUNET_SOCIAL_HostEnterCallback enter_cb,
847 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
209 GNUNET_SOCIAL_FarewellCallback farewell_cb, 848 GNUNET_SOCIAL_FarewellCallback farewell_cb,
210 void *cls) 849 void *cls)
211{ 850{
212 return NULL; 851 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
852 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
853 struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req));
854
855 if (NULL != place_key)
856 {
857 hst->place_key = *place_key;
858 }
859 else
860 {
861 struct GNUNET_CRYPTO_EddsaPrivateKey *
862 ephemeral_key = GNUNET_CRYPTO_eddsa_key_create ();
863 hst->place_key = *ephemeral_key;
864 GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key);
865 GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key);
866 GNUNET_free (ephemeral_key);
867 }
868 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
869
870 req->header.size = htons (sizeof (*req));
871 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
872 req->policy = policy;
873 req->place_key = hst->place_key;
874 req->host_key = plc->ego_key;
875
876 plc->connect_msg = (struct GNUNET_MessageHeader *) req;
877 plc->cfg = cfg;
878 plc->is_host = GNUNET_YES;
879 plc->slicer = slicer;
880
881 hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
882 hst->enter_cb = enter_cb;
883 hst->answer_door_cb = answer_door_cb;
884 hst->cb_cls = cls;
885
886 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers);
887 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
888
889 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
890 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
891
892 place_send_connect_msg (plc);
893 return hst;
213} 894}
214 895
215 896
216/** 897/**
217 * Admit @a nym to the place. 898 * Enter a place as host.
218 * 899 *
219 * The @a nym reference will remain valid until either the @a host or @a nym 900 * A place is created upon first entering, and it is active until permanently
220 * leaves the place. 901 * left using GNUNET_SOCIAL_host_leave().
221 * 902 *
222 * @param host Host of the place. 903 * @param cfg
223 * @param nym Handle for the entity that wants to enter. 904 * Configuration to contact the social service.
905 * @param ego
906 * Identity of the host.
907 * @param gns_name
908 * GNS name in the zone of the @a ego that contains the
909 * public key of the place in a PLACE record.
910 * @param policy
911 * Policy specifying entry and history restrictions for the place.
912 * @param slicer
913 * Slicer to handle incoming messages.
914 * @param answer_door_cb
915 * Function to handle new nyms that want to enter.
916 * @param farewell_cb
917 * Function to handle departing nyms.
918 * @param cls
919 * Closure for the callbacks.
920 *
921 * @return Handle for the host.
224 */ 922 */
225void 923struct GNUNET_SOCIAL_Host *
226GNUNET_SOCIAL_host_admit (struct GNUNET_SOCIAL_Host *host, 924GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
227 struct GNUNET_SOCIAL_Nym *nym) 925 struct GNUNET_IDENTITY_Ego *ego,
926 const char *gns_name,
927 enum GNUNET_PSYC_Policy policy,
928 struct GNUNET_SOCIAL_Slicer *slicer,
929 GNUNET_SOCIAL_HostEnterCallback enter_cb,
930 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
931 GNUNET_SOCIAL_FarewellCallback farewell_cb,
932 void *cls)
228{ 933{
934 struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {};
229 935
936 /* FIXME:
937 * 1. get public key by looking up PLACE entry under gns_name
938 * in the zone of the ego.
939 * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH
940 */
941
942 return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer,
943 enter_cb, answer_door_cb, farewell_cb, cls);
944}
945
946
947/**
948 * Decision whether to admit @a nym into the place or refuse entry.
949 *
950 * @param hst
951 * Host of the place.
952 * @param nym
953 * Handle for the entity that wanted to enter.
954 * @param is_admitted
955 * #GNUNET_YES if @a nym is admitted,
956 * #GNUNET_NO if @a nym is refused entry,
957 * #GNUNET_SYSERR if we cannot answer the request.
958 * @param method_name
959 * Method name for the rejection message.
960 * @param env
961 * Environment containing variables for the message, or NULL.
962 * @param data
963 * Data for the rejection message to send back.
964 * @param data_size
965 * Number of bytes in @a data for method.
966 * @return #GNUNET_OK on success,
967 * #GNUNET_SYSERR if the message is too large.
968 */
969int
970GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
971 struct GNUNET_SOCIAL_Nym *nym,
972 int is_admitted,
973 const struct GNUNET_PSYC_Message *entry_resp)
974{
975 struct GNUNET_PSYC_JoinDecisionMessage *dcsn;
976 uint16_t entry_resp_size
977 = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0;
978
979 if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size)
980 return GNUNET_SYSERR;
981
982 dcsn = GNUNET_malloc (sizeof (*dcsn) + entry_resp_size);
983 dcsn->header.size = htons (sizeof (*dcsn) + entry_resp_size);
984 dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION);
985 dcsn->is_admitted = htonl (is_admitted);
986 dcsn->slave_key = nym->pub_key;
987
988 if (0 < entry_resp_size)
989 memcpy (&dcsn[1], entry_resp, entry_resp_size);
990
991 GNUNET_CLIENT_MANAGER_transmit (hst->plc.client, &dcsn->header);
992 return GNUNET_OK;
230} 993}
231 994
232 995
@@ -249,63 +1012,60 @@ GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *host,
249 1012
250 1013
251/** 1014/**
252 * Refuse @a nym entry into the place. 1015 * Get the public key of a @a nym.
253 * 1016 *
254 * @param host Host of the place. 1017 * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
255 * @param nym Handle for the entity that wanted to enter. 1018 *
256 * @param method_name Method name for the rejection message. 1019 * @param nym Pseudonym to map to a cryptographic identifier.
257 * @param env Environment containing variables for the message, or NULL. 1020 * @param[out] nym_key Set to the public key of the nym.
258 * @param data Data for the rejection message to send back.
259 * @param data_size Number of bytes in @a data for method.
260 */ 1021 */
261void 1022struct GNUNET_CRYPTO_EcdsaPublicKey *
262GNUNET_SOCIAL_host_refuse_entry (struct GNUNET_SOCIAL_Host *host, 1023GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym)
263 struct GNUNET_SOCIAL_Nym *nym,
264 const char *method_name,
265 const struct GNUNET_ENV_Environment *env,
266 const void *data,
267 size_t data_size)
268{ 1024{
269 1025 return &nym->pub_key;
270} 1026}
271 1027
272 1028
273/** 1029/**
274 * Get the public key of a @a nym. 1030 * Obtain the private-public key pair of the hosted place.
275 * 1031 *
276 * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name(). 1032 * The public part is suitable for storing in GNS within a PLACE record,
1033 * along with peer IDs to join at.
277 * 1034 *
278 * @param nym Pseudonym to map to a cryptographic identifier. 1035 * @param host
279 * @param[out] nym_key Set to the public key of the nym. 1036 * Host of the place.
1037 *
1038 * @return Private-public key pair of the hosted place.
280 */ 1039 */
281void 1040const struct GNUNET_CRYPTO_EddsaPrivateKey *
282GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym, 1041GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst)
283 struct GNUNET_CRYPTO_EddsaPublicKey *nym_key) 1042{
1043 return &hst->place_key;
1044}
1045
1046
1047static void
1048namestore_result_host_advertise (void *cls, int32_t success, const char *emsg)
284{ 1049{
285 1050
286} 1051}
287 1052
288 1053
289/** 1054/**
290 * Obtain the private-public key pair of the host. 1055 * Connected to core service.
291 *
292 * @param host Host to get the key of.
293 * @param[out] host_key Set to the private-public key pair of the host. The
294 * public part is suitable for storing in GNS within a "PLACE"
295 * record, along with peer IDs to join at.
296 */ 1056 */
297void 1057static void
298GNUNET_SOCIAL_host_get_key (struct GNUNET_SOCIAL_Host *host, 1058core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
299 struct GNUNET_CRYPTO_EddsaPrivateKey *host_key)
300{ 1059{
301 1060 this_peer = *my_identity;
1061 // FIXME
302} 1062}
303 1063
304 1064
305/** 1065/**
306 * Advertise the place in the GNS zone of the @e ego of the @a host. 1066 * Advertise the place in the GNS zone of the @e ego of the @a host.
307 * 1067 *
308 * @param host Host of the place. 1068 * @param hst Host of the place.
309 * @param name The name for the PLACE record to put in the zone. 1069 * @param name The name for the PLACE record to put in the zone.
310 * @param peer_count Number of elements in the @a peers array. 1070 * @param peer_count Number of elements in the @a peers array.
311 * @param peers List of peers in the PLACE record that can be used to send join 1071 * @param peers List of peers in the PLACE record that can be used to send join
@@ -314,14 +1074,37 @@ GNUNET_SOCIAL_host_get_key (struct GNUNET_SOCIAL_Host *host,
314 * @param password Password used to encrypt the record. 1074 * @param password Password used to encrypt the record.
315 */ 1075 */
316void 1076void
317GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host, 1077GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst,
318 const char *name, 1078 const char *name,
319 size_t peer_count, 1079 size_t peer_count,
320 const struct GNUNET_PeerIdentity *peers, 1080 const struct GNUNET_PeerIdentity *peers,
321 struct GNUNET_TIME_Relative expiration_time, 1081 struct GNUNET_TIME_Relative expiration_time,
322 const char *password) 1082 const char *password)
323{ 1083{
324 1084 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1085 if (NULL == namestore)
1086 namestore = GNUNET_NAMESTORE_connect (plc->cfg);
1087 if (NULL == core)
1088 core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL,
1089 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1090
1091 struct GNUNET_GNSRECORD_Data rd = { 0 };
1092 rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
1093 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1094 rd.expiration_time
1095 = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, 1).rel_value_us;
1096
1097 struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec));
1098 rec->place_key = plc->pub_key;
1099 rec->origin = this_peer;
1100 rec->relay_count = htons (0); // FIXME
1101
1102 rd.data_size = sizeof (*rec);
1103 rd.data = rec;
1104
1105 GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key,
1106 name, 1, &rd, namestore_result_host_advertise,
1107 hst);
325} 1108}
326 1109
327 1110
@@ -342,26 +1125,43 @@ GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *host,
342 * @return NULL on error (announcement already in progress?). 1125 * @return NULL on error (announcement already in progress?).
343 */ 1126 */
344struct GNUNET_SOCIAL_Announcement * 1127struct GNUNET_SOCIAL_Announcement *
345GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *host, 1128GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
346 const char *method_name, 1129 const char *method_name,
347 const struct GNUNET_ENV_Environment *env, 1130 const struct GNUNET_ENV_Environment *env,
348 GNUNET_CONNECTION_TransmitReadyNotify notify, 1131 GNUNET_PSYC_TransmitNotifyData notify_data,
349 void *notify_cls, 1132 void *notify_data_cls,
350 enum GNUNET_SOCIAL_AnnounceFlags flags) 1133 enum GNUNET_SOCIAL_AnnounceFlags flags)
351{ 1134{
352 return NULL; 1135 if (GNUNET_OK ==
1136 GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
1137 NULL, notify_data, notify_data_cls, flags));
1138 return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit;
1139}
1140
1141
1142/**
1143 * Resume transmitting announcement.
1144 *
1145 * @param a
1146 * The announcement to resume.
1147 */
1148void
1149GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a)
1150{
1151 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a);
353} 1152}
354 1153
355 1154
356/** 1155/**
357 * Cancel announcement. 1156 * Cancel announcement.
358 * 1157 *
359 * @param a The announcement to cancel. 1158 * @param a
1159 * The announcement to cancel.
360 */ 1160 */
361void 1161void
362GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a) 1162GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a)
363{ 1163{
364 1164 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a);
365} 1165}
366 1166
367 1167
@@ -375,9 +1175,9 @@ GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a)
375 * @return Handle for the hosted place, valid as long as @a host is valid. 1175 * @return Handle for the hosted place, valid as long as @a host is valid.
376 */ 1176 */
377struct GNUNET_SOCIAL_Place * 1177struct GNUNET_SOCIAL_Place *
378GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *host) 1178GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst)
379{ 1179{
380 return NULL; 1180 return &hst->plc;
381} 1181}
382 1182
383 1183
@@ -390,22 +1190,65 @@ GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *host)
390 * @param keep_active Keep the place active after last host disconnected. 1190 * @param keep_active Keep the place active after last host disconnected.
391 */ 1191 */
392void 1192void
393GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active) 1193GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
1194 int keep_active,
1195 GNUNET_ContinuationCallback leave_cb,
1196 void *leave_cls)
394{ 1197{
1198 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1199
1200 /* FIXME: send msg to service */
1201
1202 plc->is_disconnecting = GNUNET_YES;
1203 plc->disconnect_cb = leave_cb;
1204 plc->disconnect_cls = leave_cls;
395 1205
1206 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1207 &host_cleanup, hst);
396} 1208}
397 1209
398 1210
1211static struct GuestEnterRequest *
1212guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key,
1213 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
1214 const struct GNUNET_PeerIdentity *origin,
1215 size_t relay_count,
1216 const struct GNUNET_PeerIdentity *relays,
1217 const struct GNUNET_PSYC_Message *join_msg)
1218{
1219 uint16_t join_msg_size = ntohs (join_msg->header.size);
1220 uint16_t relay_size = relay_count * sizeof (*relays);
1221
1222 struct GuestEnterRequest *
1223 req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size);
1224
1225 req->header.size = htons (sizeof (*req) + relay_size + join_msg_size);
1226 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
1227 req->place_key = *place_key;
1228 req->guest_key = *guest_key;
1229 req->origin = *origin;
1230 req->relay_count = relay_count;
1231
1232 uint16_t p = sizeof (*req);
1233 if (0 < relay_size)
1234 {
1235 memcpy ((char *) req + p, relays, relay_size);
1236 p += relay_size;
1237 }
1238
1239 memcpy ((char *) req + p, join_msg, join_msg_size);
1240 return req;
1241}
1242
399/** 1243/**
400 * Request entry to a place as a guest. 1244 * Request entry to a place as a guest.
401 * 1245 *
402 * @param cfg Configuration to contact the social service. 1246 * @param cfg Configuration to contact the social service.
403 * @param ego Identity of the guest. 1247 * @param ego Identity of the guest.
404 * @param address GNS name of the place to enter. Either in the form of 1248 * @param crypto_address Public key of the place to enter.
405 * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to 1249 * @param origin Peer identity of the origin of the underlying multicast group.
406 * the 'PLACE' record of the empty label ("+") in the GNS zone with the 1250 * @param relay_count Number of elements in the @a relays array.
407 * nym's public key 'NYMPUBKEY', and can be used to request entry to a 1251 * @param relays Relays for the underlying multicast group.
408 * pseudonym's place directly.
409 * @param method_name Method name for the message. 1252 * @param method_name Method name for the message.
410 * @param env Environment containing variables for the message, or NULL. 1253 * @param env Environment containing variables for the message, or NULL.
411 * @param data Payload for the message to give to the enter callback. 1254 * @param data Payload for the message to give to the enter callback.
@@ -416,26 +1259,132 @@ GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *host, int keep_active)
416 */ 1259 */
417struct GNUNET_SOCIAL_Guest * 1260struct GNUNET_SOCIAL_Guest *
418GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, 1261GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
419 struct GNUNET_IDENTITY_Ego *ego, 1262 const struct GNUNET_IDENTITY_Ego *ego,
420 char *address, 1263 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
421 const char *method_name, 1264 const struct GNUNET_PeerIdentity *origin,
422 const struct GNUNET_ENV_Environment *env, 1265 uint32_t relay_count,
423 const void *data, 1266 const struct GNUNET_PeerIdentity *relays,
424 size_t data_size, 1267 const struct GNUNET_PSYC_Message *entry_msg,
425 struct GNUNET_SOCIAL_Slicer *slicer) 1268 struct GNUNET_SOCIAL_Slicer *slicer,
1269 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
1270 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
1271 void *cls)
426{ 1272{
427 return NULL; 1273 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1274 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1275
1276 struct GuestEnterRequest *
1277 req = guest_enter_request_create (&plc->ego_key, place_key, origin,
1278 relay_count, relays, entry_msg);
1279 plc->connect_msg = &req->header;
1280 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1281 plc->pub_key = *place_key;
1282 plc->cfg = cfg;
1283 plc->is_host = GNUNET_YES;
1284 plc->slicer = slicer;
1285
1286 gst->enter_cb = local_enter_cb;
1287 gst->entry_dcsn_cb = entry_dcsn_cb;
1288 gst->cb_cls = cls;
1289
1290 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1291 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1292
1293 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1294 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
1295
1296 place_send_connect_msg (plc);
1297 return gst;
1298}
1299
1300
1301/**
1302 * Result of a GNS name lookup for entering a place.
1303 *
1304 * @see GNUNET_SOCIAL_guest_enter_by_name
1305 */
1306static void
1307gns_result_guest_enter (void *cls, uint32_t rd_count,
1308 const struct GNUNET_GNSRECORD_Data *rd)
1309{
1310 struct GNUNET_SOCIAL_Guest *gst = cls;
1311 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1312
1313 const struct GNUNET_GNSRECORD_PlaceData *
1314 rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
1315
1316 if (0 == rd_count)
1317 {
1318 if (NULL != gst->enter_cb)
1319 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1320 return;
1321 }
1322
1323
1324 if (rd->data_size < sizeof (*rec))
1325 {
1326 GNUNET_break_op (0);
1327 if (NULL != gst->enter_cb)
1328 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1329 return;
1330 }
1331
1332 struct GuestEnterRequest *
1333 req = (struct GuestEnterRequest *) plc->connect_msg;
1334 uint16_t req_size = ntohs (req->header.size);
1335
1336 struct GNUNET_PeerIdentity *relays = NULL;
1337 uint16_t relay_count = ntohs (rec->relay_count);
1338
1339 if (0 < relay_count)
1340 {
1341 uint16_t relay_size = relay_count * sizeof (struct GNUNET_PeerIdentity);
1342 struct GuestEnterRequest *
1343 req2 = GNUNET_malloc (req_size + relay_size);
1344
1345 req2->header.size = htons (req_size + relay_size);
1346 req2->header.type = req->header.type;
1347 req2->guest_key = req->guest_key;
1348
1349 uint16_t p = sizeof (*req);
1350 if (0 < relay_size)
1351 {
1352 memcpy ((char *) req2 + p, relays, relay_size);
1353 p += relay_size;
1354 }
1355
1356 memcpy ((char *) req + p, &req[1], req_size - sizeof (*req));
1357
1358 plc->connect_msg = &req2->header;
1359 GNUNET_free (req);
1360 req = req2;
1361 }
1362
1363 req->place_key = rec->place_key;
1364 req->origin = rec->origin;
1365 req->relay_count = rec->relay_count;
1366 memcpy (&req[1], &rec[1],
1367 ntohl (rec->relay_count) * sizeof (struct GNUNET_PeerIdentity));
1368
1369 plc->connect_msg = &req->header;
1370 plc->pub_key = req->place_key;
1371
1372 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1373 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc);
1374
1375 place_send_connect_msg (plc);
428} 1376}
429 1377
430/** 1378/**
431 * Request entry to a place as a guest. 1379 * Request entry to a place as a guest.
432 * 1380 *
433 * @param cfg Configuration to contact the social service. 1381 * @param cfg Configuration to contact the social service.
434 * @param ego Identity of the guest. 1382 * @param ego Identity of the guest.
435 * @param crypto_address Public key of the place to enter. 1383 * @param address GNS name of the place to enter. Either in the form of
436 * @param origin Peer identity of the origin of the underlying multicast group. 1384 * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to
437 * @param relay_count Number of elements in the @a relays array. 1385 * the 'PLACE' record of the empty label ("+") in the GNS zone with the
438 * @param relays Relays for the underlying multicast group. 1386 * nym's public key 'NYMPUBKEY', and can be used to request entry to a
1387 * pseudonym's place directly.
439 * @param method_name Method name for the message. 1388 * @param method_name Method name for the message.
440 * @param env Environment containing variables for the message, or NULL. 1389 * @param env Environment containing variables for the message, or NULL.
441 * @param data Payload for the message to give to the enter callback. 1390 * @param data Payload for the message to give to the enter callback.
@@ -445,41 +1394,75 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
445 * @return NULL on errors, otherwise handle for the guest. 1394 * @return NULL on errors, otherwise handle for the guest.
446 */ 1395 */
447struct GNUNET_SOCIAL_Guest * 1396struct GNUNET_SOCIAL_Guest *
448GNUNET_SOCIAL_guest_enter2 (const struct GNUNET_CONFIGURATION_Handle *cfg, 1397GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
449 struct GNUNET_IDENTITY_Ego *ego, 1398 struct GNUNET_IDENTITY_Ego *ego,
450 struct GNUNET_CRYPTO_EddsaPublicKey *crypto_address, 1399 char *gns_name,
451 struct GNUNET_PeerIdentity *origin, 1400 const struct GNUNET_PSYC_Message *join_msg,
452 size_t relay_count, 1401 struct GNUNET_SOCIAL_Slicer *slicer,
453 struct GNUNET_PeerIdentity *relays, 1402 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
454 const char *method_name, 1403 GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb,
455 const struct GNUNET_ENV_Environment *env, 1404 void *cls)
456 const void *data,
457 size_t data_size,
458 struct GNUNET_SOCIAL_Slicer *slicer)
459{ 1405{
460 return NULL; 1406 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1407 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1408
1409 gst->enter_cb = local_enter_cb;
1410 gst->cb_cls = cls;
1411
1412 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1413 plc->cfg = cfg;
1414 plc->is_host = GNUNET_NO;
1415 plc->slicer = slicer;
1416
1417 struct GuestEnterRequest *
1418 req = guest_enter_request_create (&plc->ego_key, NULL, NULL, 0, NULL,
1419 join_msg);
1420 plc->connect_msg = &req->header;
1421
1422 /* FIXME: get the public key of the origin and relays
1423 * by looking up the PLACE record of gns_name.
1424 */
1425 if (NULL == gns)
1426 gns = GNUNET_GNS_connect (cfg);
1427
1428 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1429 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1430
1431 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
1432 GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key);
1433 GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key,
1434 GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT,
1435 NULL, gns_result_guest_enter, gst);
1436
1437 return gst;
461} 1438}
462 1439
463 1440
464/** 1441/**
465 * Talk to the host of the place. 1442 * Talk to the host of the place.
466 * 1443 *
467 * @param place Place where we want to talk to the host. 1444 * @param place
468 * @param method_name Method to invoke on the host. 1445 * Place where we want to talk to the host.
469 * @param env Environment containing variables for the message, or NULL. 1446 * @param method_name
470 * @param notify Function to use to get the payload for the method. 1447 * Method to invoke on the host.
471 * @param notify_cls Closure for @a notify. 1448 * @param env
472 * @param flags Flags for the message being sent. 1449 * Environment containing variables for the message, or NULL.
1450 * @param notify_data
1451 * Function to use to get the payload for the method.
1452 * @param notify_data_cls
1453 * Closure for @a notify_data.
1454 * @param flags
1455 * Flags for the message being sent.
473 * 1456 *
474 * @return NULL if we are already trying to talk to the host, 1457 * @return NULL if we are already trying to talk to the host,
475 * otherwise handle to cancel the request. 1458 * otherwise handle to cancel the request.
476 */ 1459 */
477struct GNUNET_SOCIAL_TalkRequest * 1460struct GNUNET_SOCIAL_TalkRequest *
478GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Place *place, 1461GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *guest,
479 const char *method_name, 1462 const char *method_name,
480 const struct GNUNET_ENV_Environment *env, 1463 const struct GNUNET_ENV_Environment *env,
481 GNUNET_CONNECTION_TransmitReadyNotify notify, 1464 GNUNET_PSYC_TransmitNotifyData notify_data,
482 void *notify_cls, 1465 void *notify_data_cls,
483 enum GNUNET_SOCIAL_TalkFlags flags) 1466 enum GNUNET_SOCIAL_TalkFlags flags)
484{ 1467{
485 return NULL; 1468 return NULL;
@@ -487,14 +1470,28 @@ GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Place *place,
487 1470
488 1471
489/** 1472/**
1473 * Resume talking to the host of the place.
1474 *
1475 * @param tr
1476 * Talk request to resume.
1477 */
1478void
1479GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr)
1480{
1481 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr);
1482}
1483
1484
1485/**
490 * Cancel talking to the host of the place. 1486 * Cancel talking to the host of the place.
491 * 1487 *
492 * @param tr Talk request to cancel. 1488 * @param tr
1489 * Talk request to cancel.
493 */ 1490 */
494void 1491void
495GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr) 1492GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
496{ 1493{
497 1494 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr);
498} 1495}
499 1496
500 1497
@@ -507,9 +1504,21 @@ GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
507 * @param keep_active Keep place active after last application disconnected. 1504 * @param keep_active Keep place active after last application disconnected.
508 */ 1505 */
509void 1506void
510GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Place *place, int keep_active) 1507GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
1508 int keep_active,
1509 GNUNET_ContinuationCallback leave_cb,
1510 void *leave_cls)
511{ 1511{
1512 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1513
1514 /* FIXME: send msg to service */
1515
1516 plc->is_disconnecting = GNUNET_YES;
1517 plc->disconnect_cb = leave_cb;
1518 plc->disconnect_cls = leave_cls;
512 1519
1520 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1521 &guest_cleanup, gst);
513} 1522}
514 1523
515 1524
@@ -523,9 +1532,9 @@ GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Place *place, int keep_active)
523 * @return Handle for the place, valid as long as @a guest is valid. 1532 * @return Handle for the place, valid as long as @a guest is valid.
524 */ 1533 */
525struct GNUNET_SOCIAL_Place * 1534struct GNUNET_SOCIAL_Place *
526GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Host *guest) 1535GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst)
527{ 1536{
528 return NULL; 1537 return &gst->plc;
529} 1538}
530 1539
531 1540
@@ -671,6 +1680,4 @@ GNUNET_SOCIAL_place_look_at (struct GNUNET_SOCIAL_Place *place,
671} 1680}
672 1681
673 1682
674
675
676/* end of social_api.c */ 1683/* end of social_api.c */
diff --git a/src/social/test_social.c b/src/social/test_social.c
index 053e347d1..340c4482a 100644
--- a/src/social/test_social.c
+++ b/src/social/test_social.c
@@ -17,7 +17,6 @@
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA. 18 * Boston, MA 02111-1307, USA.
19 */ 19 */
20
21/** 20/**
22 * @file social/test_social.c 21 * @file social/test_social.c
23 * @brief Tests for the Social API. 22 * @brief Tests for the Social API.
@@ -32,32 +31,132 @@
32#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
33#include "gnunet_testing_lib.h" 32#include "gnunet_testing_lib.h"
34#include "gnunet_env_lib.h" 33#include "gnunet_env_lib.h"
34#include "gnunet_psyc_util_lib.h"
35#include "gnunet_social_service.h" 35#include "gnunet_social_service.h"
36#include "gnunet_core_service.h"
37#include "gnunet_identity_service.h"
36 38
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) 39#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
38 40
39#define DEBUG_SERVICE 0 41#define DEBUG_SERVICE 0
42#define DATA2ARG(data) data, sizeof (data)
40 43
41/** 44/**
42 * Return value from 'main'. 45 * Return value from 'main'.
43 */ 46 */
44static int res; 47int res;
45
46static const struct GNUNET_CONFIGURATION_Handle *cfg;
47 48
48/** 49/**
49 * Handle for task for timeout termination. 50 * Handle for task for timeout termination.
50 */ 51 */
51static GNUNET_SCHEDULER_TaskIdentifier end_badly_task; 52GNUNET_SCHEDULER_TaskIdentifier end_badly_task;
53
54const struct GNUNET_CONFIGURATION_Handle *cfg;
55
56struct GNUNET_CORE_Handle *core;
57struct GNUNET_PeerIdentity this_peer;
58
59struct GNUNET_IDENTITY_Handle *id;
60
61const struct GNUNET_IDENTITY_Ego *host_ego;
62const struct GNUNET_IDENTITY_Ego *guest_ego;
63
64const char *host_name = "Host One";
65const char *guest_name = "Guest One";
66
67struct GNUNET_CRYPTO_EddsaPrivateKey *place_key;
68struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key;
69
70struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
71struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key;
72
73struct GNUNET_SOCIAL_Slicer *host_slicer;
74struct GNUNET_SOCIAL_Slicer *guest_slicer;
75
76struct GNUNET_SOCIAL_Host *hst;
77struct GNUNET_SOCIAL_Guest *gst;
78
79struct GuestEnterMessage
80{
81 struct GNUNET_PSYC_Message *msg;
82 const char *method_name;
83 struct GNUNET_ENV_Environment *env;
84 void *data;
85 uint16_t data_size;
86} guest_enter_msg;
87
88struct TransmitClosure
89{
90 struct GNUNET_SOCIAL_Announcement *host_ann;
91 struct GNUNET_SOCIAL_TalkRequest *guest_talk;
92 struct GNUNET_ENV_Environment *env;
93 char *data[16];
94 uint8_t data_delay[16];
95 uint8_t data_count;
96 uint8_t paused;
97 uint8_t n;
98} tmit;
99
100uint8_t join_req_count;
101struct GNUNET_PSYC_Message *join_resp;
102
103enum
104{
105 TEST_NONE = 0,
106 TEST_HOST_ANSWER_DOOR_REFUSE = 1,
107 TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 2,
108 TEST_HOST_ANSWER_DOOR_ADMIT = 3,
109 TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 4,
110 TEST_HOST_ANNOUNCE = 5,
111 TEST_HOST_ANNOUNCE_END = 6,
112 TEST_GUEST_TALK = 7,
113 TEST_GUEST_TALK_END = 8,
114 TEST_GUEST_LEAVE = 9,
115 TEST_HOST_LEAVE = 10,
116} test;
117
118
119void
120guest_enter ();
121
122
123void
124guest_talk ();
125
126
127void
128host_announce2 ();
52 129
53 130
54/** 131/**
55 * Clean up all resources used. 132 * Clean up all resources used.
56 */ 133 */
57static void 134void
58cleanup () 135cleanup ()
59{ 136{
137 if (NULL != core)
138 {
139 GNUNET_CORE_disconnect (core);
140 core = NULL;
141 }
60 142
143 if (NULL != id)
144 {
145 GNUNET_IDENTITY_disconnect (id);
146 id = NULL;
147 }
148
149 if (NULL != gst)
150 {
151 GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, NULL, NULL);
152 gst = NULL;
153 }
154 if (NULL != hst)
155 {
156 GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, NULL, NULL);
157 hst = NULL;
158 }
159 GNUNET_SCHEDULER_shutdown ();
61} 160}
62 161
63 162
@@ -67,7 +166,7 @@ cleanup ()
67 * @param cls NULL 166 * @param cls NULL
68 * @param tc scheduler context 167 * @param tc scheduler context
69 */ 168 */
70static void 169void
71end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 170end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
72{ 171{
73 res = 1; 172 res = 1;
@@ -82,7 +181,7 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
82 * @param cls NULL 181 * @param cls NULL
83 * @param tc scheduler context 182 * @param tc scheduler context
84 */ 183 */
85static void 184void
86end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 185end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
87{ 186{
88 res = 0; 187 res = 0;
@@ -94,7 +193,7 @@ end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
94/** 193/**
95 * Finish the test case (successfully). 194 * Finish the test case (successfully).
96 */ 195 */
97static void 196void
98end () 197end ()
99{ 198{
100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n"); 199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");
@@ -109,6 +208,564 @@ end ()
109} 208}
110 209
111 210
211static void
212transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
213{
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
215 struct TransmitClosure *tmit = cls;
216 if (NULL != tmit->host_ann)
217 GNUNET_SOCIAL_host_announce_resume (tmit->host_ann);
218 else
219 GNUNET_SOCIAL_guest_talk_resume (tmit->guest_talk);
220}
221
222
223int
224notify_data (void *cls, uint16_t *data_size, void *data)
225{
226 struct TransmitClosure *tmit = cls;
227 if (NULL != tmit->env)
228 {
229 GNUNET_ENV_environment_destroy (tmit->env);
230 tmit->env = NULL;
231 }
232 if (0 == tmit->data_count)
233 {
234 *data_size = 0;
235 return GNUNET_YES;
236 }
237
238 uint16_t size = strlen (tmit->data[tmit->n]) + 1;
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
240 "Transmit notify data: %u bytes available, "
241 "processing fragment %u/%u (size %u).\n",
242 *data_size, tmit->n + 1, tmit->data_count, size);
243 if (*data_size < size)
244 {
245 *data_size = 0;
246 GNUNET_assert (0);
247 return GNUNET_SYSERR;
248 }
249
250 if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
253 tmit->paused = GNUNET_YES;
254 GNUNET_SCHEDULER_add_delayed (
255 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
256 tmit->data_delay[tmit->n]),
257 &transmit_resume, tmit);
258 *data_size = 0;
259 return GNUNET_NO;
260 }
261 tmit->paused = GNUNET_NO;
262
263 *data_size = size;
264 memcpy (data, tmit->data[tmit->n], size);
265
266 return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
267}
268
269
270void host_left ()
271{
272 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
273 "The host has left the place.\n");
274 GNUNET_SOCIAL_slicer_destroy (host_slicer);
275 host_slicer = NULL;
276 hst = NULL;
277
278 end ();
279}
280
281
282void
283schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
284{
285 test = TEST_HOST_LEAVE;
286 GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, &host_left, NULL);
287}
288
289
290void
291host_farewell (void *cls,
292 struct GNUNET_SOCIAL_Nym *nym,
293 struct GNUNET_ENV_Environment *env,
294 size_t variable_count,
295 struct GNUNET_ENV_Modifier *variables)
296{
297 struct GNUNET_CRYPTO_EcdsaPublicKey *
298 nym_key = GNUNET_SOCIAL_nym_get_key (nym);
299 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
300 "Nym %s has left the place.\n",
301 GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key));
302 GNUNET_assert (0 == memcmp (&guest_pub_key, nym_key, sizeof (*nym_key)));
303
304 GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL);
305}
306
307
308void
309guest_left (void *cls)
310{
311 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
312 "The guest has left the place.\n");
313 GNUNET_SOCIAL_slicer_destroy (guest_slicer);
314 guest_slicer = NULL;
315 gst = NULL;
316
317 GNUNET_SCHEDULER_add_now (&schedule_host_leave, NULL);
318}
319
320
321void
322schedule_guest_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
323{
324 test = TEST_GUEST_LEAVE;
325 /* FIXME test keep_active */
326 GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, &guest_left, NULL);
327}
328
329
330
331void
332guest_recv_method (void *cls,
333 const struct GNUNET_PSYC_MessageMethod *meth,
334 uint64_t message_id,
335 uint32_t flags,
336 const struct GNUNET_SOCIAL_Nym *nym,
337 const char *method_name)
338{
339 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
340 "Test #%u: Guest received method for message ID %" PRIu64 ":\n"
341 "%s\n",
342 test, message_id, method_name);
343 /* FIXME: check message */
344}
345
346
347void
348guest_recv_modifier (void *cls,
349 const struct GNUNET_PSYC_MessageModifier *mod,
350 uint64_t message_id,
351 enum GNUNET_ENV_Operator oper,
352 const char *name,
353 const void *value,
354 uint16_t value_size)
355{
356 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
357 "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n"
358 "%c%s: %.*s\n",
359 test, message_id, oper, name, value_size, value);
360}
361
362
363void
364guest_recv_data (void *cls,
365 const struct GNUNET_MessageHeader *msg,
366 uint64_t message_id,
367 uint64_t data_offset,
368 const void *data,
369 uint16_t data_size)
370{
371 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
372 "Test #%u: Guest received data for message ID %" PRIu64 ":\n"
373 "%.*s\n",
374 test, message_id, data_size, data);
375}
376
377
378void
379guest_recv_eom (void *cls,
380 const struct GNUNET_MessageHeader *msg,
381 uint64_t message_id,
382 uint8_t cancelled)
383{
384 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
385 "Test #%u: Guest received end of message ID %" PRIu64
386 ", cancelled: %u\n",
387 test, message_id, cancelled);
388
389 switch (test)
390 {
391 case TEST_HOST_ANNOUNCE:
392 test = TEST_HOST_ANNOUNCE_END;
393 break;
394
395 case TEST_HOST_ANNOUNCE_END:
396 guest_talk ();
397 break;
398
399 case TEST_GUEST_TALK:
400 test = TEST_GUEST_TALK_END;
401 break;
402
403 case TEST_GUEST_TALK_END:
404 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
405 break;
406
407 default:
408 GNUNET_assert (0);
409 }
410}
411
412
413void
414host_recv_method (void *cls,
415 const struct GNUNET_PSYC_MessageMethod *meth,
416 uint64_t message_id,
417 uint32_t flags,
418 const struct GNUNET_SOCIAL_Nym *nym,
419 const char *method_name)
420{
421 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
422 "Test #%u: Host received method for message ID %" PRIu64 ":\n"
423 "%s\n",
424 test, message_id, method_name);
425 /* FIXME: check message */
426}
427
428
429void
430host_recv_modifier (void *cls,
431 const struct GNUNET_PSYC_MessageModifier *mod,
432 uint64_t message_id,
433 enum GNUNET_ENV_Operator oper,
434 const char *name,
435 const void *value,
436 uint16_t value_size)
437{
438 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
439 "Test #%u: Host received modifier for message ID %" PRIu64 ":\n"
440 "%c%s: %.*s\n",
441 test, message_id, oper, name, value_size, value);
442}
443
444
445void
446host_recv_data (void *cls,
447 const struct GNUNET_MessageHeader *msg,
448 uint64_t message_id,
449 uint64_t data_offset,
450 const void *data,
451 uint16_t data_size)
452{
453 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
454 "Test #%u: Host received data for message ID %" PRIu64 ":\n"
455 "%.*s\n",
456 test, message_id, data_size, data);
457}
458
459
460void
461host_recv_eom (void *cls,
462 const struct GNUNET_MessageHeader *msg,
463 uint64_t message_id,
464 uint8_t cancelled)
465{
466 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
467 "Test #%u: Host received end of message ID %" PRIu64
468 ", cancelled: %u\n",
469 test, message_id, cancelled);
470
471 switch (test)
472 {
473 case TEST_HOST_ANNOUNCE:
474 test = TEST_HOST_ANNOUNCE_END;
475 //host_announce2 ();
476 break;
477
478 case TEST_HOST_ANNOUNCE_END:
479 guest_talk ();
480 break;
481
482 case TEST_GUEST_TALK:
483 test = TEST_GUEST_TALK_END;
484 break;
485
486 case TEST_GUEST_TALK_END:
487 GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
488 break;
489
490 default:
491 GNUNET_assert (0);
492 }
493}
494
495
496void
497guest_talk ()
498{
499 test = TEST_GUEST_TALK;
500
501 tmit = (struct TransmitClosure) {};
502 tmit.env = GNUNET_ENV_environment_create ();
503 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
504 "_bar_foo", DATA2ARG ("one two three"));
505 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
506 "_bar_baz", DATA2ARG ("four five"));
507 tmit.data[0] = "zzz xxx yyy";
508 tmit.data[1] = "zyx wvu tsr qpo";
509 tmit.data[2] = "testing ten nine eight";
510 tmit.data_count = 3;
511
512 tmit.host_ann
513 = GNUNET_SOCIAL_host_announce (hst, "_message_guest", tmit.env,
514 &notify_data, &tmit,
515 GNUNET_SOCIAL_TALK_NONE);
516}
517
518void
519host_announce ()
520{
521 test = TEST_HOST_ANNOUNCE;
522
523 tmit = (struct TransmitClosure) {};
524 tmit.env = GNUNET_ENV_environment_create ();
525 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
526 "_foo", DATA2ARG ("bar baz"));
527 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
528 "_foo_bar", DATA2ARG ("foo bar"));
529 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
530 "_foo_bar_baz", DATA2ARG ("foo bar baz"));
531 tmit.data[0] = "aaa bbb ccc";
532 tmit.data[1] = "abc def ghi jkl";
533 tmit.data[2] = "testing one two three";
534 tmit.data[3] = "four five";
535 tmit.data_count = 4;
536
537 tmit.host_ann
538 = GNUNET_SOCIAL_host_announce (hst, "_message_host", tmit.env,
539 &notify_data, &tmit,
540 GNUNET_SOCIAL_ANNOUNCE_NONE);
541}
542
543void
544host_announce2 ()
545{
546 test = TEST_HOST_ANNOUNCE;
547
548 tmit = (struct TransmitClosure) {};
549 tmit.env = GNUNET_ENV_environment_create ();
550 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
551 "_foo2", DATA2ARG ("BAR BAZ"));
552 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
553 "_foo2_bar", DATA2ARG ("FOO BAR"));
554 GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
555 "_foo2_bar", DATA2ARG ("FOO BAR BAZ"));
556 tmit.data[0] = "AAA BBB CCC";
557 tmit.data[1] = "ABC DEF GHI JKL";
558 tmit.data[2] = "TESTING ONE TWO THREE";
559 tmit.data_count = 3;
560
561 tmit.host_ann
562 = GNUNET_SOCIAL_host_announce (hst, "_message_host_two", tmit.env,
563 &notify_data, &tmit,
564 GNUNET_SOCIAL_ANNOUNCE_NONE);
565}
566
567
568void
569guest_recv_entry_decision (void *cls,
570 int is_admitted,
571 const struct GNUNET_PSYC_Message *entry_resp)
572{
573 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
574 "Guest received entry decision (try %u): %d.\n",
575 join_req_count, is_admitted);
576
577 if (NULL != entry_resp)
578 {
579 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
580 const char *method_name = NULL;
581 const void *data = NULL;
582 uint16_t data_size = 0;
583 GNUNET_PSYC_message_parse (entry_resp, &method_name, env, &data, &data_size);
584
585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
586 "%s\n%.*s\n",
587 method_name, data_size, data);
588 /* FIXME: check response message */
589 }
590
591 switch (test)
592 {
593 case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE:
594 GNUNET_assert (GNUNET_NO == is_admitted);
595 guest_enter ();
596 break;
597
598 case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT:
599 GNUNET_assert (GNUNET_YES == is_admitted);
600 host_announce ();
601 break;
602
603 default:
604 GNUNET_assert (0);
605 }
606}
607
608
609void
610host_answer_door (void *cls,
611 struct GNUNET_SOCIAL_Nym *nym,
612 const char *method_name,
613 struct GNUNET_ENV_Environment *env,
614 size_t data_size,
615 const void *data)
616{
617 join_req_count++;
618
619 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
620 "Host received entry request from guest (try %u).\n",
621 join_req_count);
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
623 "%s\n%.*s\n",
624 method_name, data_size, data);
625
626 switch (test)
627 {
628 case TEST_HOST_ANSWER_DOOR_REFUSE:
629 test = TEST_GUEST_RECV_ENTRY_DCSN_REFUSE;
630 join_resp = GNUNET_PSYC_message_create ("_refuse_nym", env,
631 DATA2ARG ("Go away!"));
632 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, join_resp);
633 break;
634
635 case TEST_HOST_ANSWER_DOOR_ADMIT:
636 test = TEST_GUEST_RECV_ENTRY_DCSN_ADMIT;
637 join_resp = GNUNET_PSYC_message_create ("_admit_nym", env,
638 DATA2ARG ("Welcome, nym!"));
639 GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp);
640 break;
641
642 default:
643 GNUNET_assert (0);
644 }
645}
646
647
648void
649guest_recv_local_enter (void *cls, int result, uint64_t max_message_id)
650{
651 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Guest entered to local place.\n");
652
653}
654
655
656void
657guest_enter ()
658{
659 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as guest.\n");
660
661 struct GuestEnterMessage *emsg = &guest_enter_msg;
662
663 emsg->method_name = "_request_enter";
664 emsg->env = GNUNET_ENV_environment_create ();
665 GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
666 "_abc", "abc def", 7);
667 GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
668 "_abc_def", "abc def ghi", 11);
669 emsg->data = "let me in";
670 emsg->data_size = strlen (emsg->data) + 1;
671 emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
672 emsg->data, emsg->data_size);
673
674 gst = GNUNET_SOCIAL_guest_enter (cfg, guest_ego, &place_pub_key,
675 &this_peer, 0, NULL, emsg->msg,
676 guest_slicer, &guest_recv_local_enter,
677 &guest_recv_entry_decision, NULL);
678}
679
680
681void id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
682{
683 GNUNET_assert (NULL != ego);
684 guest_ego = ego;
685
686 guest_slicer = GNUNET_SOCIAL_slicer_create ();
687 GNUNET_SOCIAL_slicer_add (guest_slicer, "",
688 &guest_recv_method, &guest_recv_modifier,
689 &guest_recv_data, &guest_recv_eom, NULL);
690 test = TEST_HOST_ANSWER_DOOR_ADMIT;
691 //host_announce ();
692 guest_enter ();
693}
694
695
696void id_guest_created (void *cls, const char *emsg)
697{
698 if (NULL != emsg)
699 {
700 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
701 "Could not create guest identity: %s\n", emsg);
702#if 0 == DEBUG_SERVICE
703 GNUNET_assert (0);
704#endif
705 }
706
707 GNUNET_IDENTITY_ego_lookup (cfg, guest_name, &id_guest_ego_cb, NULL);
708}
709
710
711void host_entered (void *cls, uint64_t max_message_id)
712{
713 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host entered to place.\n");
714
715 GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL);
716}
717
718
719void id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
720{
721 GNUNET_assert (NULL != ego);
722 host_ego = ego;
723
724 host_slicer = GNUNET_SOCIAL_slicer_create ();
725 GNUNET_SOCIAL_slicer_add (host_slicer, "",
726 &host_recv_method, &host_recv_modifier,
727 &host_recv_data, &host_recv_eom, NULL);
728
729 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n");
730 hst = GNUNET_SOCIAL_host_enter (cfg, host_ego, place_key,
731 GNUNET_PSYC_CHANNEL_PRIVATE, host_slicer,
732 &host_entered, &host_answer_door,
733 &host_farewell, NULL);
734}
735
736
737void id_host_created (void *cls, const char *emsg)
738{
739 if (NULL != emsg)
740 {
741 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
742 "Could not create host identity: %s\n", emsg);
743#if 0 == DEBUG_SERVICE
744 GNUNET_assert (0);
745#endif
746 }
747
748 GNUNET_IDENTITY_ego_lookup (cfg, host_name, &id_host_ego_cb, NULL);
749}
750
751
752void identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
753 void **ctx, const char *name)
754{
755
756}
757
758
759void
760core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
761{
762 this_peer = *my_identity;
763
764 id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL);
765 GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL);
766}
767
768
112/** 769/**
113 * Main function of the test, run from scheduler. 770 * Main function of the test, run from scheduler.
114 * 771 *
@@ -116,7 +773,7 @@ end ()
116 * @param cfg configuration we use (also to connect to Social service) 773 * @param cfg configuration we use (also to connect to Social service)
117 * @param peer handle to access more of the peer (not used) 774 * @param peer handle to access more of the peer (not used)
118 */ 775 */
119static void 776void
120#if DEBUG_SERVICE 777#if DEBUG_SERVICE
121run (void *cls, char *const *args, const char *cfgfile, 778run (void *cls, char *const *args, const char *cfgfile,
122 const struct GNUNET_CONFIGURATION_Handle *c) 779 const struct GNUNET_CONFIGURATION_Handle *c)
@@ -129,9 +786,14 @@ run (void *cls,
129 cfg = c; 786 cfg = c;
130 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); 787 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
131 788
132 /* FIXME: add tests */ 789 place_key = GNUNET_CRYPTO_eddsa_key_create ();
790 guest_key = GNUNET_CRYPTO_ecdsa_key_create ();
133 791
134 end (); 792 GNUNET_CRYPTO_eddsa_key_get_public (place_key, &place_pub_key);
793 GNUNET_CRYPTO_ecdsa_key_get_public (guest_key, &guest_pub_key);
794
795 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
796 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
135} 797}
136 798
137 799