aboutsummaryrefslogtreecommitdiff
path: root/src/social
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2015-12-17 14:12:44 +0000
committerGabor X Toth <*@tg-x.net>2015-12-17 14:12:44 +0000
commitc159ab01bd16e9f3ad1776fa6fb26398cb7986d9 (patch)
tree61b0cad0b3e94f7e2dc7a8b48de7dc24784e229d /src/social
parent6cf89fa848bbcb9e1f941bad1ac0c4ec6066fdd7 (diff)
downloadgnunet-c159ab01bd16e9f3ad1776fa6fb26398cb7986d9.tar.gz
gnunet-c159ab01bd16e9f3ad1776fa6fb26398cb7986d9.zip
social: API changes for application connections: store/load app subscriptions to places
Diffstat (limited to 'src/social')
-rw-r--r--src/social/Makefile.am9
-rw-r--r--src/social/gnunet-service-social.c1361
-rw-r--r--src/social/social.h181
-rw-r--r--src/social/social_api.c1233
-rw-r--r--src/social/test_social.c356
5 files changed, 2312 insertions, 828 deletions
diff --git a/src/social/Makefile.am b/src/social/Makefile.am
index 2c8d5707d..ac80d0c8c 100644
--- a/src/social/Makefile.am
+++ b/src/social/Makefile.am
@@ -25,11 +25,6 @@ libgnunetsocial_la_SOURCES = \
25libgnunetsocial_la_LIBADD = \ 25libgnunetsocial_la_LIBADD = \
26 $(top_builddir)/src/util/libgnunetutil.la \ 26 $(top_builddir)/src/util/libgnunetutil.la \
27 $(top_builddir)/src/env/libgnunetenv.la \ 27 $(top_builddir)/src/env/libgnunetenv.la \
28 $(top_builddir)/src/psycstore/libgnunetpsycutil.la \
29 $(top_builddir)/src/core/libgnunetcore.la \
30 $(top_builddir)/src/identity/libgnunetidentity.la \
31 $(top_builddir)/src/gns/libgnunetgns.la \
32 $(top_builddir)/src/namestore/libgnunetnamestore.la \
33 $(GN_LIBINTL) $(XLIB) 28 $(GN_LIBINTL) $(XLIB)
34libgnunetsocial_la_LDFLAGS = \ 29libgnunetsocial_la_LDFLAGS = \
35 $(GN_LIB_LDFLAGS) $(WINFLAGS) \ 30 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
@@ -47,6 +42,10 @@ gnunet_service_social_LDADD = \
47 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 42 $(top_builddir)/src/statistics/libgnunetstatistics.la \
48 $(top_builddir)/src/psyc/libgnunetpsyc.la \ 43 $(top_builddir)/src/psyc/libgnunetpsyc.la \
49 $(top_builddir)/src/psycstore/libgnunetpsycutil.la \ 44 $(top_builddir)/src/psycstore/libgnunetpsycutil.la \
45 $(top_builddir)/src/core/libgnunetcore.la \
46 $(top_builddir)/src/identity/libgnunetidentity.la \
47 $(top_builddir)/src/gns/libgnunetgns.la \
48 $(top_builddir)/src/namestore/libgnunetnamestore.la \
50 $(GN_LIBINTL) 49 $(GN_LIBINTL)
51 50
52 51
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c
index aace01fed..b7cf1f856 100644
--- a/src/social/gnunet-service-social.c
+++ b/src/social/gnunet-service-social.c
@@ -25,11 +25,16 @@
25 */ 25 */
26 26
27#include <inttypes.h> 27#include <inttypes.h>
28#include <strings.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_constants.h" 32#include "gnunet_constants.h"
32#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "gnunet_core_service.h"
35#include "gnunet_identity_service.h"
36#include "gnunet_namestore_service.h"
37#include "gnunet_gns_service.h"
33#include "gnunet_statistics_service.h" 38#include "gnunet_statistics_service.h"
34#include "gnunet_psyc_service.h" 39#include "gnunet_psyc_service.h"
35#include "gnunet_psyc_util_lib.h" 40#include "gnunet_psyc_util_lib.h"
@@ -42,10 +47,17 @@
42 */ 47 */
43static const struct GNUNET_CONFIGURATION_Handle *cfg; 48static const struct GNUNET_CONFIGURATION_Handle *cfg;
44 49
50/* Handles to other services */
51static struct GNUNET_CORE_Handle *core;
52static struct GNUNET_IDENTITY_Handle *id;
53static struct GNUNET_GNS_Handle *gns;
54static struct GNUNET_NAMESTORE_Handle *namestore;
55static struct GNUNET_STATISTICS_Handle *stats;
56
45/** 57/**
46 * Handle to the statistics service. 58 * ID of this peer.
47 */ 59 */
48static struct GNUNET_STATISTICS_Handle *stats; 60static struct GNUNET_PeerIdentity this_peer;
49 61
50/** 62/**
51 * Notification context, simplifies client broadcasts. 63 * Notification context, simplifies client broadcasts.
@@ -66,7 +78,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *guests;
66 78
67/** 79/**
68 * Connected guests per place. 80 * Connected guests per place.
69 * H(place_pub_key) -> Guest's pub_key -> struct Guest 81 * H(place_pub_key) -> ego_pub_key -> struct Guest
70 */ 82 */
71static struct GNUNET_CONTAINER_MultiHashMap *place_guests; 83static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
72 84
@@ -74,19 +86,44 @@ static struct GNUNET_CONTAINER_MultiHashMap *place_guests;
74 * Places entered as host or guest. 86 * Places entered as host or guest.
75 * H(place_pub_key) -> struct HostEnterRequest OR struct GuestEnterRequest 87 * H(place_pub_key) -> struct HostEnterRequest OR struct GuestEnterRequest
76 */ 88 */
77static struct GNUNET_CONTAINER_MultiHashMap *places_entered; 89static struct GNUNET_CONTAINER_MultiHashMap *places;
90
91/**
92 * Places entered per application.
93 * H(app_id) -> H(place_pub_key) -> NULL
94 */
95static struct GNUNET_CONTAINER_MultiHashMap *apps_places;
96
97/**
98 * Connected applications.
99 * H(app_id) -> struct Application
100 */
101static struct GNUNET_CONTAINER_MultiHashMap *apps;
102
103/**
104 * All egos.
105 * H(ego_pub_key) -> struct Ego
106 */
107static struct GNUNET_CONTAINER_MultiHashMap *egos;
78 108
79/** 109/**
80 * Place listener clients. 110 * Directory for storing social data.
81 * H(ego_pub_key) -> struct PlaceListener 111 * Default: ~/.local/share/gnunet/social
82 */ 112 */
83static struct GNUNET_CONTAINER_MultiHashMap *place_listeners; 113static char *dir_social;
84 114
85/** 115/**
86 * Directory for storing places. 116 * Directory for storing place data.
117 * $dir_social/places
87 */ 118 */
88static char *dir_places; 119static char *dir_places;
89 120
121/**
122 * Directory for storing app data.
123 * $dir_social/apps
124 */
125static char *dir_apps;
126
90 127
91/** 128/**
92 * Message fragment transmission queue. 129 * Message fragment transmission queue.
@@ -157,7 +194,12 @@ struct Place
157 struct GNUNET_PSYC_Channel *channel; 194 struct GNUNET_PSYC_Channel *channel;
158 195
159 /** 196 /**
160 * Public key of the channel. 197 * Private key of home in case of a host.
198 */
199 struct GNUNET_CRYPTO_EddsaPublicKey key;
200
201 /**
202 * Public key of place.
161 */ 203 */
162 struct GNUNET_CRYPTO_EddsaPublicKey pub_key; 204 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
163 205
@@ -167,6 +209,21 @@ struct Place
167 struct GNUNET_HashCode pub_key_hash; 209 struct GNUNET_HashCode pub_key_hash;
168 210
169 /** 211 /**
212 * Private key of ego.
213 */
214 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
215
216 /**
217 * Public key of ego.
218 */
219 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
220
221 /**
222 * Hash of @a ego_pub_key.
223 */
224 struct GNUNET_HashCode ego_pub_hash;
225
226 /**
170 * Last message ID received for the place. 227 * Last message ID received for the place.
171 * 0 if there is no such message. 228 * 0 if there is no such message.
172 */ 229 */
@@ -202,11 +259,6 @@ struct Host
202 struct Place plc; 259 struct Place plc;
203 260
204 /** 261 /**
205 * Private key of the channel.
206 */
207 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
208
209 /**
210 * Handle for the multicast origin. 262 * Handle for the multicast origin.
211 */ 263 */
212 struct GNUNET_PSYC_Master *master; 264 struct GNUNET_PSYC_Master *master;
@@ -240,21 +292,6 @@ struct Guest
240 struct Place plc; 292 struct Place plc;
241 293
242 /** 294 /**
243 * Private key of the slave.
244 */
245 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
246
247 /**
248 * Public key of the slave.
249 */
250 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
251
252 /**
253 * Hash of @a pub_key.
254 */
255 struct GNUNET_HashCode pub_key_hash;
256
257 /**
258 * Handle for the PSYC slave. 295 * Handle for the PSYC slave.
259 */ 296 */
260 struct GNUNET_PSYC_Slave *slave; 297 struct GNUNET_PSYC_Slave *slave;
@@ -293,7 +330,7 @@ struct Guest
293 330
294 331
295/** 332/**
296 * Context for host/guest client. 333 * Context for a client.
297 */ 334 */
298struct Client 335struct Client
299{ 336{
@@ -309,19 +346,25 @@ struct Client
309 struct MessageTransmitQueue *tmit_msg; 346 struct MessageTransmitQueue *tmit_msg;
310 347
311 /** 348 /**
312 * Ego key for listener clients; 349 * ID for application clients.
313 */ 350 */
314 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key; 351 char *app_id;
315}; 352};
316 353
317 354
318struct PlaceListener 355struct Application
319{ 356{
320 struct ClientListItem *clients_head; 357 struct ClientListItem *clients_head;
321 struct ClientListItem *clients_tail; 358 struct ClientListItem *clients_tail;
322}; 359};
323 360
324 361
362struct Ego {
363 struct GNUNET_CRYPTO_EcdsaPrivateKey key;
364 char *name;
365};
366
367
325struct OperationClosure 368struct OperationClosure
326{ 369{
327 struct GNUNET_SERVER_Client *client; 370 struct GNUNET_SERVER_Client *client;
@@ -335,6 +378,18 @@ static int
335psyc_transmit_message (struct Place *plc); 378psyc_transmit_message (struct Place *plc);
336 379
337 380
381static void
382cleanup_place (struct Place *plc);
383
384
385int
386place_entry_cleanup (void *cls, const struct GNUNET_HashCode *key, void *value)
387{
388 cleanup_place (value);
389 return GNUNET_YES;
390}
391
392
338/** 393/**
339 * Task run during shutdown. 394 * Task run during shutdown.
340 * 395 *
@@ -344,11 +399,34 @@ psyc_transmit_message (struct Place *plc);
344static void 399static void
345shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 400shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
346{ 401{
402 GNUNET_CONTAINER_multihashmap_iterate (hosts, place_entry_cleanup, NULL);
403 GNUNET_CONTAINER_multihashmap_iterate (guests, place_entry_cleanup, NULL);
404
347 if (NULL != nc) 405 if (NULL != nc)
348 { 406 {
349 GNUNET_SERVER_notification_context_destroy (nc); 407 GNUNET_SERVER_notification_context_destroy (nc);
350 nc = NULL; 408 nc = NULL;
351 } 409 }
410 if (NULL != core)
411 {
412 GNUNET_CORE_disconnect (core);
413 core = NULL;
414 }
415 if (NULL != id)
416 {
417 GNUNET_IDENTITY_disconnect (id);
418 id = NULL;
419 }
420 if (NULL != namestore)
421 {
422 GNUNET_NAMESTORE_disconnect (namestore);
423 namestore = NULL;
424 }
425 if (NULL != gns)
426 {
427 GNUNET_GNS_disconnect (gns);
428 gns = NULL;
429 }
352 if (NULL != stats) 430 if (NULL != stats)
353 { 431 {
354 GNUNET_STATISTICS_destroy (stats, GNUNET_YES); 432 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
@@ -383,7 +461,7 @@ cleanup_guest (struct Guest *gst)
383 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, 461 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests,
384 &plc->pub_key_hash); 462 &plc->pub_key_hash);
385 GNUNET_assert (NULL != plc_gst); // FIXME 463 GNUNET_assert (NULL != plc_gst); // FIXME
386 GNUNET_CONTAINER_multihashmap_remove (plc_gst, &gst->pub_key_hash, gst); 464 GNUNET_CONTAINER_multihashmap_remove (plc_gst, &plc->ego_pub_hash, gst);
387 465
388 if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst)) 466 if (0 == GNUNET_CONTAINER_multihashmap_size (plc_gst))
389 { 467 {
@@ -444,15 +522,20 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
444 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client); 522 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
445 if (NULL == ctx) 523 if (NULL == ctx)
446 { 524 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 525 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
448 "%p User context is NULL in client_disconnect()\n", ctx); 526 "%p User context is NULL in client_disconnect()\n", ctx);
449 GNUNET_break (0);
450 return; 527 return;
451 } 528 }
452 529
453 struct Place *plc = ctx->plc; 530 struct Place *plc = ctx->plc;
531
532 if (NULL != ctx->app_id)
533 GNUNET_free (ctx->app_id);
534
535 GNUNET_free (ctx);
536
454 if (NULL == plc) 537 if (NULL == plc)
455 return; // place listener client, nothing to do 538 return; // application client, nothing to do
456 539
457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
458 "%p Client (%s) disconnected from place %s\n", 541 "%p Client (%s) disconnected from place %s\n",
@@ -470,40 +553,35 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
470 } 553 }
471 cli = cli->next; 554 cli = cli->next;
472 } 555 }
556}
473 557
474 if (NULL == plc->clients_head) 558
475 { /* Last client disconnected. */ 559/**
476 if (GNUNET_YES != plc->is_disconnected) 560 * Send message to a client.
477 { 561 */
478 plc->is_disconnected = GNUNET_YES; 562static inline void
479 if (NULL != plc->tmit_msgs_head) 563client_send_msg (struct GNUNET_SERVER_Client *client,
480 { /* Send pending messages to PSYC before cleanup. */ 564 const struct GNUNET_MessageHeader *msg)
481 psyc_transmit_message (plc); 565{
482 } 566 GNUNET_SERVER_notification_context_add (nc, client);
483 else 567 GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO);
484 {
485 cleanup_place (plc);
486 }
487 }
488 }
489} 568}
490 569
491 570
492/** 571/**
493 * Send message to all clients connected to the channel. 572 * Send message to all clients connected to a place.
494 */ 573 */
495static void 574static void
496client_send_msg (const struct Place *plc, 575place_send_msg (const struct Place *plc,
497 const struct GNUNET_MessageHeader *msg) 576 const struct GNUNET_MessageHeader *msg)
498{ 577{
499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
500 "%p Sending message to clients.\n", plc); 579 "%p Sending message to clients of place.\n", plc);
501 580
502 struct ClientListItem *cli = plc->clients_head; 581 struct ClientListItem *cli = plc->clients_head;
503 while (NULL != cli) 582 while (NULL != cli)
504 { 583 {
505 GNUNET_SERVER_notification_context_add (nc, cli->client); 584 client_send_msg (cli->client, msg);
506 GNUNET_SERVER_notification_context_unicast (nc, cli->client, msg, GNUNET_NO);
507 cli = cli->next; 585 cli = cli->next;
508 } 586 }
509} 587}
@@ -542,13 +620,31 @@ client_send_result (struct GNUNET_SERVER_Client *client, uint64_t op_id,
542 "%" PRId64 " (size: %u)\n", 620 "%" PRId64 " (size: %u)\n",
543 client, GNUNET_ntohll (op_id), result_code, data_size); 621 client, GNUNET_ntohll (op_id), result_code, data_size);
544 622
545 GNUNET_SERVER_notification_context_add (nc, client); 623 client_send_msg (client, &res->header);
546 GNUNET_SERVER_notification_context_unicast (nc, client, &res->header,
547 GNUNET_NO);
548 GNUNET_free (res); 624 GNUNET_free (res);
549} 625}
550 626
551 627
628static void
629client_send_host_enter_ack (struct GNUNET_SERVER_Client *client,
630 struct Host *hst, uint32_t result)
631{
632 struct Place *plc = &hst->plc;
633
634 struct HostEnterAck hack;
635 hack.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
636 hack.header.size = htons (sizeof (hack));
637 hack.result_code = htonl (result);
638 hack.max_message_id = GNUNET_htonll (plc->max_message_id);
639 hack.place_pub_key = plc->pub_key;
640
641 if (NULL != client)
642 client_send_msg (client, &hack.header);
643 else
644 place_send_msg (plc, &hack.header);
645}
646
647
552/** 648/**
553 * Called after a PSYC master is started. 649 * Called after a PSYC master is started.
554 */ 650 */
@@ -560,13 +656,7 @@ psyc_master_started (void *cls, int result, uint64_t max_message_id)
560 plc->max_message_id = max_message_id; 656 plc->max_message_id = max_message_id;
561 plc->is_ready = GNUNET_YES; 657 plc->is_ready = GNUNET_YES;
562 658
563 struct GNUNET_PSYC_CountersResultMessage res; 659 client_send_host_enter_ack (NULL, hst, result);
564 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
565 res.header.size = htons (sizeof (res));
566 res.result_code = htonl (result);
567 res.max_message_id = GNUNET_htonll (plc->max_message_id);
568
569 client_send_msg (plc, &res.header);
570} 660}
571 661
572 662
@@ -585,7 +675,7 @@ psyc_recv_join_request (void *cls,
585 GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash); 675 GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
586 GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh, 676 GNUNET_CONTAINER_multihashmap_put (hst->join_reqs, &slave_key_hash, jh,
587 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 677 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
588 client_send_msg (&hst->plc, &req->header); 678 place_send_msg (&hst->plc, &req->header);
589} 679}
590 680
591 681
@@ -606,7 +696,7 @@ psyc_slave_connected (void *cls, int result, uint64_t max_message_id)
606 res.result_code = htonl (result); 696 res.result_code = htonl (result);
607 res.max_message_id = GNUNET_htonll (plc->max_message_id); 697 res.max_message_id = GNUNET_htonll (plc->max_message_id);
608 698
609 client_send_msg (plc, &res.header); 699 place_send_msg (plc, &res.header);
610} 700}
611 701
612 702
@@ -620,7 +710,7 @@ psyc_recv_join_dcsn (void *cls,
620 const struct GNUNET_PSYC_Message *join_msg) 710 const struct GNUNET_PSYC_Message *join_msg)
621{ 711{
622 struct Guest *gst = cls; 712 struct Guest *gst = cls;
623 client_send_msg (&gst->plc, &dcsn->header); 713 place_send_msg (&gst->plc, &dcsn->header);
624} 714}
625 715
626 716
@@ -641,7 +731,7 @@ psyc_recv_message (void *cls,
641 plc, ntohs (msg->header.size), str); 731 plc, ntohs (msg->header.size), str);
642 GNUNET_free (str); 732 GNUNET_free (str);
643 733
644 client_send_msg (plc, &msg->header); 734 place_send_msg (plc, &msg->header);
645 735
646 /* FIXME: further processing */ 736 /* FIXME: further processing */
647} 737}
@@ -656,110 +746,219 @@ place_init (struct Place *plc)
656 746
657} 747}
658 748
749/**
750 * Add a place to the @e places hash map.
751 *
752 * @param ereq
753 * Entry request.
754 *
755 * @return #GNUNET_OK if the place was added
756 * #GNUNET_NO if the place already exists in the hash map
757 * #GNUNET_SYSERR on error
758 */
759static int
760place_add (const struct PlaceEnterRequest *ereq)
761{
762 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
763 "Adding place to hashmap:\n");
764
765 struct EgoPlacePublicKey ego_place_pub_key = {
766 .ego_pub_key = ereq->ego_pub_key,
767 .place_pub_key = ereq->place_pub_key,
768 };
769 struct GNUNET_HashCode ego_place_pub_hash;
770 GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
771
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
773 " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
774
775 struct GNUNET_MessageHeader *
776 place_msg = GNUNET_CONTAINER_multihashmap_get (places, &ego_place_pub_hash);
777 if (NULL != place_msg)
778 return GNUNET_NO;
779
780 place_msg = GNUNET_copy_message (&ereq->header);
781 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places, &ego_place_pub_hash, place_msg,
782 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
783 {
784 GNUNET_break (0);
785 GNUNET_free (place_msg);
786 return GNUNET_SYSERR;
787 }
788
789 return GNUNET_OK;
790}
659 791
660/** 792/**
661 * Add place to places_entered hash map. 793 * Add a place to the @e app_places hash map.
662 * 794 *
663 * @param ego_pub_hash 795 * @param app_id
664 * H(ego_pub_key) 796 * Application ID.
665 * @param place_pub_hash
666 * H(place_pub_key)
667 * @param msg 797 * @param msg
668 * Entry message. 798 * Entry message.
669 * 799 *
670 * @return Return value of GNUNET_CONTAINER_multihashmap_put () 800 * @return #GNUNET_OK if the place was added
801 * #GNUNET_NO if the place already exists in the hash map
802 * #GNUNET_SYSERR on error
671 */ 803 */
672static int 804static int
673place_add (const struct GNUNET_HashCode *ego_pub_hash, 805app_place_add (const char *app_id,
674 const struct GNUNET_HashCode *place_pub_hash, 806 const struct PlaceEnterRequest *ereq)
675 const struct GNUNET_MessageHeader *msg)
676{ 807{
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Adding place to hashmap:\n"); 809 "Adding app place to hashmap:\n");
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 " ego_pub_hash = %s\n", GNUNET_h2s (ego_pub_hash)); 811 " app_id = %s\n", app_id);
812
813 struct GNUNET_HashCode app_id_hash;
814 GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
815
816 struct EgoPlacePublicKey ego_place_pub_key = {
817 .ego_pub_key = ereq->ego_pub_key,
818 .place_pub_key = ereq->place_pub_key,
819 };
820 struct GNUNET_HashCode ego_place_pub_hash;
821 GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
822
681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682 " place_pub_hash = %s\n", GNUNET_h2s (place_pub_hash)); 824 " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
683 825
684 struct GNUNET_CONTAINER_MultiHashMap * 826 struct GNUNET_CONTAINER_MultiHashMap *
685 ego_places = GNUNET_CONTAINER_multihashmap_get (places_entered, ego_pub_hash); 827 app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
686 if (NULL == ego_places) 828 if (NULL == app_places)
687 { 829 {
688 ego_places = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); 830 app_places = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
689 GNUNET_CONTAINER_multihashmap_put (places_entered, ego_pub_hash, ego_places, 831 GNUNET_CONTAINER_multihashmap_put (apps_places, &app_id_hash, app_places,
690 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 832 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
691 } 833 }
692 834
693 struct GNUNET_MessageHeader *msg_old, *msg_new; 835 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (app_places, &ego_place_pub_hash))
694 if (NULL != (msg_old = GNUNET_CONTAINER_multihashmap_get (ego_places, place_pub_hash))) 836 return GNUNET_NO;
837
838 if (GNUNET_SYSERR == place_add (ereq))
839 return GNUNET_SYSERR;
840
841 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash,
842 NULL, 0))
695 { 843 {
696 GNUNET_free (msg_old); 844 GNUNET_break (0);
697 GNUNET_CONTAINER_multihashmap_remove_all (ego_places, place_pub_hash); 845 return GNUNET_SYSERR;
698 } 846 }
699 847
700 uint16_t msg_size = ntohs (msg->size); 848 return GNUNET_OK;
701 msg_new = GNUNET_malloc (msg_size);
702 memcpy (msg_new, msg, msg_size);
703 int ret = GNUNET_CONTAINER_multihashmap_put (ego_places, place_pub_hash, msg_new,
704 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
705 if (GNUNET_OK != ret)
706 GNUNET_break (0);
707 return ret;
708} 849}
709 850
710 851
711/** 852/**
712 * Save place entry message to disk. 853 * Save place entry message to disk.
713 * 854 *
714 * @param ego_key 855 * @param app_id
715 * Private key of ego. 856 * Application ID.
716 * @param place_pub_hash
717 * Hash of public key of place.
718 * @param msg 857 * @param msg
719 * Entry message. 858 * Entry message.
720 */ 859 */
721static void 860static int
722place_save (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ego_key, 861app_place_save (const char *app_id,
723 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub, 862 const struct PlaceEnterRequest *ereq)
724 const struct GNUNET_MessageHeader *msg)
725{ 863{
864 app_place_add (app_id, ereq);
865
726 if (NULL == dir_places) 866 if (NULL == dir_places)
727 return; 867 return GNUNET_SYSERR;
728 868
869 struct GNUNET_HashCode ego_pub_hash;
729 struct GNUNET_HashCode place_pub_hash; 870 struct GNUNET_HashCode place_pub_hash;
730 GNUNET_CRYPTO_hash (place_pub, sizeof (place_pub), &place_pub_hash); 871 GNUNET_CRYPTO_hash (&ereq->ego_pub_key, sizeof (ereq->ego_pub_key),
872 &ego_pub_hash);
873 GNUNET_CRYPTO_hash (&ereq->place_pub_key, sizeof (ereq->place_pub_key),
874 &place_pub_hash);
875
876 struct GNUNET_CRYPTO_HashAsciiEncoded ego_pub_hash_ascii;
877 struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii;
878 memcpy (&ego_pub_hash_ascii.encoding,
879 GNUNET_h2s_full (&ego_pub_hash), sizeof (ego_pub_hash_ascii));
880 memcpy (&place_pub_hash_ascii.encoding,
881 GNUNET_h2s_full (&place_pub_hash), sizeof (place_pub_hash_ascii));
882
883 char *filename = NULL;
884 GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
885 dir_social, DIR_SEPARATOR,
886 "places", DIR_SEPARATOR,
887 ego_pub_hash_ascii.encoding, DIR_SEPARATOR,
888 place_pub_hash_ascii.encoding);
889 int ret = GNUNET_DISK_directory_create_for_file (filename);
890 if (GNUNET_OK != ret
891 || 0 > GNUNET_DISK_fn_write (filename, ereq, ntohs (ereq->header.size),
892 GNUNET_DISK_PERM_USER_READ
893 | GNUNET_DISK_PERM_USER_WRITE))
894 {
895 GNUNET_break (0);
896 ret = GNUNET_SYSERR;
897 }
898 GNUNET_free (filename);
731 899
732 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub; 900 if (ret == GNUNET_OK)
733 struct GNUNET_HashCode ego_pub_hash; 901 {
734 GNUNET_CRYPTO_ecdsa_key_get_public (ego_key, &ego_pub); 902 GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s%c" "%s",
735 GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash); 903 dir_social, DIR_SEPARATOR,
736 904 "apps", DIR_SEPARATOR,
737 place_add (&ego_pub_hash, &place_pub_hash, msg); 905 app_id, DIR_SEPARATOR,
738 906 ego_pub_hash_ascii.encoding, DIR_SEPARATOR,
739 char *ego_pub_hash_str = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1); 907 place_pub_hash_ascii.encoding);
740 char *place_pub_hash_str = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1); 908 ret = GNUNET_DISK_directory_create_for_file (filename);
741 memcpy (ego_pub_hash_str, GNUNET_h2s_full (&ego_pub_hash), sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); 909 if (GNUNET_OK != ret
742 memcpy (place_pub_hash_str, GNUNET_h2s_full (&place_pub_hash), sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); 910 || 0 > GNUNET_DISK_fn_write (filename, "", 0,
743 911 GNUNET_DISK_PERM_USER_READ
744 char *filename = GNUNET_malloc (strlen (dir_places) + 1 912 | GNUNET_DISK_PERM_USER_WRITE))
745 + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1 913 {
746 + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1); 914 GNUNET_break (0);
747 GNUNET_asprintf (&filename, 915 ret = GNUNET_SYSERR;
748 "%s%s%s%s%s", 916 }
749 dir_places, DIR_SEPARATOR_STR, 917 GNUNET_free (filename);
750 ego_pub_hash_str, DIR_SEPARATOR_STR, 918 }
751 place_pub_hash_str); 919 return ret;
920}
921
922
923int
924app_place_remove (const char *app_id,
925 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key)
926{
927 struct GNUNET_HashCode place_pub_hash;
928 GNUNET_CRYPTO_hash (place_pub_key, sizeof (*place_pub_key), &place_pub_hash);
929
930 struct GNUNET_CRYPTO_HashAsciiEncoded place_pub_hash_ascii;
931 memcpy (&place_pub_hash_ascii.encoding,
932 GNUNET_h2s_full (&place_pub_hash), sizeof (place_pub_hash_ascii));
933
934 char *app_place_filename = NULL;
935 GNUNET_asprintf (&app_place_filename,
936 "%s%c" "%s%/",
937 dir_social, DIR_SEPARATOR,
938 "apps", DIR_SEPARATOR,
939 app_id, DIR_SEPARATOR,
940 place_pub_hash_ascii.encoding);
941
942 struct GNUNET_HashCode app_id_hash;
943 GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
944
945 struct GNUNET_CONTAINER_MultiHashMap *
946 app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
752 947
753 GNUNET_DISK_directory_create_for_file (filename); 948 if (NULL != app_places)
754 if (GNUNET_DISK_fn_write (filename, msg, ntohs (msg->size), 949 GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL);
755 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE) < 0) 950
951 int ret = unlink (app_place_filename);
952 GNUNET_free (app_place_filename);
953 if (0 != ret)
756 { 954 {
757 GNUNET_break (0); 955 GNUNET_break (0);
956 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
957 "Error removing app place: unlink returned %d\n", errno);
958 return GNUNET_SYSERR;
758 } 959 }
759 960
760 GNUNET_free (ego_pub_hash_str); 961 return GNUNET_OK;
761 GNUNET_free (place_pub_hash_str);
762 GNUNET_free (filename);
763} 962}
764 963
765 964
@@ -772,35 +971,34 @@ place_save (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ego_key,
772 * Returned Host struct. 971 * Returned Host struct.
773 * 972 *
774 * @return #GNUNET_YES if the host entered the place just now, 973 * @return #GNUNET_YES if the host entered the place just now,
775 * #GNUNET_NO if the place is already entered. 974 * #GNUNET_NO if the place is already entered,
975 * #GNUNET_SYSERR if place_pub_key was set
976 * but its private key was not found
776 */ 977 */
777static int 978static int
778host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst) 979host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst)
779{ 980{
780 int ret = GNUNET_NO; 981 int ret = GNUNET_NO;
781 struct GNUNET_CRYPTO_EddsaPublicKey place_pub;
782 struct GNUNET_HashCode place_pub_hash; 982 struct GNUNET_HashCode place_pub_hash;
783 983 GNUNET_CRYPTO_hash (&hreq->place_pub_key, sizeof (hreq->place_pub_key),
784 GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub); 984 &place_pub_hash);
785 GNUNET_CRYPTO_hash (&place_pub, sizeof (place_pub), &place_pub_hash);
786
787 struct Host *hst = GNUNET_CONTAINER_multihashmap_get (hosts, &place_pub_hash); 985 struct Host *hst = GNUNET_CONTAINER_multihashmap_get (hosts, &place_pub_hash);
986
788 if (NULL == hst) 987 if (NULL == hst)
789 { 988 {
790 hst = GNUNET_new (struct Host); 989 hst = GNUNET_new (struct Host);
791 hst->policy = ntohl (hreq->policy); 990 hst->policy = hreq->policy;
792 hst->priv_key = hreq->place_key;
793 hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); 991 hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
794 992
795 struct Place *plc = &hst->plc; 993 struct Place *plc = &hst->plc;
994 place_init (plc);
796 plc->is_host = GNUNET_YES; 995 plc->is_host = GNUNET_YES;
797 plc->pub_key = place_pub; 996 plc->pub_key = hreq->place_pub_key;
798 plc->pub_key_hash = place_pub_hash; 997 plc->pub_key_hash = place_pub_hash;
799 place_init (plc);
800 998
801 GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc, 999 GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
802 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1000 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
803 hst->master = GNUNET_PSYC_master_start (cfg, &hst->priv_key, hst->policy, 1001 hst->master = GNUNET_PSYC_master_start (cfg, &hreq->place_key, hst->policy,
804 &psyc_master_started, 1002 &psyc_master_started,
805 &psyc_recv_join_request, 1003 &psyc_recv_join_request,
806 &psyc_recv_message, NULL, hst); 1004 &psyc_recv_message, NULL, hst);
@@ -821,10 +1019,41 @@ static void
821client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client, 1019client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
822 const struct GNUNET_MessageHeader *msg) 1020 const struct GNUNET_MessageHeader *msg)
823{ 1021{
824 const struct HostEnterRequest *hreq 1022 struct HostEnterRequest *hreq
825 = (const struct HostEnterRequest *) msg; 1023 = (struct HostEnterRequest *) GNUNET_copy_message (msg);
826 struct Place *plc; 1024
827 struct Host *hst; 1025 uint8_t app_id_size = ntohs (hreq->header.size) - sizeof (*hreq);
1026 const char *app_id = NULL;
1027 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &hreq[1],
1028 app_id_size, 1, &app_id);
1029 if (0 == offset || offset != app_id_size || app_id == NULL)
1030 {
1031 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1032 "offset = %u, app_id_size = %u, app_id = %s\n",
1033 offset, app_id_size, app_id);
1034 GNUNET_break (0);
1035 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1036 return;
1037 }
1038
1039 struct Host *hst = NULL;
1040 struct Place *plc = NULL;
1041 int ret = GNUNET_OK;
1042
1043 struct GNUNET_CRYPTO_EddsaPublicKey empty_pub_key;
1044 memset (&empty_pub_key, 0, sizeof (empty_pub_key));
1045
1046 if (0 == memcmp (&hreq->place_pub_key, &empty_pub_key, sizeof (empty_pub_key)))
1047 { // no public key set: create new private key & save the place
1048 struct GNUNET_CRYPTO_EddsaPrivateKey *
1049 place_key = GNUNET_CRYPTO_eddsa_key_create ();
1050 hreq->place_key = *place_key;
1051 GNUNET_CRYPTO_eddsa_key_get_public (place_key, &hreq->place_pub_key);
1052 GNUNET_CRYPTO_eddsa_key_clear (place_key);
1053 GNUNET_free (place_key);
1054
1055 app_place_save (app_id, (const struct PlaceEnterRequest *) hreq);
1056 }
828 1057
829 switch (host_enter (hreq, &hst)) 1058 switch (host_enter (hreq, &hst))
830 { 1059 {
@@ -835,40 +1064,32 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
835 case GNUNET_NO: 1064 case GNUNET_NO:
836 { 1065 {
837 plc = &hst->plc; 1066 plc = &hst->plc;
838 1067 client_send_host_enter_ack (client, hst, GNUNET_OK);
839 struct GNUNET_PSYC_CountersResultMessage res;
840 res.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK);
841 res.header.size = htons (sizeof (res));
842 res.result_code = htonl (GNUNET_OK);
843 res.max_message_id = GNUNET_htonll (plc->max_message_id);
844
845 GNUNET_SERVER_notification_context_add (nc, client);
846 GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
847 GNUNET_NO);
848 break; 1068 break;
849 } 1069 }
850 case GNUNET_SYSERR: 1070 case GNUNET_SYSERR:
851 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1071 ret = GNUNET_SYSERR;
852 return;
853 } 1072 }
854 1073
855 struct GNUNET_CRYPTO_EddsaPublicKey place_pub; 1074 if (ret != GNUNET_SYSERR)
856 GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub); 1075 {
857 1076
858 place_save (&hreq->host_key, &place_pub, msg); 1077 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1078 "%p Client connected as host to place %s.\n",
1079 hst, GNUNET_h2s (&plc->pub_key_hash));
859 1080
860 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1081 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
861 "%p Client connected as host to place %s.\n", 1082 cli->client = client;
862 hst, GNUNET_h2s (&plc->pub_key_hash)); 1083 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
863 1084
864 struct ClientListItem *cli = GNUNET_new (struct ClientListItem); 1085 struct Client *ctx = GNUNET_new (struct Client);
865 cli->client = client; 1086 ctx->plc = plc;
866 GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli); 1087 GNUNET_SERVER_client_set_user_context (client, ctx);
1088 }
867 1089
868 struct Client *ctx = GNUNET_new (struct Client); 1090 GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
869 ctx->plc = plc; 1091 GNUNET_free (hreq);
870 GNUNET_SERVER_client_set_user_context (client, ctx); 1092 GNUNET_SERVER_receive_done (client, ret);
871 GNUNET_SERVER_receive_done (client, GNUNET_OK);
872} 1093}
873 1094
874 1095
@@ -881,7 +1102,8 @@ client_recv_host_enter (void *cls, struct GNUNET_SERVER_Client *client,
881 * Returned Guest struct. 1102 * Returned Guest struct.
882 * 1103 *
883 * @return #GNUNET_YES if the guest entered the place just now, 1104 * @return #GNUNET_YES if the guest entered the place just now,
884 * #GNUNET_NO if the place is already entered. 1105 * #GNUNET_NO if the place is already entered,
1106 * #GNUNET_SYSERR on error.
885 */ 1107 */
886static int 1108static int
887guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) 1109guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
@@ -889,44 +1111,68 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
889 int ret = GNUNET_NO; 1111 int ret = GNUNET_NO;
890 uint16_t greq_size = ntohs (greq->header.size); 1112 uint16_t greq_size = ntohs (greq->header.size);
891 1113
892 struct GNUNET_CRYPTO_EcdsaPublicKey gst_pub_key; 1114 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key = greq->ego_pub_key;
893 struct GNUNET_HashCode place_pub_hash, gst_pub_key_hash; 1115 struct GNUNET_HashCode ego_pub_hash;
894 GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &gst_pub_key); 1116 GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
895 GNUNET_CRYPTO_hash (&gst_pub_key, sizeof (gst_pub_key), &gst_pub_key_hash); 1117 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
896 GNUNET_CRYPTO_hash (&greq->place_key, sizeof (greq->place_key), &place_pub_hash); 1118
1119 if (NULL == ego)
1120 return GNUNET_SYSERR;
1121
1122 struct GNUNET_HashCode place_pub_hash;
1123 GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key),
1124 &place_pub_hash);
897 1125
898 struct GNUNET_CONTAINER_MultiHashMap * 1126 struct GNUNET_CONTAINER_MultiHashMap *
899 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &place_pub_hash); 1127 plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &place_pub_hash);
900 struct Guest *gst = NULL; 1128 struct Guest *gst = NULL;
901 struct Place *plc;
902 1129
903 if (NULL != plc_gst) 1130 if (NULL != plc_gst)
904 gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &gst_pub_key_hash); 1131 gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash);
905 1132
906 if (NULL == gst || NULL == gst->slave) 1133 if (NULL == gst || NULL == gst->slave)
907 { 1134 {
908 gst = GNUNET_new (struct Guest); 1135 gst = GNUNET_new (struct Guest);
909 gst->priv_key = greq->guest_key;
910 gst->pub_key = gst_pub_key;
911 gst->pub_key_hash = gst_pub_key_hash;
912 gst->origin = greq->origin; 1136 gst->origin = greq->origin;
913 gst->relay_count = ntohl (greq->relay_count); 1137 gst->relay_count = ntohl (greq->relay_count);
914 1138
1139 uint16_t len;
1140 uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
1141 const char *app_id = (const char *) &greq[1];
1142 const char *p = app_id;
1143
1144 len = strnlen (app_id, remaining);
1145 if (len == remaining)
1146 {
1147 GNUNET_break (0);
1148 return GNUNET_SYSERR;
1149 }
1150 p += len + 1;
1151 remaining -= len + 1;
1152
915 const struct GNUNET_PeerIdentity *relays = NULL; 1153 const struct GNUNET_PeerIdentity *relays = NULL;
916 uint16_t relay_size = gst->relay_count * sizeof (*relays); 1154 uint16_t relay_size = gst->relay_count * sizeof (*relays);
1155 if (remaining < relay_size)
1156 {
1157 GNUNET_break (0);
1158 return GNUNET_SYSERR;
1159 }
917 if (0 < relay_size) 1160 if (0 < relay_size)
918 relays = (const struct GNUNET_PeerIdentity *) &greq[1]; 1161 relays = (const struct GNUNET_PeerIdentity *) p;
1162 p += relay_size;
1163 remaining -= relay_size;
1164
919 struct GNUNET_PSYC_Message *join_msg = NULL; 1165 struct GNUNET_PSYC_Message *join_msg = NULL;
920 uint16_t join_msg_size = 0; 1166 uint16_t join_msg_size = 0;
921 1167
922 if (sizeof (*greq) + relay_size + sizeof (struct GNUNET_MessageHeader) 1168 if (sizeof (struct GNUNET_MessageHeader) <= remaining)
923 <= greq_size)
924 { 1169 {
925 join_msg = (struct GNUNET_PSYC_Message *) 1170 join_msg = (struct GNUNET_PSYC_Message *) p;
926 (((char *) &greq[1]) + relay_size);
927 join_msg_size = ntohs (join_msg->header.size); 1171 join_msg_size = ntohs (join_msg->header.size);
1172 p += join_msg_size;
1173 remaining -= join_msg_size;
928 } 1174 }
929 if (sizeof (*greq) + relay_size + join_msg_size != greq_size) 1175 if (0 != remaining)
930 { 1176 {
931 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1177 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
932 "%u + %u + %u != %u\n", 1178 "%u + %u + %u != %u\n",
@@ -935,17 +1181,20 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
935 GNUNET_free (gst); 1181 GNUNET_free (gst);
936 return GNUNET_SYSERR; 1182 return GNUNET_SYSERR;
937 } 1183 }
938 if (0 < gst->relay_count) 1184 if (0 < relay_size)
939 { 1185 {
940 gst->relays = GNUNET_malloc (relay_size); 1186 gst->relays = GNUNET_malloc (relay_size);
941 memcpy (gst->relays, &greq[1], relay_size); 1187 memcpy (gst->relays, relays, relay_size);
942 } 1188 }
943 1189
944 plc = &gst->plc; 1190 struct Place *plc = &gst->plc;
1191 place_init (plc);
945 plc->is_host = GNUNET_NO; 1192 plc->is_host = GNUNET_NO;
946 plc->pub_key = greq->place_key; 1193 plc->pub_key = greq->place_pub_key;
947 plc->pub_key_hash = place_pub_hash; 1194 plc->pub_key_hash = place_pub_hash;
948 place_init (plc); 1195 plc->ego_pub_key = ego_pub_key;
1196 plc->ego_pub_hash = ego_pub_hash;
1197 plc->ego_key = ego->key;
949 1198
950 if (NULL == plc_gst) 1199 if (NULL == plc_gst)
951 { 1200 {
@@ -953,12 +1202,12 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
953 (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst, 1202 (void) GNUNET_CONTAINER_multihashmap_put (place_guests, &plc->pub_key_hash, plc_gst,
954 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1203 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
955 } 1204 }
956 (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &gst->pub_key_hash, gst, 1205 (void) GNUNET_CONTAINER_multihashmap_put (plc_gst, &plc->ego_pub_hash, gst,
957 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1206 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
958 (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst, 1207 (void) GNUNET_CONTAINER_multihashmap_put (guests, &plc->pub_key_hash, gst,
959 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 1208 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
960 gst->slave 1209 gst->slave
961 = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &gst->priv_key, 1210 = GNUNET_PSYC_slave_join (cfg, &plc->pub_key, &plc->ego_key,
962 &gst->origin, gst->relay_count, gst->relays, 1211 &gst->origin, gst->relay_count, gst->relays,
963 &psyc_recv_message, NULL, &psyc_slave_connected, 1212 &psyc_recv_message, NULL, &psyc_slave_connected,
964 &psyc_recv_join_dcsn, gst, join_msg); 1213 &psyc_recv_join_dcsn, gst, join_msg);
@@ -981,6 +1230,18 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
981{ 1230{
982 const struct GuestEnterRequest * 1231 const struct GuestEnterRequest *
983 greq = (const struct GuestEnterRequest *) msg; 1232 greq = (const struct GuestEnterRequest *) msg;
1233
1234 uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
1235 const char *app_id = NULL;
1236 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &greq[1],
1237 remaining, 1, &app_id);
1238 if (0 == offset)
1239 {
1240 GNUNET_break (0);
1241 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1242 return;
1243 }
1244
984 struct Guest *gst = NULL; 1245 struct Guest *gst = NULL;
985 struct Place *plc = NULL; 1246 struct Place *plc = NULL;
986 1247
@@ -988,6 +1249,7 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
988 { 1249 {
989 case GNUNET_YES: 1250 case GNUNET_YES:
990 plc = &gst->plc; 1251 plc = &gst->plc;
1252 app_place_save (app_id, (const struct PlaceEnterRequest *) greq);
991 break; 1253 break;
992 1254
993 case GNUNET_NO: 1255 case GNUNET_NO:
@@ -1000,28 +1262,21 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
1000 res.result_code = htonl (GNUNET_OK); 1262 res.result_code = htonl (GNUNET_OK);
1001 res.max_message_id = GNUNET_htonll (plc->max_message_id); 1263 res.max_message_id = GNUNET_htonll (plc->max_message_id);
1002 1264
1003 GNUNET_SERVER_notification_context_add (nc, client); 1265 client_send_msg (client, &res.header);
1004 GNUNET_SERVER_notification_context_unicast (nc, client, &res.header,
1005 GNUNET_NO);
1006 if (NULL != gst->join_dcsn) 1266 if (NULL != gst->join_dcsn)
1007 { 1267 client_send_msg (client, &gst->join_dcsn->header);
1008 GNUNET_SERVER_notification_context_add (nc, client); 1268
1009 GNUNET_SERVER_notification_context_unicast (nc, client,
1010 &gst->join_dcsn->header,
1011 GNUNET_NO);
1012 }
1013 break; 1269 break;
1014 } 1270 }
1015 case GNUNET_SYSERR: 1271 case GNUNET_SYSERR:
1272 GNUNET_break (0);
1016 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1273 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1017 return; 1274 return;
1018 } 1275 }
1019 1276
1020 place_save (&greq->guest_key, &greq->place_key, msg);
1021
1022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 "%p Client connected as guest to place %s.\n", 1278 "%p Client connected as guest to place %s.\n",
1024 gst, GNUNET_h2s (&gst->plc.pub_key_hash)); 1279 gst, GNUNET_h2s (&plc->pub_key_hash));
1025 1280
1026 struct ClientListItem *cli = GNUNET_new (struct ClientListItem); 1281 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
1027 cli->client = client; 1282 cli->client = client;
@@ -1034,16 +1289,159 @@ client_recv_guest_enter (void *cls, struct GNUNET_SERVER_Client *client,
1034} 1289}
1035 1290
1036 1291
1292struct GuestEnterByNameClosure
1293{
1294 struct GNUNET_SERVER_Client *client;
1295 char *app_id;
1296 char *password;
1297 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
1298 struct GNUNET_MessageHeader *join_msg;
1299};
1300
1301
1302/**
1303 * Result of a GNS name lookup for entering a place.
1304 *
1305 * @see GNUNET_SOCIAL_guest_enter_by_name
1306 */
1307static void
1308gns_result_guest_enter (void *cls, uint32_t rd_count,
1309 const struct GNUNET_GNSRECORD_Data *rd)
1310{
1311 struct GuestEnterByNameClosure *gcls = cls;
1312 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1313 "%p GNS result: %u records.\n", gcls->client, rd_count);
1314
1315 const struct GNUNET_GNSRECORD_PlaceData *
1316 rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
1317
1318 if (0 == rd_count || rd->data_size < sizeof (*rec))
1319 {
1320 GNUNET_break (0);
1321 GNUNET_SERVER_receive_done (gcls->client, GNUNET_SYSERR);
1322 return;
1323 }
1324
1325 uint16_t relay_count = ntohl (rec->relay_count);
1326 struct GNUNET_PeerIdentity *relays = NULL;
1327
1328 if (0 < relay_count)
1329 {
1330 if (rd->data_size == sizeof (*rec) + relay_count * sizeof (struct GNUNET_PeerIdentity))
1331 {
1332 relays = (struct GNUNET_PeerIdentity *) &rec[1];
1333 }
1334 else
1335 {
1336 relay_count = 0;
1337 GNUNET_break_op (0);
1338 }
1339 }
1340
1341 uint16_t app_id_size = strlen (gcls->app_id) + 1;
1342 uint16_t relay_size = relay_count * sizeof (*relays);
1343 uint16_t join_msg_size = 0;
1344 if (NULL != gcls->join_msg)
1345 join_msg_size = ntohs (gcls->join_msg->size);
1346 uint16_t greq_size = sizeof (struct GuestEnterRequest)
1347 + app_id_size + relay_size + join_msg_size;
1348 struct GuestEnterRequest *greq = GNUNET_malloc (greq_size);
1349 greq->header.size = htons (greq_size);
1350 greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
1351 greq->ego_pub_key = gcls->ego_pub_key;
1352 greq->place_pub_key = rec->place_pub_key;
1353 greq->origin = rec->origin;
1354 greq->relay_count = rec->relay_count;
1355
1356 void *p = &greq[1];
1357 memcpy (p, gcls->app_id, app_id_size);
1358 p += app_id_size;
1359 memcpy (p, relays, relay_size);
1360 p += relay_size;
1361 memcpy (p, gcls->join_msg, join_msg_size);
1362
1363 client_recv_guest_enter (NULL, gcls->client, &greq->header);
1364
1365 GNUNET_free (gcls->app_id);
1366 if (NULL != gcls->password)
1367 GNUNET_free (gcls->password);
1368 if (NULL != gcls->join_msg)
1369 GNUNET_free (gcls->join_msg);
1370 GNUNET_free (gcls);
1371 GNUNET_free (greq);
1372}
1373
1374
1375/**
1376 * Handle a connecting client entering a place as guest using a GNS address.
1377 *
1378 * Look up GNS address and generate a GuestEnterRequest from that.
1379 */
1380static void
1381client_recv_guest_enter_by_name (void *cls, struct GNUNET_SERVER_Client *client,
1382 const struct GNUNET_MessageHeader *msg)
1383{
1384 const struct GuestEnterByNameRequest *
1385 greq = (const struct GuestEnterByNameRequest *) msg;
1386
1387 struct GuestEnterByNameClosure *gcls = GNUNET_malloc (sizeof (*gcls));
1388 gcls->client = client;
1389 gcls->ego_pub_key = greq->ego_pub_key;
1390
1391 const char *p = (const char *) &greq[1];
1392 const char *app_id = NULL, *password = NULL, *gns_name = NULL;
1393 uint16_t remaining = ntohs (greq->header.size) - sizeof (*greq);
1394 uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 3,
1395 &app_id,
1396 &gns_name,
1397 &password);
1398 p += offset;
1399 remaining -= offset;
1400
1401 if (0 != offset && sizeof (*gcls->join_msg) <= remaining)
1402 {
1403 gcls->join_msg = GNUNET_copy_message ((struct GNUNET_MessageHeader *) p);
1404 remaining -= ntohs (gcls->join_msg->size);
1405 }
1406
1407 if (0 == offset || 0 != remaining)
1408 {
1409 if (NULL != gcls->join_msg)
1410 GNUNET_free (gcls->join_msg);
1411 GNUNET_break (0);
1412 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1413 return;
1414 }
1415
1416 uint16_t app_id_size = strlen (app_id) + 1;
1417 gcls->app_id = GNUNET_malloc (app_id_size);
1418 memcpy (gcls->app_id, app_id, app_id_size);
1419
1420 uint16_t password_size = strlen (password);
1421 if (0 < password_size++)
1422 {
1423 gcls->password = GNUNET_malloc (password_size);
1424 memcpy (gcls->password, password, password_size);
1425 }
1426
1427 GNUNET_GNS_lookup (gns, gns_name, &greq->ego_pub_key,
1428 GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT,
1429 NULL, gns_result_guest_enter, gcls);
1430}
1431
1432
1037void 1433void
1038place_notify (struct GNUNET_MessageHeader *msg, 1434app_notify_place (struct GNUNET_MessageHeader *msg,
1039 struct GNUNET_SERVER_Client *client) 1435 struct GNUNET_SERVER_Client *client)
1040{ 1436{
1041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1042 "%p Sending place notification of type %u to client.\n", 1438 "%p Sending place notification of type %u to client.\n",
1043 client, ntohs (msg->type)); 1439 client, ntohs (msg->type));
1044 1440
1045 uint16_t msg_size = ntohs (msg->size); 1441 uint16_t msg_size = ntohs (msg->size);
1046 struct GNUNET_CRYPTO_EcdsaPublicKey place_pub; 1442 struct AppPlaceMessage amsg;
1443 amsg.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE);
1444 amsg.header.size = htons (sizeof (amsg));
1047 1445
1048 switch (ntohs (msg->type)) 1446 switch (ntohs (msg->type))
1049 { 1447 {
@@ -1051,77 +1449,181 @@ place_notify (struct GNUNET_MessageHeader *msg,
1051 if (msg_size < sizeof (struct HostEnterRequest)) 1449 if (msg_size < sizeof (struct HostEnterRequest))
1052 return; 1450 return;
1053 struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg; 1451 struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg;
1054 GNUNET_CRYPTO_ecdsa_key_get_public (&hreq->host_key, &place_pub); 1452 amsg.is_host = GNUNET_YES;
1453 amsg.ego_pub_key = hreq->ego_pub_key;
1454 amsg.place_pub_key = hreq->place_pub_key;
1055 break; 1455 break;
1056 1456
1057 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER: 1457 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
1058 if (msg_size < sizeof (struct GuestEnterRequest)) 1458 if (msg_size < sizeof (struct GuestEnterRequest))
1059 return; 1459 return;
1060 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg; 1460 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg;
1061 GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &place_pub); 1461 amsg.is_host = GNUNET_NO;
1462 amsg.ego_pub_key = greq->ego_pub_key;
1463 amsg.place_pub_key = greq->place_pub_key;
1062 break; 1464 break;
1063 1465
1064 default: 1466 default:
1065 return; 1467 return;
1066 } 1468 }
1067 1469
1068 GNUNET_SERVER_notification_context_add (nc, client); 1470 client_send_msg (client, &amsg.header);
1069 GNUNET_SERVER_notification_context_unicast (nc, client, msg, 1471}
1070 GNUNET_NO); 1472
1473
1474void
1475app_notify_ego (struct Ego *ego, struct GNUNET_SERVER_Client *client)
1476{
1477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1478 "%p Sending ego notification to client: %s\n",
1479 client, ego->name);
1480
1481 size_t name_size = strlen (ego->name) + 1;
1482 struct AppEgoMessage *emsg = GNUNET_malloc (sizeof (*emsg) + name_size);
1483 emsg->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO);
1484 emsg->header.size = htons (sizeof (*emsg) + name_size);
1485
1486 GNUNET_CRYPTO_ecdsa_key_get_public (&ego->key, &emsg->ego_pub_key);
1487 memcpy (&emsg[1], ego->name, name_size);
1488
1489 client_send_msg (client, &emsg->header);
1490 GNUNET_free (emsg);
1491}
1492
1493
1494int
1495app_place_entry (void *cls, const struct GNUNET_HashCode *key, void *value)
1496{
1497 struct GNUNET_MessageHeader *
1498 msg = GNUNET_CONTAINER_multihashmap_get (places, key);
1499 if (NULL != msg)
1500 app_notify_place (msg, cls);
1501 return GNUNET_YES;
1071} 1502}
1072 1503
1073 1504
1074int 1505int
1075map_entry_place (void *cls, const struct GNUNET_HashCode *key, void *value) 1506ego_entry (void *cls, const struct GNUNET_HashCode *key, void *value)
1076{ 1507{
1077 place_notify (value, cls); 1508 app_notify_ego (value, cls);
1078 return GNUNET_YES; 1509 return GNUNET_YES;
1079} 1510}
1080 1511
1081 1512
1082/** 1513/**
1083 * Handle a connecting client listening for entered places. 1514 * Handle application connection.
1084 */ 1515 */
1085static void 1516static void
1086client_recv_place_listen (void *cls, struct GNUNET_SERVER_Client *client, 1517client_recv_app_connect (void *cls, struct GNUNET_SERVER_Client *client,
1087 const struct GNUNET_MessageHeader *msg) 1518 const struct GNUNET_MessageHeader *msg)
1088{ 1519{
1089 const struct PlaceListenRequest *req 1520 const struct AppConnectRequest *creq
1090 = (const struct PlaceListenRequest *) msg; 1521 = (const struct AppConnectRequest *) msg;
1522
1523 uint8_t app_id_size = ntohs (creq->header.size) - sizeof (*creq);
1524 const char *app_id = NULL;
1525 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &creq[1],
1526 app_id_size, 1, &app_id);
1527 if (0 == offset || offset != app_id_size)
1528 {
1529 GNUNET_break (0);
1530 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1531 return;
1532 }
1091 1533
1092 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub; 1534 struct GNUNET_HashCode app_id_hash;
1093 struct GNUNET_HashCode ego_pub_hash; 1535 GNUNET_CRYPTO_hash (app_id, app_id_size, &app_id_hash);
1094 1536
1095 GNUNET_CRYPTO_ecdsa_key_get_public (&req->ego_key, &ego_pub); 1537 GNUNET_CONTAINER_multihashmap_iterate (egos, ego_entry, client);
1096 GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash);
1097 1538
1098 struct GNUNET_CONTAINER_MultiHashMap * 1539 struct GNUNET_CONTAINER_MultiHashMap *
1099 ego_places = GNUNET_CONTAINER_multihashmap_get (places_entered, &ego_pub_hash); 1540 app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
1100 if (NULL != ego_places) 1541 if (NULL != app_places)
1101 GNUNET_CONTAINER_multihashmap_iterate (ego_places, map_entry_place, client); 1542 GNUNET_CONTAINER_multihashmap_iterate (app_places, app_place_entry, client);
1102
1103 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1104 "%p Client connected to listen for entered places of ego %s.\n",
1105 NULL, GNUNET_h2s (&ego_pub_hash));
1106 1543
1107 struct ClientListItem *cli = GNUNET_new (struct ClientListItem); 1544 struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
1108 cli->client = client; 1545 cli->client = client;
1109 struct PlaceListener *pl = GNUNET_CONTAINER_multihashmap_get (place_listeners, 1546 struct Application *app = GNUNET_CONTAINER_multihashmap_get (apps,
1110 &ego_pub_hash); 1547 &app_id_hash);
1111 if (NULL == pl) { 1548 if (NULL == app) {
1112 pl = GNUNET_malloc (sizeof (*pl)); 1549 app = GNUNET_malloc (sizeof (*app));
1113 (void) GNUNET_CONTAINER_multihashmap_put (place_listeners, &ego_pub_hash, pl, 1550 (void) GNUNET_CONTAINER_multihashmap_put (apps, &app_id_hash, app,
1114 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 1551 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1115 } 1552 }
1116 GNUNET_CONTAINER_DLL_insert (pl->clients_head, pl->clients_tail, cli); 1553 GNUNET_CONTAINER_DLL_insert (app->clients_head, app->clients_tail, cli);
1554
1555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1556 "%p Application %s connected.\n", app, app_id);
1117 1557
1118 struct Client *ctx = GNUNET_new (struct Client); 1558 struct Client *ctx = GNUNET_new (struct Client);
1119 ctx->ego_key = req->ego_key; 1559 ctx->app_id = GNUNET_malloc (app_id_size);
1560 memcpy (ctx->app_id, app_id, app_id_size);
1561
1120 GNUNET_SERVER_client_set_user_context (client, ctx); 1562 GNUNET_SERVER_client_set_user_context (client, ctx);
1121 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1563 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1122} 1564}
1123 1565
1124 1566
1567/**
1568 * Handle application detach request.
1569 */
1570static void
1571client_recv_app_detach (void *cls, struct GNUNET_SERVER_Client *client,
1572 const struct GNUNET_MessageHeader *msg)
1573{
1574 struct Client *
1575 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
1576 GNUNET_assert (NULL != ctx);
1577
1578 const struct AppDetachRequest *req
1579 = (const struct AppDetachRequest *) msg;
1580
1581 int ret = app_place_remove (ctx->app_id, &req->place_pub_key);
1582 client_send_result (client, req->op_id, ret, NULL, 0);
1583
1584 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1585}
1586
1587
1588/**
1589 * Handle application detach request.
1590 */
1591static void
1592client_recv_place_leave (void *cls, struct GNUNET_SERVER_Client *client,
1593 const struct GNUNET_MessageHeader *msg)
1594{
1595 struct Client *
1596 ctx = GNUNET_SERVER_client_get_user_context (client, struct Client);
1597 GNUNET_assert (NULL != ctx);
1598 struct Place *plc = ctx->plc;
1599
1600 /* Disconnect all clients connected to the place */
1601 /* FIXME: disconnect from the network, but keep local connection for history access */
1602 struct ClientListItem *cli = plc->clients_head, *next;
1603 while (NULL != cli)
1604 {
1605 GNUNET_CONTAINER_DLL_remove (plc->clients_head, plc->clients_tail, cli);
1606 GNUNET_SERVER_client_disconnect (cli->client);
1607 next = cli->next;
1608 GNUNET_free (cli);
1609 cli = next;
1610 }
1611
1612 if (GNUNET_YES != plc->is_disconnected)
1613 {
1614 plc->is_disconnected = GNUNET_YES;
1615 if (NULL != plc->tmit_msgs_head)
1616 { /* Send pending messages to PSYC before cleanup. */
1617 psyc_transmit_message (plc);
1618 }
1619 else
1620 {
1621 cleanup_place (plc);
1622 }
1623 }
1624}
1625
1626
1125struct JoinDecisionClosure 1627struct JoinDecisionClosure
1126{ 1628{
1127 int32_t is_admitted; 1629 int32_t is_admitted;
@@ -1198,9 +1700,7 @@ send_message_ack (struct Place *plc, struct GNUNET_SERVER_Client *client)
1198 struct GNUNET_MessageHeader res; 1700 struct GNUNET_MessageHeader res;
1199 res.size = htons (sizeof (res)); 1701 res.size = htons (sizeof (res));
1200 res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK); 1702 res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK);
1201 1703 client_send_msg (client, &res);
1202 GNUNET_SERVER_notification_context_add (nc, client);
1203 GNUNET_SERVER_notification_context_unicast (nc, client, &res, GNUNET_NO);
1204} 1704}
1205 1705
1206 1706
@@ -1872,7 +2372,7 @@ psyc_recv_history_message (void *cls, uint64_t message_id, uint32_t flags,
1872 memcpy (&res[1], msg, size); 2372 memcpy (&res[1], msg, size);
1873 2373
1874 /** @todo FIXME: send only to requesting client */ 2374 /** @todo FIXME: send only to requesting client */
1875 client_send_msg (plc, &res->header); 2375 place_send_msg (plc, &res->header);
1876} 2376}
1877 2377
1878 2378
@@ -1977,7 +2477,7 @@ psyc_recv_state_var (void *cls,
1977 memcpy (&res[1], mod, size); 2477 memcpy (&res[1], mod, size);
1978 2478
1979 /** @todo FIXME: send only to requesting client */ 2479 /** @todo FIXME: send only to requesting client */
1980 client_send_msg (plc, &res->header); 2480 place_send_msg (plc, &res->header);
1981} 2481}
1982 2482
1983 2483
@@ -2059,6 +2559,130 @@ client_recv_state_get (void *cls, struct GNUNET_SERVER_Client *client,
2059} 2559}
2060 2560
2061 2561
2562static void
2563namestore_recv_records_store_result (void *cls, int32_t result,
2564 const char *err_msg)
2565{
2566 struct OperationClosure *ocls = cls;
2567 client_send_result (ocls->client, ocls->op_id, result, err_msg,
2568 (NULL != err_msg) ? strlen (err_msg) : 0);
2569 GNUNET_free (ocls);
2570}
2571
2572
2573/**
2574 * Handle request to add PLACE record to GNS zone.
2575 */
2576static void
2577client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client,
2578 const struct GNUNET_MessageHeader *msg)
2579{
2580 const struct ZoneAddPlaceRequest *preq
2581 = (const struct ZoneAddPlaceRequest *) msg;
2582
2583 uint16_t remaining = ntohs (preq->header.size) - sizeof (*preq);
2584 const char *p = (const char *) &preq[1];
2585 const char *name = NULL, *password = NULL;
2586 uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 2,
2587 &name, &password);
2588 remaining -= offset;
2589 p += offset;
2590 const struct GNUNET_PeerIdentity *
2591 relays = (const struct GNUNET_PeerIdentity *) p;
2592 uint16_t relay_size = ntohl (preq->relay_count) * sizeof (*relays);
2593
2594 if (0 == offset || remaining != relay_size)
2595 {
2596 GNUNET_break (0);
2597 client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
2598 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2599 return;
2600 }
2601
2602 struct GNUNET_GNSRECORD_Data rd = { };
2603 rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
2604 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2605 rd.expiration_time = GNUNET_ntohll (preq->expiration_time);
2606
2607 struct GNUNET_GNSRECORD_PlaceData *
2608 rec = GNUNET_malloc (sizeof (*rec) + relay_size);
2609 rec->place_pub_key = preq->place_pub_key;
2610 rec->origin = this_peer;
2611 rec->relay_count = preq->relay_count;
2612 memcpy (&rec[1], relays, relay_size);
2613
2614 rd.data = rec;
2615 rd.data_size = sizeof (*rec) + relay_size;
2616
2617 struct GNUNET_HashCode ego_pub_hash;
2618 GNUNET_CRYPTO_hash (&preq->ego_pub_key, sizeof (preq->ego_pub_key), &ego_pub_hash);
2619 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
2620 if (NULL == ego)
2621 {
2622 client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
2623 }
2624 else
2625 {
2626 struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls));
2627 ocls->client = client;
2628 ocls->op_id = preq->op_id;
2629 GNUNET_NAMESTORE_records_store (namestore, &ego->key,
2630 name, 1, &rd,
2631 namestore_recv_records_store_result, ocls);
2632 }
2633 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2634}
2635
2636
2637/**
2638 * Handle request to add PLACE record to GNS zone.
2639 */
2640static void
2641client_recv_zone_add_nym (void *cls, struct GNUNET_SERVER_Client *client,
2642 const struct GNUNET_MessageHeader *msg)
2643{
2644 const struct ZoneAddNymRequest *nreq
2645 = (const struct ZoneAddNymRequest *) msg;
2646
2647 uint16_t name_size = ntohs (nreq->header.size) - sizeof (*nreq);
2648 const char *name = NULL;
2649 uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &nreq[1],
2650 name_size, 1, &name);
2651 if (0 == offset || offset != name_size)
2652 {
2653 GNUNET_break (0);
2654 client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
2655 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2656 return;
2657 }
2658
2659 struct GNUNET_GNSRECORD_Data rd = { };
2660 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
2661 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2662 rd.expiration_time = GNUNET_ntohll (nreq->expiration_time);
2663 rd.data = &nreq->nym_pub_key;
2664 rd.data_size = sizeof (nreq->nym_pub_key);
2665
2666 struct GNUNET_HashCode ego_pub_hash;
2667 GNUNET_CRYPTO_hash (&nreq->ego_pub_key, sizeof (nreq->ego_pub_key), &ego_pub_hash);
2668 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
2669 if (NULL == ego)
2670 {
2671 client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
2672 }
2673 else
2674 {
2675 struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls));
2676 ocls->client = client;
2677 ocls->op_id = nreq->op_id;
2678 GNUNET_NAMESTORE_records_store (namestore, &ego->key,
2679 name, 1, &rd,
2680 namestore_recv_records_store_result, ocls);
2681 }
2682 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2683}
2684
2685
2062static const struct GNUNET_SERVER_MessageHandler handlers[] = { 2686static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2063 { &client_recv_host_enter, NULL, 2687 { &client_recv_host_enter, NULL,
2064 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 }, 2688 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 0 },
@@ -2066,6 +2690,9 @@ static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2066 { &client_recv_guest_enter, NULL, 2690 { &client_recv_guest_enter, NULL,
2067 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 }, 2691 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 0 },
2068 2692
2693 { &client_recv_guest_enter_by_name, NULL,
2694 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME, 0 },
2695
2069 { &client_recv_join_decision, NULL, 2696 { &client_recv_join_decision, NULL,
2070 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 }, 2697 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 },
2071 2698
@@ -2081,50 +2708,79 @@ static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2081 { &client_recv_state_get, NULL, 2708 { &client_recv_state_get, NULL,
2082 GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, 0 }, 2709 GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, 0 },
2083 2710
2084 { &client_recv_place_listen, NULL, 2711 { &client_recv_zone_add_place, NULL,
2085 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN, 0 }, 2712 GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE, 0 },
2713
2714 { &client_recv_zone_add_nym, NULL,
2715 GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM, 0 },
2716
2717 { &client_recv_app_connect, NULL,
2718 GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT, 0 },
2719
2720 { &client_recv_app_detach, NULL,
2721 GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH, 0 },
2722
2723 { &client_recv_place_leave, NULL,
2724 GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE, 0 },
2086 2725
2087 { NULL, NULL, 0, 0 } 2726 { NULL, NULL, 0, 0 }
2088}; 2727};
2089 2728
2090 2729
2730const char *
2731path_basename (const char *path)
2732{
2733 const char *basename = strrchr (path, DIR_SEPARATOR);
2734 if (NULL != basename)
2735 basename++;
2736
2737 if (NULL == basename || '\0' == basename)
2738 return NULL;
2739
2740 return basename;
2741}
2742
2743
2744struct PlaceLoadClosure
2745{
2746 const char *app_id;
2747 const char *ego_pub_hash_str;
2748};
2749
2750
2751/** Load a place file */
2091int 2752int
2092file_place_load (void *cls, const char *filename) 2753file_place_load (void *cls, const char *filename)
2093{ 2754{
2094 uint64_t fsize = 0; 2755 char *app_id = cls;
2756 uint64_t file_size = 0;
2095 if (GNUNET_OK != 2757 if (GNUNET_OK !=
2096 GNUNET_DISK_file_size (filename, &fsize, GNUNET_YES, GNUNET_YES) 2758 GNUNET_DISK_file_size (filename, &file_size, GNUNET_YES, GNUNET_YES)
2097 || fsize < sizeof (struct HostEnterRequest)) 2759 || file_size < sizeof (struct HostEnterRequest))
2098 return GNUNET_OK; 2760 return GNUNET_OK;
2099 2761
2100 struct GNUNET_MessageHeader *msg = GNUNET_malloc (fsize); 2762 struct PlaceEnterRequest *ereq = GNUNET_malloc (file_size);
2101 ssize_t rsize = GNUNET_DISK_fn_read (filename, msg, fsize); 2763 ssize_t read_size = GNUNET_DISK_fn_read (filename, ereq, file_size);
2102 if (rsize < 0 || (size_t) rsize < sizeof (*msg)) 2764 if (read_size < 0 || read_size < sizeof (*ereq))
2103 return GNUNET_OK; 2765 return GNUNET_OK;
2104 2766
2105 uint16_t msg_size = ntohs (msg->size); 2767 uint16_t ereq_size = ntohs (ereq->header.size);
2106 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub; 2768 if (read_size != ereq_size)
2107 struct GNUNET_CRYPTO_EddsaPublicKey place_pub; 2769 return GNUNET_OK;
2108 2770
2109 switch (ntohs (msg->type)) 2771 switch (ntohs (ereq->header.type))
2110 { 2772 {
2111 case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER: 2773 case GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER:
2112 if (msg_size < sizeof (struct HostEnterRequest)) 2774 if (ereq_size < sizeof (struct HostEnterRequest))
2113 return GNUNET_OK; 2775 return GNUNET_OK;
2114 struct HostEnterRequest *hreq = (struct HostEnterRequest *) msg; 2776 struct HostEnterRequest *hreq = (struct HostEnterRequest *) ereq;
2115 GNUNET_CRYPTO_ecdsa_key_get_public (&hreq->host_key, &ego_pub);
2116 GNUNET_CRYPTO_eddsa_key_get_public (&hreq->place_key, &place_pub);
2117
2118 host_enter (hreq, NULL); 2777 host_enter (hreq, NULL);
2119 break; 2778 break;
2120 2779
2121 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER: 2780 case GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER:
2122 if (msg_size < sizeof (struct GuestEnterRequest)) 2781 if (ereq_size < sizeof (struct GuestEnterRequest))
2123 return GNUNET_OK; 2782 return GNUNET_OK;
2124 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) msg; 2783 struct GuestEnterRequest *greq = (struct GuestEnterRequest *) ereq;
2125 GNUNET_CRYPTO_ecdsa_key_get_public (&greq->guest_key, &ego_pub);
2126 place_pub = greq->place_key;
2127
2128 guest_enter (greq, NULL); 2784 guest_enter (greq, NULL);
2129 break; 2785 break;
2130 2786
@@ -2132,40 +2788,135 @@ file_place_load (void *cls, const char *filename)
2132 return GNUNET_OK; 2788 return GNUNET_OK;
2133 } 2789 }
2134 2790
2135 struct GNUNET_HashCode ego_pub_hash, place_pub_hash; 2791 app_place_add (app_id, ereq);
2136 GNUNET_CRYPTO_hash (&ego_pub, sizeof (ego_pub), &ego_pub_hash); 2792 return GNUNET_OK;
2137 GNUNET_CRYPTO_hash (&place_pub, sizeof (place_pub), &place_pub_hash); 2793}
2794
2795
2796/** Load an ego place file */
2797int
2798file_ego_place_load (void *cls, const char *place_filename)
2799{
2800 struct PlaceLoadClosure *plcls = cls;
2138 2801
2139 place_add (&ego_pub_hash, &place_pub_hash, msg); 2802 const char *place_pub_hash_str = path_basename (place_filename);
2803 if (NULL == place_pub_hash_str)
2804 {
2805 GNUNET_break (0);
2806 return GNUNET_OK;
2807 }
2808
2809 char *filename = NULL;
2810 GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
2811 dir_social, DIR_SEPARATOR,
2812 "places", DIR_SEPARATOR,
2813 plcls->ego_pub_hash_str, DIR_SEPARATOR,
2814 place_pub_hash_str);
2815
2816 struct PlaceEnterRequest ereq[GNUNET_SERVER_MAX_MESSAGE_SIZE];
2817
2818 int read_size = GNUNET_DISK_fn_read (filename, &ereq,
2819 GNUNET_SERVER_MAX_MESSAGE_SIZE);
2820 GNUNET_free (filename);
2821
2822 if (read_size < (ssize_t) sizeof (ereq))
2823 return GNUNET_OK;
2824
2825 app_place_add (plcls->app_id, ereq);
2140 return GNUNET_OK; 2826 return GNUNET_OK;
2141} 2827}
2142 2828
2143 2829
2830/**
2831 * Read @e place_pub_hash_str entries in @a dir_ego
2832 *
2833 * @param dir_ego
2834 * Data directory of an application ego.
2835 * e.g. ~/.local/share/gnunet/social/apps/$app_id/$ego_pub_hash_str/
2836 */
2837int
2838scan_app_ego_dir (void *cls, const char *dir_ego)
2839{
2840 struct PlaceLoadClosure *plcls = cls;
2841 plcls->ego_pub_hash_str = path_basename (dir_ego);
2842
2843 if (NULL != plcls->ego_pub_hash_str)
2844 GNUNET_DISK_directory_scan (dir_ego, file_ego_place_load, plcls);
2845
2846 return GNUNET_OK;
2847}
2848
2849/**
2850 * Read @e ego_pub_hash_str entries in @a dir_app
2851 *
2852 * @param dir_app
2853 * Data directory of an application.
2854 * e.g. ~/.local/share/gnunet/social/apps/$app_id/
2855 */
2144int 2856int
2145load_places_of_ego (void *cls, const char *dir_ego) 2857scan_app_dir (void *cls, const char *dir_app)
2146{ 2858{
2147 if (GNUNET_YES != GNUNET_DISK_directory_test (dir_ego, GNUNET_YES)) 2859 if (GNUNET_YES != GNUNET_DISK_directory_test (dir_app, GNUNET_YES))
2148 return GNUNET_OK; 2860 return GNUNET_OK;
2149 2861
2150 GNUNET_DISK_directory_scan (dir_ego, file_place_load, NULL); 2862 struct PlaceLoadClosure plcls;
2863 plcls.app_id = path_basename (dir_app);
2864
2865 if (NULL != plcls.app_id)
2866 GNUNET_DISK_directory_scan (dir_app, scan_app_ego_dir, &plcls);
2867
2151 return GNUNET_OK; 2868 return GNUNET_OK;
2152} 2869}
2153 2870
2154 2871
2155void 2872static void
2156load_places () 2873identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego,
2874 void **ctx, const char *name)
2157{ 2875{
2158 if (GNUNET_OK != 2876 if (NULL == id_ego) // end of initial list of egos
2159 GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "PLACES_DIR",
2160 &dir_places))
2161 {
2162 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "social", "PLACES_DIR");
2163 GNUNET_break (0);
2164 return; 2877 return;
2878
2879 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
2880 GNUNET_IDENTITY_ego_get_public_key (id_ego, &ego_pub_key);
2881
2882 struct GNUNET_HashCode ego_pub_hash;
2883 GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
2884
2885 struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
2886 if (NULL != ego)
2887 {
2888 GNUNET_free (ego->name);
2889 if (NULL == name) // deleted
2890 {
2891 GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego);
2892 GNUNET_free (ego);
2893 ego = NULL;
2894 }
2895 }
2896 else
2897 {
2898 ego = GNUNET_malloc (sizeof (*ego));
2165 } 2899 }
2900 if (NULL != ego)
2901 {
2902 ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego));
2903 size_t name_size = strlen (name) + 1;
2904 ego->name = GNUNET_malloc (name_size);
2905 memcpy (ego->name, name, name_size);
2166 2906
2167 places_entered = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO); 2907 GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego,
2168 GNUNET_DISK_directory_scan (dir_places, load_places_of_ego, NULL); 2908 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
2909 }
2910}
2911
2912
2913/**
2914 * Connected to core service.
2915 */
2916static void
2917core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
2918{
2919 this_peer = *my_identity;
2169} 2920}
2170 2921
2171 2922
@@ -2181,12 +2932,38 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
2181 const struct GNUNET_CONFIGURATION_Handle *c) 2932 const struct GNUNET_CONFIGURATION_Handle *c)
2182{ 2933{
2183 cfg = c; 2934 cfg = c;
2184 stats = GNUNET_STATISTICS_create ("social", cfg); 2935
2185 hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 2936 hosts = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2186 guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 2937 guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2187 place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); 2938 place_guests = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2188 place_listeners = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); 2939
2189 load_places (); 2940 egos = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2941 apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2942 places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
2943 apps_places = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_NO);
2944
2945 core = GNUNET_CORE_connect (cfg, NULL, core_connected, NULL, NULL,
2946 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
2947 id = GNUNET_IDENTITY_connect (cfg, &identity_recv_ego, NULL);
2948 gns = GNUNET_GNS_connect (cfg);
2949 namestore = GNUNET_NAMESTORE_connect (cfg);
2950 stats = GNUNET_STATISTICS_create ("social", cfg);
2951
2952 if (GNUNET_OK !=
2953 GNUNET_CONFIGURATION_get_value_filename (cfg, "social", "SOCIAL_DATA_DIR",
2954 &dir_social))
2955 {
2956 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
2957 "social", "SOCIAL_DATA_DIR");
2958 GNUNET_break (0);
2959 return;
2960 }
2961 GNUNET_asprintf (&dir_places, "%s%c%s",
2962 dir_social, DIR_SEPARATOR, "places");
2963 GNUNET_asprintf (&dir_apps, "%s%c%s",
2964 dir_social, DIR_SEPARATOR, "apps");
2965
2966 GNUNET_DISK_directory_scan (dir_apps, scan_app_dir, NULL);
2190 2967
2191 nc = GNUNET_SERVER_notification_context_create (server, 1); 2968 nc = GNUNET_SERVER_notification_context_create (server, 1);
2192 GNUNET_SERVER_add_handlers (server, handlers); 2969 GNUNET_SERVER_add_handlers (server, handlers);
diff --git a/src/social/social.h b/src/social/social.h
index 6dfd55612..651338c51 100644
--- a/src/social/social.h
+++ b/src/social/social.h
@@ -49,6 +49,37 @@ GNUNET_NETWORK_STRUCT_BEGIN
49/**** library -> service ****/ 49/**** library -> service ****/
50 50
51 51
52struct AppConnectRequest
53{
54 /**
55 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT
56 */
57 struct GNUNET_MessageHeader header;
58
59 /* Followed by char *app_id */
60};
61
62
63struct AppDetachRequest
64{
65 /**
66 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH
67 */
68 struct GNUNET_MessageHeader header;
69
70 /**
71 * Public key of place.
72 */
73 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
74
75 /**
76 * Operation ID.
77 */
78 uint64_t op_id GNUNET_PACKED;
79
80};
81
82
52struct HostEnterRequest 83struct HostEnterRequest
53{ 84{
54 /** 85 /**
@@ -58,46 +89,179 @@ struct HostEnterRequest
58 89
59 uint32_t policy GNUNET_PACKED; 90 uint32_t policy GNUNET_PACKED;
60 91
61 struct GNUNET_CRYPTO_EcdsaPrivateKey host_key; 92 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
93
94 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
62 95
63 struct GNUNET_CRYPTO_EddsaPrivateKey place_key; 96 struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
97
98 /* Followed by char *app_id */
64}; 99};
65 100
66 101
67struct GuestEnterRequest 102struct GuestEnterRequest
68{ 103{
69 /** 104 /**
70 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ADDR 105 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER
71 */ 106 */
72 struct GNUNET_MessageHeader header; 107 struct GNUNET_MessageHeader header;
73 108
74 uint32_t relay_count GNUNET_PACKED; 109 uint32_t relay_count GNUNET_PACKED;
75 110
76 struct GNUNET_CRYPTO_EcdsaPrivateKey guest_key; 111 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
77 112
78 struct GNUNET_CRYPTO_EddsaPublicKey place_key; 113 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
79 114
80 struct GNUNET_PeerIdentity origin; 115 struct GNUNET_PeerIdentity origin;
81 116
117 /* Followed by char *app_id */
82 /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ 118 /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */
119 /* Followed by struct GNUNET_MessageHeader *join_msg */
120};
121
83 122
84 /* Followed by struct GNUNET_MessageHeader join_msg */ 123/** Compatible parts of HostEnterRequest and GuestEnterRequest */
124struct PlaceEnterRequest
125{
126 struct GNUNET_MessageHeader header;
127
128 uint32_t reserved GNUNET_PACKED;
129
130 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
131
132 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
85}; 133};
86 134
87 135
88struct PlaceListenRequest 136struct EgoPlacePublicKey
137{
138 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
139 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
140};
141
142
143struct GuestEnterByNameRequest
89{ 144{
90 /** 145 /**
91 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN 146 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME
92 */ 147 */
93 struct GNUNET_MessageHeader header; 148 struct GNUNET_MessageHeader header;
94 149
95 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key; 150 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
151
152 /* Followed by char *app_id */
153 /* Followed by char *gns_name */
154 /* Followed by char *password */
155 /* Followed by struct GNUNET_MessageHeader *join_msg */
96}; 156};
97 157
98 158
159struct ZoneAddPlaceRequest
160{
161 struct GNUNET_MessageHeader header;
162
163 uint32_t relay_count GNUNET_PACKED;
164
165 /**
166 * Operation ID.
167 */
168 uint64_t op_id;
169
170 /**
171 * Expiration time: absolute value in us.
172 */
173 uint64_t expiration_time;
174
175 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
176
177 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
178
179 struct GNUNET_PeerIdentity origin;
180
181 /* Followed by const char *name */
182 /* Followed by const char *password */
183 /* Followed by struct GNUNET_PeerIdentity *relays[relay_count] */
184};
185
186
187struct ZoneAddNymRequest
188{
189 struct GNUNET_MessageHeader header;
190
191 /**
192 * Operation ID.
193 */
194 uint64_t op_id;
195
196 /**
197 * Expiration time: absolute value in us.
198 */
199 uint64_t expiration_time;
200
201 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
202
203 struct GNUNET_CRYPTO_EcdsaPublicKey nym_pub_key;
204
205 /* Followed by const char *name */
206};
207
99/**** service -> library ****/ 208/**** service -> library ****/
100 209
210
211struct AppEgoMessage
212{
213 /**
214 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO
215 */
216 struct GNUNET_MessageHeader header;
217
218 /**
219 * Public key of ego.
220 */
221 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
222
223 /* Followed by char *name */
224};
225
226
227struct AppPlaceMessage
228{
229 /**
230 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE
231 */
232 struct GNUNET_MessageHeader header;
233
234 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
235
236 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
237
238 uint8_t is_host;
239};
240
241
242struct HostEnterAck {
243 /**
244 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK
245 */
246 struct GNUNET_MessageHeader header;
247
248 /**
249 * Status code for the operation.
250 */
251 uint32_t result_code GNUNET_PACKED;
252
253 /**
254 * Last message ID sent to the channel.
255 */
256 uint64_t max_message_id GNUNET_PACKED;
257
258 /**
259 * Public key of the place.
260 */
261 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
262};
263
264
101#if REMOVE 265#if REMOVE
102struct NymEnterRequest 266struct NymEnterRequest
103{ 267{
@@ -105,6 +269,7 @@ struct NymEnterRequest
105 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER 269 * Type: GNUNET_MESSAGE_TYPE_SOCIAL_NYM_ENTER
106 */ 270 */
107 struct GNUNET_MessageHeader header; 271 struct GNUNET_MessageHeader header;
272
108 /** 273 /**
109 * Public key of the joining slave. 274 * Public key of the joining slave.
110 */ 275 */
diff --git a/src/social/social_api.c b/src/social/social_api.c
index 9a2f99ae8..6c85ba294 100644
--- a/src/social/social_api.c
+++ b/src/social/social_api.c
@@ -30,10 +30,6 @@
30#include "platform.h" 30#include "platform.h"
31#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
32#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"
37#include "gnunet_psyc_service.h" 33#include "gnunet_psyc_service.h"
38#include "gnunet_psyc_util_lib.h" 34#include "gnunet_psyc_util_lib.h"
39#include "gnunet_social_service.h" 35#include "gnunet_social_service.h"
@@ -41,11 +37,15 @@
41 37
42#define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__) 38#define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__)
43 39
44 40/**
45static struct GNUNET_CORE_Handle *core; 41 * Handle for an ego.
46static struct GNUNET_GNS_Handle *gns; 42 */
47static struct GNUNET_NAMESTORE_Handle *namestore; 43struct GNUNET_SOCIAL_Ego
48static struct GNUNET_PeerIdentity this_peer; 44{
45 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
46 struct GNUNET_HashCode pub_key_hash;
47 char *name;
48};
49 49
50 50
51/** 51/**
@@ -59,6 +59,76 @@ struct GNUNET_SOCIAL_Nym
59 59
60 60
61/** 61/**
62 * Handle for an application.
63 */
64struct GNUNET_SOCIAL_App
65{
66 /**
67 * Configuration to use.
68 */
69 const struct GNUNET_CONFIGURATION_Handle *cfg;
70
71 /**
72 * Client connection to the service.
73 */
74 struct GNUNET_CLIENT_MANAGER_Connection *client;
75
76 /**
77 * Message to send on reconnect.
78 */
79 struct GNUNET_MessageHeader *connect_msg;
80
81 /**
82 * Function called after disconnected from the service.
83 */
84 GNUNET_ContinuationCallback disconnect_cb;
85
86 /**
87 * Closure for @a disconnect_cb.
88 */
89 void *disconnect_cls;
90
91 /**
92 * Application ID.
93 */
94 char *id;
95
96 /**
97 * Hash map of all egos.
98 * pub_key_hash -> struct GNUNET_SOCIAL_Ego *
99 */
100 struct GNUNET_CONTAINER_MultiHashMap *egos;
101
102 GNUNET_SOCIAL_AppEgoCallback ego_cb;
103 GNUNET_SOCIAL_AppHostPlaceCallback host_cb;
104 GNUNET_SOCIAL_AppGuestPlaceCallback guest_cb;
105 void *cb_cls;
106
107 /**
108 * Is this place in the process of disconnecting from the service?
109 * #GNUNET_YES or #GNUNET_NO
110 */
111 uint8_t is_disconnecting;
112};
113
114
115struct GNUNET_SOCIAL_HostConnection
116{
117 struct GNUNET_SOCIAL_App *app;
118
119 struct AppPlaceMessage plc_msg;
120};
121
122
123struct GNUNET_SOCIAL_GuestConnection
124{
125 struct GNUNET_SOCIAL_App *app;
126
127 struct AppPlaceMessage plc_msg;
128};
129
130
131/**
62 * Handle for a place where social interactions happen. 132 * Handle for a place where social interactions happen.
63 */ 133 */
64struct GNUNET_SOCIAL_Place 134struct GNUNET_SOCIAL_Place
@@ -109,9 +179,9 @@ struct GNUNET_SOCIAL_Place
109 struct GNUNET_CRYPTO_EddsaPublicKey pub_key; 179 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
110 180
111 /** 181 /**
112 * Private key of the ego. 182 * Public key of the ego.
113 */ 183 */
114 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key; 184 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
115 185
116 /** 186 /**
117 * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)? 187 * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)?
@@ -133,8 +203,6 @@ struct GNUNET_SOCIAL_Host
133{ 203{
134 struct GNUNET_SOCIAL_Place plc; 204 struct GNUNET_SOCIAL_Place plc;
135 205
136 struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
137
138 /** 206 /**
139 * Receipt handle. 207 * Receipt handle.
140 */ 208 */
@@ -190,19 +258,6 @@ struct GNUNET_SOCIAL_Guest
190 258
191 259
192/** 260/**
193 * Handle for place notifications.
194 */
195struct GNUNET_SOCIAL_PlaceListenHandle
196{
197 struct GNUNET_SOCIAL_Place plc;
198
199 GNUNET_SOCIAL_PlaceNotifyHostCallback notify_host;
200 GNUNET_SOCIAL_PlaceNotifyGuestCallback notify_guest;
201 void *notify_cls;
202};
203
204
205/**
206 * Hash map of all nyms. 261 * Hash map of all nyms.
207 * pub_key_hash -> struct GNUNET_SOCIAL_Nym * 262 * pub_key_hash -> struct GNUNET_SOCIAL_Nym *
208 */ 263 */
@@ -417,6 +472,22 @@ struct GNUNET_SOCIAL_LookHandle
417}; 472};
418 473
419 474
475struct ZoneAddPlaceHandle
476{
477 struct ZoneAddPlaceRequest *req;
478 GNUNET_ResultCallback result_cb;
479 void *result_cls;
480};
481
482
483struct ZoneAddNymHandle
484{
485 struct ZoneAddNymRequest *req;
486 GNUNET_ResultCallback result_cb;
487 void *result_cls;
488};
489
490
420/*** NYM ***/ 491/*** NYM ***/
421 492
422static struct GNUNET_SOCIAL_Nym * 493static struct GNUNET_SOCIAL_Nym *
@@ -1012,6 +1083,31 @@ GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
1012 GNUNET_free (slicer); 1083 GNUNET_free (slicer);
1013} 1084}
1014 1085
1086/*** CLIENT ***/
1087
1088
1089static void
1090app_send_connect_msg (struct GNUNET_SOCIAL_App *app)
1091{
1092 uint16_t cmsg_size = ntohs (app->connect_msg->size);
1093 struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
1094 memcpy (cmsg, app->connect_msg, cmsg_size);
1095 GNUNET_CLIENT_MANAGER_transmit_now (app->client, cmsg);
1096}
1097
1098
1099static void
1100app_recv_disconnect (void *cls,
1101 struct GNUNET_CLIENT_MANAGER_Connection *client,
1102 const struct GNUNET_MessageHeader *msg)
1103{
1104 struct GNUNET_SOCIAL_App *
1105 app = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*app));
1106
1107 GNUNET_CLIENT_MANAGER_reconnect (client);
1108 app_send_connect_msg (app);
1109}
1110
1015 1111
1016/*** PLACE ***/ 1112/*** PLACE ***/
1017 1113
@@ -1066,6 +1162,32 @@ place_recv_result (void *cls,
1066 1162
1067 1163
1068static void 1164static void
1165app_recv_result (void *cls,
1166 struct GNUNET_CLIENT_MANAGER_Connection *client,
1167 const struct GNUNET_MessageHeader *msg)
1168{
1169 struct GNUNET_SOCIAL_App *
1170 app = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*app));
1171
1172 const struct GNUNET_OperationResultMessage *
1173 res = (const struct GNUNET_OperationResultMessage *) msg;
1174
1175 uint16_t size = ntohs (msg->size);
1176 if (size < sizeof (*res))
1177 { /* Error, message too small. */
1178 GNUNET_break (0);
1179 return;
1180 }
1181
1182 uint16_t data_size = size - sizeof (*res);
1183 const char *data = (0 < data_size) ? (const char *) &res[1] : NULL;
1184 GNUNET_CLIENT_MANAGER_op_result (app->client, GNUNET_ntohll (res->op_id),
1185 GNUNET_ntohll (res->result_code),
1186 data, data_size);
1187}
1188
1189
1190static void
1069op_recv_history_result (void *cls, int64_t result, 1191op_recv_history_result (void *cls, int64_t result,
1070 const void *err_msg, uint16_t err_msg_size) 1192 const void *err_msg, uint16_t err_msg_size)
1071{ 1193{
@@ -1261,11 +1383,13 @@ host_recv_enter_ack (void *cls,
1261 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client, 1383 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
1262 sizeof (struct GNUNET_SOCIAL_Place)); 1384 sizeof (struct GNUNET_SOCIAL_Place));
1263 1385
1264 struct GNUNET_PSYC_CountersResultMessage * 1386 struct HostEnterAck *hack = (struct HostEnterAck *) msg;
1265 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg; 1387 hst->plc.pub_key = hack->place_pub_key;
1266 int32_t result = ntohl (cres->result_code); 1388
1389 int32_t result = ntohl (hack->result_code);
1267 if (NULL != hst->enter_cb) 1390 if (NULL != hst->enter_cb)
1268 hst->enter_cb (hst->cb_cls, result, GNUNET_ntohll (cres->max_message_id)); 1391 hst->enter_cb (hst->cb_cls, result, &hack->place_pub_key,
1392 GNUNET_ntohll (hack->max_message_id));
1269} 1393}
1270 1394
1271 1395
@@ -1364,52 +1488,85 @@ guest_recv_join_decision (void *cls,
1364 1488
1365 1489
1366static void 1490static void
1367notify_recv_place_host (void *cls, 1491app_recv_ego (void *cls,
1368 struct GNUNET_CLIENT_MANAGER_Connection *client, 1492 struct GNUNET_CLIENT_MANAGER_Connection *client,
1369 const struct GNUNET_MessageHeader *msg) 1493 const struct GNUNET_MessageHeader *msg)
1370{ 1494{
1371 struct GNUNET_SOCIAL_PlaceListenHandle * 1495 struct GNUNET_SOCIAL_App *
1372 pl = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*pl)); 1496 app = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*app));
1373 if (NULL == pl->notify_host)
1374 return;
1375 1497
1376 struct HostEnterRequest * 1498 struct AppEgoMessage *
1377 hreq = (struct HostEnterRequest *) msg; 1499 emsg = (struct AppEgoMessage *) msg;
1378 1500
1379 pl->notify_host (pl->notify_cls, &hreq->place_key, ntohl (hreq->policy)); 1501 uint16_t name_size = ntohs (emsg->header.size) - sizeof (*emsg);
1502
1503 struct GNUNET_HashCode ego_pub_hash;
1504 GNUNET_CRYPTO_hash (&emsg->ego_pub_key, sizeof (emsg->ego_pub_key),
1505 &ego_pub_hash);
1506
1507 struct GNUNET_SOCIAL_Ego *
1508 ego = GNUNET_CONTAINER_multihashmap_get (app->egos, &ego_pub_hash);
1509 if (NULL == ego)
1510 {
1511 ego = GNUNET_malloc (sizeof (*ego));
1512 ego->pub_key = emsg->ego_pub_key;
1513 ego->name = GNUNET_malloc (name_size);
1514 memcpy (ego->name, &emsg[1], name_size);
1515 }
1516 else
1517 {
1518 ego->name = GNUNET_realloc (ego->name, name_size);
1519 memcpy (ego->name, &emsg[1], name_size);
1520 }
1521
1522 GNUNET_CONTAINER_multihashmap_put (app->egos, &ego_pub_hash, ego,
1523 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1524
1525 if (NULL != app->ego_cb)
1526 app->ego_cb (app->cb_cls, ego, &ego->pub_key, ego->name);
1380} 1527}
1381 1528
1382 1529
1383static void 1530static void
1384notify_recv_place_guest (void *cls, 1531app_recv_place (void *cls,
1385 struct GNUNET_CLIENT_MANAGER_Connection *client, 1532 struct GNUNET_CLIENT_MANAGER_Connection *client,
1386 const struct GNUNET_MessageHeader *msg) 1533 const struct GNUNET_MessageHeader *msg)
1387{ 1534{
1388 struct GNUNET_SOCIAL_PlaceListenHandle * 1535 struct GNUNET_SOCIAL_App *
1389 pl = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*pl)); 1536 app = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*app));
1390 if (NULL == pl->notify_guest)
1391 return;
1392 1537
1393 struct GuestEnterRequest * 1538 struct AppPlaceMessage *
1394 greq = (struct GuestEnterRequest *) msg; 1539 pmsg = (struct AppPlaceMessage *) msg;
1395 uint16_t greq_size = ntohs (greq->header.size);
1396 1540
1397 const struct GNUNET_PeerIdentity *relays = NULL; 1541 if ((GNUNET_YES == pmsg->is_host && NULL == app->host_cb)
1398 uint16_t relay_count = ntohs (greq->relay_count); 1542 || (GNUNET_NO == pmsg->is_host && NULL == app->guest_cb))
1399 uint16_t relay_size = relay_count * sizeof (*relays); 1543 return;
1400 if (0 < relay_size)
1401 relays = (const struct GNUNET_PeerIdentity *) &greq[1];
1402 struct GNUNET_PSYC_Message *join_msg = NULL;
1403 1544
1404 if (sizeof (*greq) + relay_size + sizeof (struct GNUNET_MessageHeader) 1545 struct GNUNET_HashCode ego_pub_hash;
1405 <= greq_size) 1546 GNUNET_CRYPTO_hash (&pmsg->ego_pub_key, sizeof (pmsg->ego_pub_key),
1547 &ego_pub_hash);
1548 struct GNUNET_SOCIAL_Ego *
1549 ego = GNUNET_CONTAINER_multihashmap_get (app->egos, &ego_pub_hash);
1550 if (NULL == ego)
1406 { 1551 {
1407 join_msg = (struct GNUNET_PSYC_Message *) 1552 GNUNET_break (0);
1408 (((char *) &greq[1]) + relay_size); 1553 return;
1409 } 1554 }
1410 1555
1411 pl->notify_guest (pl->notify_cls, &greq->place_key, &greq->origin, 1556 if (GNUNET_YES == pmsg->is_host)
1412 relay_count, relays, join_msg); 1557 {
1558 struct GNUNET_SOCIAL_HostConnection *hconn = GNUNET_malloc (sizeof (*hconn));
1559 hconn->app = app;
1560 hconn->plc_msg = *pmsg;
1561 app->host_cb (app->cb_cls, hconn, ego, &pmsg->place_pub_key);
1562 }
1563 else
1564 {
1565 struct GNUNET_SOCIAL_GuestConnection *gconn = GNUNET_malloc (sizeof (*gconn));
1566 gconn->app = app;
1567 gconn->plc_msg = *pmsg;
1568 app->guest_cb (app->cb_cls, gconn, ego, &pmsg->place_pub_key);
1569 }
1413} 1570}
1414 1571
1415 1572
@@ -1417,7 +1574,7 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
1417{ 1574{
1418 { host_recv_enter_ack, NULL, 1575 { host_recv_enter_ack, NULL,
1419 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK, 1576 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
1420 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO }, 1577 sizeof (struct HostEnterAck), GNUNET_NO },
1421 1578
1422 { host_recv_enter_request, NULL, 1579 { host_recv_enter_request, NULL,
1423 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST, 1580 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
@@ -1490,15 +1647,21 @@ static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
1490 1647
1491 1648
1492 1649
1493static struct GNUNET_CLIENT_MANAGER_MessageHandler notify_handlers[] = 1650static struct GNUNET_CLIENT_MANAGER_MessageHandler app_handlers[] =
1494{ 1651{
1495 { notify_recv_place_host, NULL, 1652 { app_recv_ego, NULL,
1496 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER, 1653 GNUNET_MESSAGE_TYPE_SOCIAL_APP_EGO,
1497 sizeof (struct HostEnterRequest), GNUNET_NO }, 1654 sizeof (struct AppEgoMessage), GNUNET_YES },
1655
1656 { app_recv_place, NULL,
1657 GNUNET_MESSAGE_TYPE_SOCIAL_APP_PLACE,
1658 sizeof (struct AppPlaceMessage), GNUNET_NO },
1498 1659
1499 { notify_recv_place_guest, NULL, 1660 { app_recv_result, NULL,
1500 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER, 1661 GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE,
1501 sizeof (struct GuestEnterRequest), GNUNET_YES }, 1662 sizeof (struct GNUNET_OperationResultMessage), GNUNET_YES },
1663
1664 { app_recv_disconnect, NULL, 0, 0, GNUNET_NO },
1502 1665
1503 { NULL, NULL, 0, 0, GNUNET_NO } 1666 { NULL, NULL, 0, 0, GNUNET_NO }
1504}; 1667};
@@ -1515,22 +1678,6 @@ place_cleanup (struct GNUNET_SOCIAL_Place *plc)
1515 GNUNET_free (plc->connect_msg); 1678 GNUNET_free (plc->connect_msg);
1516 if (NULL != plc->disconnect_cb) 1679 if (NULL != plc->disconnect_cb)
1517 plc->disconnect_cb (plc->disconnect_cls); 1680 plc->disconnect_cb (plc->disconnect_cls);
1518
1519 if (NULL != core)
1520 {
1521 GNUNET_CORE_disconnect (core);
1522 core = NULL;
1523 }
1524 if (NULL != namestore)
1525 {
1526 GNUNET_NAMESTORE_disconnect (namestore);
1527 namestore = NULL;
1528 }
1529 if (NULL != gns)
1530 {
1531 GNUNET_GNS_disconnect (gns);
1532 gns = NULL;
1533 }
1534} 1681}
1535 1682
1536 1683
@@ -1539,8 +1686,16 @@ host_cleanup (void *cls)
1539{ 1686{
1540 struct GNUNET_SOCIAL_Host *hst = cls; 1687 struct GNUNET_SOCIAL_Host *hst = cls;
1541 place_cleanup (&hst->plc); 1688 place_cleanup (&hst->plc);
1542 GNUNET_PSYC_receive_destroy (hst->recv); 1689 if (NULL != hst->recv)
1543 GNUNET_SOCIAL_slicer_destroy (hst->slicer); 1690 {
1691 GNUNET_PSYC_receive_destroy (hst->recv);
1692 hst->recv = NULL;
1693 }
1694 if (NULL != hst->slicer)
1695 {
1696 GNUNET_SOCIAL_slicer_destroy (hst->slicer);
1697 hst->slicer = NULL;
1698 }
1544 GNUNET_free (hst); 1699 GNUNET_free (hst);
1545} 1700}
1546 1701
@@ -1568,11 +1723,13 @@ guest_cleanup (void *cls)
1568 * Identity of the host. 1723 * Identity of the host.
1569 * @param place_key 1724 * @param place_key
1570 * Private-public key pair of the place. 1725 * Private-public key pair of the place.
1571 * NULL for ephemeral places. 1726 * NULL to generate a key.
1572 * @param policy 1727 * @param policy
1573 * Policy specifying entry and history restrictions for the place. 1728 * Policy specifying entry and history restrictions for the place.
1574 * @param slicer 1729 * @param slicer
1575 * Slicer to handle incoming messages. 1730 * Slicer to handle incoming messages.
1731 * @param enter_cb
1732 * Function called when the place is entered and ready to use.
1576 * @param answer_door_cb 1733 * @param answer_door_cb
1577 * Function to handle new nyms that want to enter. 1734 * Function to handle new nyms that want to enter.
1578 * @param farewell_cb 1735 * @param farewell_cb
@@ -1583,9 +1740,8 @@ guest_cleanup (void *cls)
1583 * @return Handle for the host. 1740 * @return Handle for the host.
1584 */ 1741 */
1585struct GNUNET_SOCIAL_Host * 1742struct GNUNET_SOCIAL_Host *
1586GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, 1743GNUNET_SOCIAL_host_enter (const struct GNUNET_SOCIAL_App *app,
1587 const struct GNUNET_IDENTITY_Ego *ego, 1744 const struct GNUNET_SOCIAL_Ego *ego,
1588 const struct GNUNET_CRYPTO_EddsaPrivateKey *place_key,
1589 enum GNUNET_PSYC_Policy policy, 1745 enum GNUNET_PSYC_Policy policy,
1590 struct GNUNET_SOCIAL_Slicer *slicer, 1746 struct GNUNET_SOCIAL_Slicer *slicer,
1591 GNUNET_SOCIAL_HostEnterCallback enter_cb, 1747 GNUNET_SOCIAL_HostEnterCallback enter_cb,
@@ -1595,35 +1751,17 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1595{ 1751{
1596 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst)); 1752 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
1597 struct GNUNET_SOCIAL_Place *plc = &hst->plc; 1753 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1598 struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req));
1599
1600 if (NULL != place_key)
1601 {
1602 hst->place_key = *place_key;
1603 }
1604 else
1605 {
1606 struct GNUNET_CRYPTO_EddsaPrivateKey *
1607 ephemeral_key = GNUNET_CRYPTO_eddsa_key_create ();
1608 hst->place_key = *ephemeral_key;
1609 GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key);
1610 GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key);
1611 GNUNET_free (ephemeral_key);
1612 }
1613 1754
1614 plc->cfg = cfg; 1755 plc->cfg = app->cfg;
1615 plc->is_host = GNUNET_YES; 1756 plc->is_host = GNUNET_YES;
1616 plc->slicer = slicer; 1757 plc->slicer = slicer;
1617 1758
1618 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1619 GNUNET_CRYPTO_eddsa_key_get_public (place_key, &plc->pub_key);
1620
1621 hst->enter_cb = enter_cb; 1759 hst->enter_cb = enter_cb;
1622 hst->answer_door_cb = answer_door_cb; 1760 hst->answer_door_cb = answer_door_cb;
1623 hst->farewell_cb = farewell_cb; 1761 hst->farewell_cb = farewell_cb;
1624 hst->cb_cls = cls; 1762 hst->cb_cls = cls;
1625 1763
1626 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers); 1764 plc->client = GNUNET_CLIENT_MANAGER_connect (plc->cfg, "social", host_handlers);
1627 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc)); 1765 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
1628 1766
1629 plc->tmit = GNUNET_PSYC_transmit_create (plc->client); 1767 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
@@ -1636,13 +1774,15 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1636 NULL, host_recv_notice_place_leave_eom, hst); 1774 NULL, host_recv_notice_place_leave_eom, hst);
1637 hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer); 1775 hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer);
1638 1776
1639 req->header.size = htons (sizeof (*req)); 1777 uint16_t app_id_size = strlen (app->id) + 1;
1640 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER); 1778 struct HostEnterRequest *hreq = GNUNET_malloc (sizeof (*hreq) + app_id_size);
1641 req->policy = policy; 1779 hreq->header.size = htons (sizeof (*hreq) + app_id_size);
1642 req->place_key = hst->place_key; 1780 hreq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
1643 req->host_key = plc->ego_key; 1781 hreq->policy = policy;
1782 hreq->ego_pub_key = ego->pub_key;
1783 memcpy (&hreq[1], app->id, app_id_size);
1644 1784
1645 plc->connect_msg = (struct GNUNET_MessageHeader *) req; 1785 plc->connect_msg = &hreq->header;
1646 place_send_connect_msg (plc); 1786 place_send_connect_msg (plc);
1647 1787
1648 return hst; 1788 return hst;
@@ -1650,22 +1790,15 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1650 1790
1651 1791
1652/** 1792/**
1653 * Enter a place as host. 1793 * Reconnect to an already entered place as host.
1654 * 1794 *
1655 * A place is created upon first entering, and it is active until permanently 1795 * @param hconn
1656 * left using GNUNET_SOCIAL_host_leave(). 1796 * Host connection handle.
1657 * 1797 * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppHostPlaceCallback()
1658 * @param cfg
1659 * Configuration to contact the social service.
1660 * @param ego
1661 * Identity of the host.
1662 * @param gns_name
1663 * GNS name in the zone of the @a ego that contains the
1664 * public key of the place in a PLACE record.
1665 * @param policy
1666 * Policy specifying entry and history restrictions for the place.
1667 * @param slicer 1798 * @param slicer
1668 * Slicer to handle incoming messages. 1799 * Slicer to handle incoming messages.
1800 * @param enter_cb
1801 * Function called when the place is entered and ready to use.
1669 * @param answer_door_cb 1802 * @param answer_door_cb
1670 * Function to handle new nyms that want to enter. 1803 * Function to handle new nyms that want to enter.
1671 * @param farewell_cb 1804 * @param farewell_cb
@@ -1676,26 +1809,54 @@ GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1676 * @return Handle for the host. 1809 * @return Handle for the host.
1677 */ 1810 */
1678struct GNUNET_SOCIAL_Host * 1811struct GNUNET_SOCIAL_Host *
1679GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, 1812GNUNET_SOCIAL_host_enter_reconnect (struct GNUNET_SOCIAL_HostConnection *hconn,
1680 struct GNUNET_IDENTITY_Ego *ego, 1813 struct GNUNET_SOCIAL_Slicer *slicer,
1681 const char *gns_name, 1814 GNUNET_SOCIAL_HostEnterCallback enter_cb,
1682 enum GNUNET_PSYC_Policy policy, 1815 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
1683 struct GNUNET_SOCIAL_Slicer *slicer, 1816 GNUNET_SOCIAL_FarewellCallback farewell_cb,
1684 GNUNET_SOCIAL_HostEnterCallback enter_cb, 1817 void *cls)
1685 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb, 1818{
1686 GNUNET_SOCIAL_FarewellCallback farewell_cb, 1819 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
1687 void *cls) 1820 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1688{ 1821
1689 struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {}; 1822 size_t app_id_size = strlen (hconn->app->id) + 1;
1690 1823 struct HostEnterRequest *hreq = GNUNET_malloc (sizeof (*hreq) + app_id_size);
1691 /* FIXME: 1824
1692 * 1. get public key by looking up PLACE entry under gns_name 1825 hst->enter_cb = enter_cb;
1693 * in the zone of the ego. 1826 hst->answer_door_cb = answer_door_cb;
1694 * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH 1827 hst->farewell_cb = farewell_cb;
1695 */ 1828 hst->cb_cls = cls;
1829
1830 plc->cfg = hconn->app->cfg;
1831 plc->is_host = GNUNET_YES;
1832 plc->slicer = slicer;
1833 plc->pub_key = hconn->plc_msg.place_pub_key;
1834 plc->ego_pub_key = hconn->plc_msg.ego_pub_key;
1835
1836 plc->client = GNUNET_CLIENT_MANAGER_connect (plc->cfg, "social", host_handlers);
1837 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
1838
1839 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1840 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer);
1841
1842 hst->slicer = GNUNET_SOCIAL_slicer_create ();
1843 GNUNET_SOCIAL_slicer_method_add (hst->slicer, "_notice_place_leave",
1844 host_recv_notice_place_leave_method,
1845 host_recv_notice_place_leave_modifier,
1846 NULL, host_recv_notice_place_leave_eom, hst);
1847 hst->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, hst->slicer);
1848
1849 hreq->header.size = htons (sizeof (*hreq) + app_id_size);
1850 hreq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
1851 hreq->place_pub_key = hconn->plc_msg.place_pub_key;
1852 hreq->ego_pub_key = hconn->plc_msg.ego_pub_key;
1853 memcpy (&hreq[1], hconn->app->id, app_id_size);
1696 1854
1697 return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer, 1855 plc->connect_msg = &hreq->header;
1698 enter_cb, answer_door_cb, farewell_cb, cls); 1856 place_send_connect_msg (plc);
1857
1858 GNUNET_free (hconn);
1859 return hst;
1699} 1860}
1700 1861
1701 1862
@@ -1759,12 +1920,16 @@ GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
1759 * Host of the place. 1920 * Host of the place.
1760 * @param nym 1921 * @param nym
1761 * Handle for the entity to be ejected. 1922 * Handle for the entity to be ejected.
1923 * @param env
1924 * Environment for the message or NULL.
1762 */ 1925 */
1763void 1926void
1764GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *hst, 1927GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *hst,
1765 const struct GNUNET_SOCIAL_Nym *nym) 1928 const struct GNUNET_SOCIAL_Nym *nym,
1929 struct GNUNET_ENV_Environment *env)
1766{ 1930{
1767 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); 1931 if (NULL == env)
1932 env = GNUNET_ENV_environment_create ();
1768 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET, 1933 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET,
1769 "_nym", &nym->pub_key, sizeof (nym->pub_key)); 1934 "_nym", &nym->pub_key, sizeof (nym->pub_key));
1770 GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", env, NULL, NULL, 1935 GNUNET_SOCIAL_host_announce (hst, "_notice_place_leave", env, NULL, NULL,
@@ -1773,121 +1938,79 @@ GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *hst,
1773 1938
1774 1939
1775/** 1940/**
1776 * Get the public key of a @a nym. 1941 * Get the public key of @a ego.
1777 * 1942 *
1778 * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name(). 1943 * @param ego
1779 * 1944 * Ego.
1780 * @param nym
1781 * Pseudonym to map to a cryptographic identifier.
1782 * 1945 *
1783 * @return Public key of nym. 1946 * @return Public key of ego.
1784 */ 1947 */
1785const struct GNUNET_CRYPTO_EcdsaPublicKey * 1948const struct GNUNET_CRYPTO_EcdsaPublicKey *
1786GNUNET_SOCIAL_nym_get_key (const struct GNUNET_SOCIAL_Nym *nym) 1949GNUNET_SOCIAL_ego_get_pub_key (const struct GNUNET_SOCIAL_Ego *ego)
1787{ 1950{
1788 return &nym->pub_key; 1951 return &ego->pub_key;
1789} 1952}
1790 1953
1791 1954
1792/** 1955/**
1793 * Get the hash of the public key of a @a nym. 1956 * Get the hash of the public key of @a ego.
1794 * 1957 *
1795 * @param nym 1958 * @param ego
1796 * Pseudonym to map to a cryptographic identifier. 1959 * Ego.
1797 * 1960 *
1798 * @return Hash of the public key of nym. 1961 * @return Hash of the public key of @a ego.
1799 */ 1962 */
1800const struct GNUNET_HashCode * 1963const struct GNUNET_HashCode *
1801GNUNET_SOCIAL_nym_get_key_hash (const struct GNUNET_SOCIAL_Nym *nym) 1964GNUNET_SOCIAL_ego_get_pub_key_hash (const struct GNUNET_SOCIAL_Ego *ego)
1802{ 1965{
1803 return &nym->pub_key_hash; 1966 return &ego->pub_key_hash;
1804} 1967}
1805 1968
1806 1969
1807/** 1970/**
1808 * Obtain the private-public key pair of the hosted place. 1971 * Get the name of @a ego.
1809 *
1810 * The public part is suitable for storing in GNS within a PLACE record,
1811 * along with peer IDs to join at.
1812 * 1972 *
1813 * @param host 1973 * @param ego
1814 * Host of the place. 1974 * Ego.
1815 * 1975 *
1816 * @return Private-public key pair of the hosted place. 1976 * @return Public key of @a ego.
1817 */ 1977 */
1818const struct GNUNET_CRYPTO_EddsaPrivateKey * 1978const char *
1819GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst) 1979GNUNET_SOCIAL_ego_get_name (const struct GNUNET_SOCIAL_Ego *ego)
1820{ 1980{
1821 return &hst->place_key; 1981 return ego->name;
1822} 1982}
1823 1983
1824 1984
1825/** 1985/**
1826 * Connected to core service. 1986 * Get the public key of @a nym.
1987 *
1988 * Suitable, for example, to be used with GNUNET_SOCIAL_zone_add_nym().
1989 *
1990 * @param nym
1991 * Pseudonym.
1992 *
1993 * @return Public key of @a nym.
1827 */ 1994 */
1828static void 1995const struct GNUNET_CRYPTO_EcdsaPublicKey *
1829core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) 1996GNUNET_SOCIAL_nym_get_pub_key (const struct GNUNET_SOCIAL_Nym *nym)
1830{ 1997{
1831 this_peer = *my_identity; 1998 return &nym->pub_key;
1832 // FIXME
1833} 1999}
1834 2000
1835 2001
1836/** 2002/**
1837 * Advertise the place in the GNS zone of the @e ego of the @a host. 2003 * Get the hash of the public key of @a nym.
1838 * 2004 *
1839 * @param hst 2005 * @param nym
1840 * Host of the place. 2006 * Pseudonym.
1841 * @param name 2007 *
1842 * The name for the PLACE record to put in the zone. 2008 * @return Hash of the public key of @a nym.
1843 * @param peer_count
1844 * Number of elements in the @a peers array.
1845 * @param peers
1846 * List of peers to put in the PLACE record to advertise
1847 * as entry points to the place in addition to the origin.
1848 * @param expiration_time
1849 * Expiration time of the record, use 0 to remove the record.
1850 * @param password
1851 * Password used to encrypt the record or NULL to keep it cleartext.
1852 * @param result_cb
1853 * Function called with the result of the operation.
1854 * @param result_cls
1855 * Closure for @a result_cb
1856 */ 2009 */
1857void 2010const struct GNUNET_HashCode *
1858GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst, 2011GNUNET_SOCIAL_nym_get_pub_key_hash (const struct GNUNET_SOCIAL_Nym *nym)
1859 const char *name,
1860 uint32_t peer_count,
1861 const struct GNUNET_PeerIdentity *peers,
1862 struct GNUNET_TIME_Absolute expiration_time,
1863 const char *password,
1864 GNUNET_NAMESTORE_ContinuationWithStatus result_cb,
1865 void *result_cls)
1866{ 2012{
1867 struct GNUNET_SOCIAL_Place *plc = &hst->plc; 2013 return &nym->pub_key_hash;
1868 if (NULL == namestore)
1869 namestore = GNUNET_NAMESTORE_connect (plc->cfg);
1870 if (NULL == core)
1871 core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL,
1872 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1873
1874 struct GNUNET_GNSRECORD_Data rd = { };
1875 rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
1876 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1877 rd.expiration_time = expiration_time.abs_value_us;
1878
1879 struct GNUNET_GNSRECORD_PlaceData *
1880 rec = GNUNET_malloc (sizeof (*rec) + peer_count * sizeof (*peers));
1881 rec->place_key = plc->pub_key;
1882 rec->origin = this_peer;
1883 rec->relay_count = htonl (peer_count);
1884 memcpy (&rec[1], peers, peer_count * sizeof (*peers));
1885
1886 rd.data = rec;
1887 rd.data_size = sizeof (*rec) + peer_count * sizeof (*peers);
1888
1889 GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key,
1890 name, 1, &rd, result_cb, result_cls);
1891} 2014}
1892 2015
1893 2016
@@ -1966,65 +2089,117 @@ GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst)
1966} 2089}
1967 2090
1968 2091
2092
2093void
2094place_leave (struct GNUNET_SOCIAL_Place *plc)
2095{
2096 struct GNUNET_MessageHeader msg;
2097 msg.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
2098 msg.size = htons (sizeof (msg));
2099 GNUNET_CLIENT_MANAGER_transmit (plc->client, &msg);
2100}
2101
2102
2103void
2104place_disconnect (struct GNUNET_SOCIAL_Place *plc,
2105 GNUNET_ContinuationCallback disconnect_cb,
2106 void *disconnect_cls)
2107{
2108 plc->is_disconnecting = GNUNET_YES;
2109 plc->disconnect_cb = disconnect_cb;
2110 plc->disconnect_cls = disconnect_cls;
2111
2112 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
2113 GNUNET_YES == plc->is_host
2114 ? host_cleanup : guest_cleanup,
2115 plc);
2116}
2117
2118
1969/** 2119/**
1970 * Stop hosting a place. 2120 * Disconnect from a home.
1971 * 2121 *
1972 * Invalidates host handle. 2122 * Invalidates host handle.
1973 * 2123 *
1974 * @param host Host leaving the place. 2124 * @param hst
1975 * @param keep_active Keep the place active after last host disconnected. 2125 * The host to disconnect.
1976 */ 2126 */
1977void 2127void
1978GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst, 2128GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst,
1979 int keep_active, 2129 GNUNET_ContinuationCallback disconnect_cb,
1980 GNUNET_ContinuationCallback leave_cb, 2130 void *cls)
1981 void *leave_cls)
1982{ 2131{
1983 struct GNUNET_SOCIAL_Place *plc = &hst->plc; 2132 place_disconnect (&hst->plc, disconnect_cb, cls);
2133}
1984 2134
1985 /* FIXME: send msg to service */
1986 2135
1987 plc->is_disconnecting = GNUNET_YES; 2136/**
1988 plc->disconnect_cb = leave_cb; 2137 * Stop hosting the home.
1989 plc->disconnect_cls = leave_cls; 2138 *
1990 2139 * Sends a _notice_place_closed announcement to the home.
1991 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES, 2140 * Invalidates host handle.
1992 &host_cleanup, hst); 2141 *
2142 * @param hst
2143 * The host leaving.
2144 * @param env
2145 * Environment for the message or NULL.
2146 * _nym is set to @e nym regardless whether an @e env is provided.
2147 * @param disconnect_cb
2148 * Function called after the host left the place
2149 * and disconnected from the social service.
2150 * @param cls
2151 * Closure for @a disconnect_cb.
2152 */
2153void
2154GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
2155 const struct GNUNET_ENV_Environment *env,
2156 GNUNET_ContinuationCallback disconnect_cb,
2157 void *cls)
2158{
2159 GNUNET_SOCIAL_host_announce (hst, "_notice_place_closed", env, NULL, NULL,
2160 GNUNET_SOCIAL_ANNOUNCE_NONE);
2161 place_leave (&hst->plc);
2162 GNUNET_SOCIAL_host_disconnect (hst, disconnect_cb, cls);
1993} 2163}
1994 2164
1995 2165
1996/*** GUEST ***/ 2166/*** GUEST ***/
1997 2167
1998static struct GuestEnterRequest * 2168static struct GuestEnterRequest *
1999guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key, 2169guest_enter_request_create (const char *app_id,
2000 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key, 2170 const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key,
2171 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
2001 const struct GNUNET_PeerIdentity *origin, 2172 const struct GNUNET_PeerIdentity *origin,
2002 size_t relay_count, 2173 size_t relay_count,
2003 const struct GNUNET_PeerIdentity *relays, 2174 const struct GNUNET_PeerIdentity *relays,
2004 const struct GNUNET_PSYC_Message *join_msg) 2175 const struct GNUNET_PSYC_Message *join_msg)
2005{ 2176{
2177 uint16_t app_id_size = strlen (app_id) + 1;
2006 uint16_t join_msg_size = ntohs (join_msg->header.size); 2178 uint16_t join_msg_size = ntohs (join_msg->header.size);
2007 uint16_t relay_size = relay_count * sizeof (*relays); 2179 uint16_t relay_size = relay_count * sizeof (*relays);
2008 2180
2009 struct GuestEnterRequest * 2181 struct GuestEnterRequest *
2010 req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size); 2182 greq = GNUNET_malloc (sizeof (*greq) + app_id_size + relay_size + join_msg_size);
2183
2184 greq->header.size = htons (sizeof (*greq) + app_id_size + relay_size + join_msg_size);
2185 greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
2186 greq->place_pub_key = *place_pub_key;
2187 greq->ego_pub_key = *ego_pub_key;
2188 greq->origin = *origin;
2189 greq->relay_count = htonl (relay_count);
2011 2190
2012 req->header.size = htons (sizeof (*req) + relay_size + join_msg_size); 2191 char *p = (char *) &greq[1];
2013 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER); 2192 memcpy (p, app_id, app_id_size);
2014 req->place_key = *place_key; 2193 p += app_id_size;
2015 req->guest_key = *guest_key;
2016 req->origin = *origin;
2017 req->relay_count = htonl (relay_count);
2018 2194
2019 uint16_t p = sizeof (*req);
2020 if (0 < relay_size) 2195 if (0 < relay_size)
2021 { 2196 {
2022 memcpy ((char *) req + p, relays, relay_size); 2197 memcpy (p, relays, relay_size);
2023 p += relay_size; 2198 p += relay_size;
2024 } 2199 }
2025 2200
2026 memcpy ((char *) req + p, join_msg, join_msg_size); 2201 memcpy (p, join_msg, join_msg_size);
2027 return req; 2202 return greq;
2028} 2203}
2029 2204
2030/** 2205/**
@@ -2045,13 +2220,13 @@ guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_ke
2045 * @return NULL on errors, otherwise handle for the guest. 2220 * @return NULL on errors, otherwise handle for the guest.
2046 */ 2221 */
2047struct GNUNET_SOCIAL_Guest * 2222struct GNUNET_SOCIAL_Guest *
2048GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg, 2223GNUNET_SOCIAL_guest_enter (const struct GNUNET_SOCIAL_App *app,
2049 const struct GNUNET_IDENTITY_Ego *ego, 2224 const struct GNUNET_SOCIAL_Ego *ego,
2050 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key, 2225 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
2051 const struct GNUNET_PeerIdentity *origin, 2226 const struct GNUNET_PeerIdentity *origin,
2052 uint32_t relay_count, 2227 uint32_t relay_count,
2053 const struct GNUNET_PeerIdentity *relays, 2228 const struct GNUNET_PeerIdentity *relays,
2054 const struct GNUNET_PSYC_Message *join_msg, 2229 const struct GNUNET_PSYC_Message *entry_msg,
2055 struct GNUNET_SOCIAL_Slicer *slicer, 2230 struct GNUNET_SOCIAL_Slicer *slicer,
2056 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, 2231 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
2057 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb, 2232 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
@@ -2060,9 +2235,9 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
2060 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); 2235 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
2061 struct GNUNET_SOCIAL_Place *plc = &gst->plc; 2236 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
2062 2237
2063 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); 2238 plc->ego_pub_key = ego->pub_key;
2064 plc->pub_key = *place_key; 2239 plc->pub_key = *place_pub_key;
2065 plc->cfg = cfg; 2240 plc->cfg = app->cfg;
2066 plc->is_host = GNUNET_YES; 2241 plc->is_host = GNUNET_YES;
2067 plc->slicer = slicer; 2242 plc->slicer = slicer;
2068 2243
@@ -2070,86 +2245,22 @@ GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
2070 gst->entry_dcsn_cb = entry_dcsn_cb; 2245 gst->entry_dcsn_cb = entry_dcsn_cb;
2071 gst->cb_cls = cls; 2246 gst->cb_cls = cls;
2072 2247
2073 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers); 2248 plc->client = GNUNET_CLIENT_MANAGER_connect (plc->cfg, "social", guest_handlers);
2074 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); 2249 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
2075 2250
2076 plc->tmit = GNUNET_PSYC_transmit_create (plc->client); 2251 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
2077 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer); 2252 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer);
2078 2253
2079 struct GuestEnterRequest * 2254 struct GuestEnterRequest *
2080 req = guest_enter_request_create (&plc->ego_key, place_key, origin, 2255 greq = guest_enter_request_create (app->id, &ego->pub_key, &plc->pub_key,
2081 relay_count, relays, join_msg); 2256 origin, relay_count, relays, entry_msg);
2082 plc->connect_msg = &req->header; 2257 plc->connect_msg = &greq->header;
2083 place_send_connect_msg (plc); 2258 place_send_connect_msg (plc);
2084 return gst; 2259 return gst;
2085} 2260}
2086 2261
2087 2262
2088/** 2263/**
2089 * Result of a GNS name lookup for entering a place.
2090 *
2091 * @see GNUNET_SOCIAL_guest_enter_by_name
2092 */
2093static void
2094gns_result_guest_enter (void *cls, uint32_t rd_count,
2095 const struct GNUNET_GNSRECORD_Data *rd)
2096{
2097 struct GNUNET_SOCIAL_Guest *gst = cls;
2098 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
2099
2100 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2101 "%p GNS result: %u records.\n", gst, rd_count);
2102
2103 const struct GNUNET_GNSRECORD_PlaceData *
2104 rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
2105
2106 if (0 == rd_count)
2107 {
2108 if (NULL != gst->enter_cb)
2109 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
2110 return;
2111 }
2112
2113 if (rd->data_size < sizeof (*rec))
2114 {
2115 GNUNET_break_op (0);
2116 if (NULL != gst->enter_cb)
2117 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
2118 return;
2119 }
2120
2121 uint16_t relay_count = ntohl (rec->relay_count);
2122 struct GNUNET_PeerIdentity *relays = NULL;
2123
2124 if (0 < relay_count)
2125 {
2126 if (rd->data_size == sizeof (*rec) + relay_count * sizeof (struct GNUNET_PeerIdentity))
2127 {
2128 relays = (struct GNUNET_PeerIdentity *) &rec[1];
2129 }
2130 else
2131 {
2132 relay_count = 0;
2133 GNUNET_break_op (0);
2134 }
2135 }
2136
2137 struct GuestEnterRequest *
2138 req = guest_enter_request_create (&plc->ego_key, &rec->place_key,
2139 &rec->origin, relay_count, relays,
2140 (struct GNUNET_PSYC_Message *) plc->connect_msg);
2141 GNUNET_free (plc->connect_msg);
2142 plc->connect_msg = &req->header;
2143 plc->pub_key = req->place_key;
2144
2145 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
2146 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer);
2147
2148 place_send_connect_msg (plc);
2149}
2150
2151
2152/**
2153 * Request entry to a place by name as a guest. 2264 * Request entry to a place by name as a guest.
2154 * 2265 *
2155 * @param cfg 2266 * @param cfg
@@ -2165,7 +2276,7 @@ gns_result_guest_enter (void *cls, uint32_t rd_count,
2165 * @param password 2276 * @param password
2166 * Password to decrypt the record, or NULL for cleartext records. 2277 * Password to decrypt the record, or NULL for cleartext records.
2167 * @param join_msg 2278 * @param join_msg
2168 * Entry request message. 2279 * Entry request message or NULL.
2169 * @param slicer 2280 * @param slicer
2170 * Slicer to use for processing incoming requests from guests. 2281 * Slicer to use for processing incoming requests from guests.
2171 * @param local_enter_cb 2282 * @param local_enter_cb
@@ -2176,9 +2287,10 @@ gns_result_guest_enter (void *cls, uint32_t rd_count,
2176 * @return NULL on errors, otherwise handle for the guest. 2287 * @return NULL on errors, otherwise handle for the guest.
2177 */ 2288 */
2178struct GNUNET_SOCIAL_Guest * 2289struct GNUNET_SOCIAL_Guest *
2179GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg, 2290GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app,
2180 const struct GNUNET_IDENTITY_Ego *ego, 2291 const struct GNUNET_SOCIAL_Ego *ego,
2181 const char *gns_name, const char *password, 2292 const char *gns_name,
2293 const char *password,
2182 const struct GNUNET_PSYC_Message *join_msg, 2294 const struct GNUNET_PSYC_Message *join_msg,
2183 struct GNUNET_SOCIAL_Slicer *slicer, 2295 struct GNUNET_SOCIAL_Slicer *slicer,
2184 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb, 2296 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
@@ -2188,32 +2300,109 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg
2188 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst)); 2300 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
2189 struct GNUNET_SOCIAL_Place *plc = &gst->plc; 2301 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
2190 2302
2191 GNUNET_assert (NULL != join_msg); 2303 if (NULL == password)
2304 password = "";
2305
2306 uint16_t app_id_size = strlen (app->id) + 1;
2307 uint16_t gns_name_size = strlen (gns_name) + 1;
2308 uint16_t password_size = strlen (password) + 1;
2309
2310 uint16_t join_msg_size = 0;
2311 if (NULL != join_msg);
2312 join_msg_size = ntohs (join_msg->header.size);
2313
2314 uint16_t greq_size = sizeof (struct GuestEnterByNameRequest)
2315 + app_id_size + gns_name_size + password_size + join_msg_size;
2316 struct GuestEnterByNameRequest *greq = GNUNET_malloc (greq_size);
2317 greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_BY_NAME);
2318 greq->header.size = htons (greq_size);
2319 greq->ego_pub_key = ego->pub_key;
2320
2321 char *p = (char *) &greq[1];
2322 memcpy (p, app->id, app_id_size);
2323 p += app_id_size;
2324 memcpy (p, gns_name, gns_name_size);
2325 p += gns_name_size;
2326 memcpy (p, password, password_size);
2327 p += password_size;
2328 if (NULL != join_msg)
2329 memcpy (p, join_msg, join_msg_size);
2192 2330
2193 gst->enter_cb = local_enter_cb; 2331 gst->enter_cb = local_enter_cb;
2194 gst->entry_dcsn_cb = entry_decision_cb; 2332 gst->entry_dcsn_cb = entry_decision_cb;
2195 gst->cb_cls = cls; 2333 gst->cb_cls = cls;
2196 2334
2197 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); 2335 plc->ego_pub_key = ego->pub_key;
2198 plc->cfg = cfg; 2336 plc->cfg = app->cfg;
2199 plc->is_host = GNUNET_NO; 2337 plc->is_host = GNUNET_NO;
2200 plc->slicer = slicer; 2338 plc->slicer = slicer;
2201 2339
2202 uint16_t join_msg_size = ntohs (join_msg->header.size); 2340 plc->client = GNUNET_CLIENT_MANAGER_connect (app->cfg, "social", guest_handlers);
2203 plc->connect_msg = GNUNET_malloc (join_msg_size); 2341 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
2204 memcpy (plc->connect_msg, join_msg, join_msg_size); 2342
2343 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
2344 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer);
2345
2346 plc->connect_msg = &greq->header;
2347 place_send_connect_msg (plc);
2348
2349 return gst;
2350}
2205 2351
2206 if (NULL == gns)
2207 gns = GNUNET_GNS_connect (cfg);
2208 2352
2209 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers); 2353/**
2354 * Reconnect to an already entered place as guest.
2355 *
2356 * @param gconn
2357 * Guest connection handle.
2358 * @see GNUNET_SOCIAL_app_connect() & GNUNET_SOCIAL_AppGuestPlaceCallback()
2359 * @param slicer
2360 * Slicer to use for processing incoming requests from guests.
2361 * @param local_enter_cb
2362 * Called upon connection established to the social service.
2363 * @param entry_decision_cb
2364 * Called upon receiving entry decision.
2365 *
2366 * @return NULL on errors, otherwise handle for the guest.
2367 */
2368struct GNUNET_SOCIAL_Guest *
2369GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn,
2370 struct GNUNET_SOCIAL_Slicer *slicer,
2371 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
2372 void *cls)
2373{
2374 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
2375 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
2376
2377 uint16_t app_id_size = strlen (gconn->app->id) + 1;
2378 uint16_t greq_size = sizeof (struct GuestEnterRequest) + app_id_size;
2379 struct GuestEnterRequest *greq = GNUNET_malloc (greq_size);
2380 greq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
2381 greq->header.size = htons (greq_size);
2382 greq->ego_pub_key = gconn->plc_msg.ego_pub_key;
2383 greq->place_pub_key = gconn->plc_msg.place_pub_key;
2384
2385 memcpy (&greq[1], gconn->app->id, app_id_size);
2386
2387 gst->enter_cb = local_enter_cb;
2388 gst->cb_cls = cls;
2389
2390 plc->cfg = gconn->app->cfg;
2391 plc->is_host = GNUNET_NO;
2392 plc->slicer = slicer;
2393 plc->pub_key = gconn->plc_msg.place_pub_key;
2394 plc->ego_pub_key = gconn->plc_msg.ego_pub_key;
2395
2396 plc->client = GNUNET_CLIENT_MANAGER_connect (plc->cfg, "social", guest_handlers);
2210 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc)); 2397 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
2211 2398
2212 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key; 2399 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
2213 GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key); 2400 plc->recv = GNUNET_PSYC_receive_create (NULL, slicer_message, plc->slicer);
2214 GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key, 2401
2215 GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT, 2402 plc->connect_msg = &greq->header;
2216 NULL, gns_result_guest_enter, gst); 2403 place_send_connect_msg (plc);
2404
2405 GNUNET_free (gconn);
2217 return gst; 2406 return gst;
2218} 2407}
2219 2408
@@ -2284,6 +2473,23 @@ GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
2284 2473
2285 2474
2286/** 2475/**
2476 * Disconnect from a place.
2477 *
2478 * Invalidates guest handle.
2479 *
2480 * @param gst
2481 * The guest to disconnect.
2482 */
2483void
2484GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst,
2485 GNUNET_ContinuationCallback disconnect_cb,
2486 void *cls)
2487{
2488 place_disconnect (&gst->plc, disconnect_cb, cls);
2489}
2490
2491
2492/**
2287 * Leave a place temporarily or permanently. 2493 * Leave a place temporarily or permanently.
2288 * 2494 *
2289 * Notifies the owner of the place about leaving, and destroys the place handle. 2495 * Notifies the owner of the place about leaving, and destroys the place handle.
@@ -2301,28 +2507,14 @@ GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
2301 */ 2507 */
2302void 2508void
2303GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst, 2509GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
2304 int keep_active,
2305 struct GNUNET_ENV_Environment *env, 2510 struct GNUNET_ENV_Environment *env,
2306 GNUNET_ContinuationCallback leave_cb, 2511 GNUNET_ContinuationCallback disconnect_cb,
2307 void *leave_cls) 2512 void *cls)
2308{ 2513{
2309 struct GNUNET_SOCIAL_Place *plc = &gst->plc; 2514 GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL,
2310 2515 GNUNET_SOCIAL_TALK_NONE);
2311 plc->is_disconnecting = GNUNET_YES; 2516 place_leave (&gst->plc);
2312 plc->disconnect_cb = leave_cb; 2517 GNUNET_SOCIAL_guest_disconnect (gst, disconnect_cb, cls);
2313 plc->disconnect_cls = leave_cls;
2314
2315 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2316 "Guest: leaving place.\n");
2317
2318 if (GNUNET_NO == keep_active && NULL != plc->tmit)
2319 {
2320 GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL,
2321 GNUNET_SOCIAL_TALK_NONE);
2322 }
2323
2324 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
2325 &guest_cleanup, gst);
2326} 2518}
2327 2519
2328 2520
@@ -2342,6 +2534,21 @@ GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst)
2342} 2534}
2343 2535
2344 2536
2537/**
2538 * Obtain the public key of a place.
2539 *
2540 * @param plc
2541 * Place.
2542 *
2543 * @return Public key of the place.
2544 */
2545const struct GNUNET_CRYPTO_EddsaPublicKey *
2546GNUNET_SOCIAL_place_get_key (struct GNUNET_SOCIAL_Place *plc)
2547{
2548 return &plc->pub_key;
2549}
2550
2551
2345static struct GNUNET_SOCIAL_HistoryRequest * 2552static struct GNUNET_SOCIAL_HistoryRequest *
2346place_history_replay (struct GNUNET_SOCIAL_Place *plc, 2553place_history_replay (struct GNUNET_SOCIAL_Place *plc,
2347 uint64_t start_message_id, 2554 uint64_t start_message_id,
@@ -2571,8 +2778,119 @@ GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *look)
2571} 2778}
2572 2779
2573 2780
2781static void
2782op_recv_zone_add_place_result (void *cls, int64_t result,
2783 const void *err_msg, uint16_t err_msg_size)
2784{
2785 LOG (GNUNET_ERROR_TYPE_DEBUG,
2786 "Received zone add place result: %" PRId64 ".\n", result);
2787
2788 struct ZoneAddPlaceHandle *add_plc = cls;
2789 if (NULL != add_plc->result_cb)
2790 add_plc->result_cb (add_plc->result_cls, result, err_msg, err_msg_size);
2791
2792 GNUNET_free (add_plc->req);
2793 GNUNET_free (add_plc);
2794}
2795
2796
2574/** 2797/**
2575 * Add public key to the GNS zone of the @e ego. 2798 * Advertise @e place in the GNS zone of @e ego.
2799 *
2800 * @param app
2801 * Application handle.
2802 * @param ego
2803 * Ego.
2804 * @param place_pub_key
2805 * Public key of place to add.
2806 * @param name
2807 * The name for the PLACE record to put in the zone.
2808 * @param password
2809 * Password used to encrypt the record or NULL to keep it cleartext.
2810 * @param relay_count
2811 * Number of elements in the @a relays array.
2812 * @param relays
2813 * List of relays to put in the PLACE record to advertise
2814 * as entry points to the place in addition to the origin.
2815 * @param expiration_time
2816 * Expiration time of the record, use 0 to remove the record.
2817 * @param result_cb
2818 * Function called with the result of the operation.
2819 * @param result_cls
2820 * Closure for @a result_cb
2821 *
2822 * @return #GNUNET_OK if the request was sent,
2823 * #GNUNET_SYSERR on error, e.g. the name/password is too long.
2824 */
2825int
2826GNUNET_SOCIAL_zone_add_place (const struct GNUNET_SOCIAL_App *app,
2827 const struct GNUNET_SOCIAL_Ego *ego,
2828 const char *name,
2829 const char *password,
2830 const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
2831 const struct GNUNET_PeerIdentity *origin,
2832 uint32_t relay_count,
2833 const struct GNUNET_PeerIdentity *relays,
2834 struct GNUNET_TIME_Absolute expiration_time,
2835 GNUNET_ResultCallback result_cb,
2836 void *result_cls)
2837{
2838 struct ZoneAddPlaceRequest *preq;
2839 size_t name_size = strlen (name) + 1;
2840 size_t password_size = strlen (password) + 1;
2841 size_t relay_size = relay_count * sizeof (*relays);
2842 size_t preq_size = sizeof (*preq) + name_size + password_size + relay_size;
2843
2844 if (GNUNET_SERVER_MAX_MESSAGE_SIZE < preq_size)
2845 return GNUNET_SYSERR;
2846
2847 preq = GNUNET_malloc (preq_size);
2848 preq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_PLACE);
2849 preq->header.size = htons (preq_size);
2850 preq->expiration_time = GNUNET_htonll (expiration_time.abs_value_us);
2851 preq->ego_pub_key = ego->pub_key;
2852 preq->place_pub_key = *place_pub_key;
2853 preq->origin = *origin;
2854 preq->relay_count = htonl (relay_count);
2855
2856 char *p = (char *) &preq[1];
2857 memcpy (p, name, name_size);
2858 p += name_size;
2859 memcpy (p, password, password_size);
2860 p += password_size;
2861 memcpy (p, relays, relay_size);
2862
2863 struct ZoneAddPlaceHandle * add_plc = GNUNET_malloc (sizeof (*add_plc));
2864 add_plc->req = preq;
2865 add_plc->result_cb = result_cb;
2866 add_plc->result_cls = result_cls;
2867
2868 preq->op_id = GNUNET_htonll (GNUNET_CLIENT_MANAGER_op_add (app->client,
2869 op_recv_zone_add_place_result,
2870 add_plc));
2871 GNUNET_CLIENT_MANAGER_transmit_now (app->client, &preq->header);
2872 return GNUNET_OK;
2873}
2874
2875
2876static void
2877op_recv_zone_add_nym_result (void *cls, int64_t result,
2878 const void *err_msg, uint16_t err_msg_size)
2879{
2880 LOG (GNUNET_ERROR_TYPE_DEBUG,
2881 "Received zone add nym result: %" PRId64 ".\n", result);
2882
2883 struct ZoneAddNymHandle *add_nym = cls;
2884 if (NULL != add_nym->result_cb)
2885 add_nym->result_cb (add_nym->result_cls, result, err_msg, err_msg_size);
2886
2887 GNUNET_free (add_nym->req);
2888 GNUNET_free (add_nym);
2889}
2890
2891
2892/**
2893 * Add nym to the GNS zone of @e ego.
2576 * 2894 *
2577 * @param cfg 2895 * @param cfg
2578 * Configuration. 2896 * Configuration.
@@ -2588,43 +2906,57 @@ GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *look)
2588 * Function called with the result of the operation. 2906 * Function called with the result of the operation.
2589 * @param result_cls 2907 * @param result_cls
2590 * Closure for @a result_cb 2908 * Closure for @a result_cb
2909 *
2910 * @return #GNUNET_OK if the request was sent,
2911 * #GNUNET_SYSERR on error, e.g. the name is too long.
2591 */ 2912 */
2592void 2913int
2593GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg, 2914GNUNET_SOCIAL_zone_add_nym (const struct GNUNET_SOCIAL_App *app,
2594 const struct GNUNET_IDENTITY_Ego *ego, 2915 const struct GNUNET_SOCIAL_Ego *ego,
2595 const char *name, 2916 const char *name,
2596 const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key, 2917 const struct GNUNET_CRYPTO_EcdsaPublicKey *nym_pub_key,
2597 struct GNUNET_TIME_Absolute expiration_time, 2918 struct GNUNET_TIME_Absolute expiration_time,
2598 GNUNET_NAMESTORE_ContinuationWithStatus result_cb, 2919 GNUNET_ResultCallback result_cb,
2599 void *result_cls) 2920 void *result_cls)
2600{ 2921{
2601 if (NULL == namestore) 2922 struct ZoneAddNymRequest *nreq;
2602 namestore = GNUNET_NAMESTORE_connect (cfg); 2923
2603 2924 size_t name_size = strlen (name) + 1;
2604 struct GNUNET_GNSRECORD_Data rd = { }; 2925 if (GNUNET_SERVER_MAX_MESSAGE_SIZE < sizeof (*nreq) + name_size)
2605 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; 2926 return GNUNET_SYSERR;
2606 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
2607 rd.expiration_time = expiration_time.abs_value_us;
2608 rd.data = nym_pub_key;
2609 rd.data_size = sizeof (*nym_pub_key);
2610 2927
2611 GNUNET_NAMESTORE_records_store (namestore, 2928 nreq = GNUNET_malloc (sizeof (*nreq) + name_size);
2612 GNUNET_IDENTITY_ego_get_private_key (ego), 2929 nreq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_ZONE_ADD_NYM);
2613 name, 1, &rd, result_cb, result_cls); 2930 nreq->header.size = htons (sizeof (*nreq) + name_size);
2931 nreq->expiration_time = GNUNET_htonll (expiration_time.abs_value_us);
2932 nreq->ego_pub_key = ego->pub_key;
2933 nreq->nym_pub_key = *nym_pub_key;
2934 memcpy (&nreq[1], name, name_size);
2935
2936 struct ZoneAddNymHandle * add_nym = GNUNET_malloc (sizeof (*add_nym));
2937 add_nym->req = nreq;
2938 add_nym->result_cb = result_cb;
2939 add_nym->result_cls = result_cls;
2940
2941 nreq->op_id = GNUNET_htonll (GNUNET_CLIENT_MANAGER_op_add (app->client,
2942 op_recv_zone_add_nym_result,
2943 add_nym));
2944 GNUNET_CLIENT_MANAGER_transmit_now (app->client, &nreq->header);
2945 return GNUNET_OK;
2614} 2946}
2615 2947
2616 2948
2617/** 2949/**
2618 * Start listening for entered places as host or guest. 2950 * Connect application to the social service.
2619 * 2951 *
2620 * The @notify_host and @notify_guest functions are 2952 * The @host_place_cb and @guest_place_cb functions are
2621 * initially called with the full list of entered places, 2953 * initially called for each entered places,
2622 * then later each time a new place is entered. 2954 * then later each time a new place is entered with the current application ID.
2623 * 2955 *
2624 * @param cfg 2956 * @param cfg
2625 * Configuration. 2957 * Configuration.
2626 * @param ego 2958 * @param id
2627 * Listen for places of this ego. 2959 * Application ID.
2628 * @param notify_host 2960 * @param notify_host
2629 * Function to notify about a place entered as host. 2961 * Function to notify about a place entered as host.
2630 * @param notify_guest 2962 * @param notify_guest
@@ -2634,48 +2966,81 @@ GNUNET_SOCIAL_zone_add_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg,
2634 * 2966 *
2635 * @return Handle that can be used to stop listening. 2967 * @return Handle that can be used to stop listening.
2636 */ 2968 */
2637struct GNUNET_SOCIAL_PlaceListenHandle * 2969struct GNUNET_SOCIAL_App *
2638GNUNET_SOCIAL_place_listen_start (const struct GNUNET_CONFIGURATION_Handle *cfg, 2970GNUNET_SOCIAL_app_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
2639 const struct GNUNET_IDENTITY_Ego *ego, 2971 const char *id,
2640 GNUNET_SOCIAL_PlaceNotifyHostCallback notify_host, 2972 GNUNET_SOCIAL_AppEgoCallback ego_cb,
2641 GNUNET_SOCIAL_PlaceNotifyGuestCallback notify_guest, 2973 GNUNET_SOCIAL_AppHostPlaceCallback host_cb,
2642 void *notify_cls) 2974 GNUNET_SOCIAL_AppGuestPlaceCallback guest_cb,
2643{ 2975 void *cls)
2644 struct GNUNET_SOCIAL_PlaceListenHandle *pl = GNUNET_malloc (sizeof *pl); 2976{
2645 pl->notify_host = notify_host; 2977 uint16_t app_id_size = strnlen (id, GNUNET_SOCIAL_APP_MAX_ID_SIZE);
2646 pl->notify_guest = notify_guest; 2978 if (GNUNET_SOCIAL_APP_MAX_ID_SIZE == app_id_size)
2647 pl->notify_cls = notify_cls; 2979 return NULL;
2648 2980 app_id_size++;
2649 struct GNUNET_SOCIAL_Place *plc = &pl->plc; 2981
2650 2982 struct GNUNET_SOCIAL_App *app = GNUNET_malloc (sizeof *app);
2651 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego); 2983 app->cfg = cfg;
2652 plc->cfg = cfg; 2984 app->ego_cb = ego_cb;
2653 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", 2985 app->host_cb = host_cb;
2654 notify_handlers); 2986 app->guest_cb = guest_cb;
2655 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, pl, sizeof (*pl)); 2987 app->cb_cls = cls;
2656 2988 app->egos = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2657 struct PlaceListenRequest *req = GNUNET_malloc (sizeof (*req)); 2989 app->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social",
2658 req->ego_key = plc->ego_key; 2990 app_handlers);
2659 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LISTEN); 2991 GNUNET_CLIENT_MANAGER_set_user_context_ (app->client, app, sizeof (*app));
2660 req->header.size = htons (sizeof (*req));
2661
2662 plc->connect_msg = (struct GNUNET_MessageHeader *) req;
2663 place_send_connect_msg (plc);
2664 2992
2665 return pl; 2993 app->id = GNUNET_malloc (app_id_size);
2994 memcpy (app->id, id, app_id_size);
2995
2996 struct AppConnectRequest *creq = GNUNET_malloc (sizeof (*creq) + app_id_size);
2997 creq->header.size = htons (sizeof (*creq) + app_id_size);
2998 creq->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_CONNECT);
2999 memcpy (&creq[1], app->id, app_id_size);
3000
3001 app->connect_msg = &creq->header;
3002 app_send_connect_msg (app);
3003
3004 return app;
3005}
3006
3007
3008/**
3009 * Disconnect application.
3010 *
3011 * @param app
3012 * Application handle.
3013 */
3014void
3015GNUNET_SOCIAL_app_disconnect (struct GNUNET_SOCIAL_App *app)
3016{
3017 GNUNET_CLIENT_MANAGER_disconnect (app->client, GNUNET_NO, NULL, NULL);
2666} 3018}
2667 3019
2668 3020
2669/** 3021/**
2670 * Stop listening for entered places. 3022 * Detach application from a place.
2671 * 3023 *
2672 * @param pl 3024 * Removes the place from the entered places list for this application.
2673 * Place listen handle. 3025 * Note: this does not disconnect from the place.
3026 *
3027 * @see GNUNET_SOCIAL_host_disconnect() and GNUNET_SOCIAL_guest_disconnect()
3028 *
3029 * @param app
3030 * Application.
3031 * @param plc
3032 * Place.
2674 */ 3033 */
2675void 3034void
2676GNUNET_SOCIAL_place_listen_stop (struct GNUNET_SOCIAL_PlaceListenHandle *pl) 3035GNUNET_SOCIAL_app_detach (struct GNUNET_SOCIAL_App *app,
3036 struct GNUNET_SOCIAL_Place *plc)
2677{ 3037{
2678 GNUNET_CLIENT_MANAGER_disconnect (pl->plc.client, GNUNET_NO, NULL, NULL); 3038 struct AppDetachRequest dreq;
3039 dreq.header.size = htons (sizeof (dreq));
3040 dreq.header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_APP_DETACH);
3041 dreq.place_pub_key = plc->pub_key;
3042 GNUNET_CLIENT_MANAGER_transmit_now (plc->client, &dreq.header);
2679} 3043}
2680 3044
3045
2681/* end of social_api.c */ 3046/* end of social_api.c */
diff --git a/src/social/test_social.c b/src/social/test_social.c
index 158fa469d..38710cd1a 100644
--- a/src/social/test_social.c
+++ b/src/social/test_social.c
@@ -45,6 +45,9 @@
45 */ 45 */
46int res; 46int res;
47 47
48struct GNUNET_SOCIAL_App *app;
49const char *app_id = "test";
50
48/** 51/**
49 * Handle for task for timeout termination. 52 * Handle for task for timeout termination.
50 */ 53 */
@@ -57,8 +60,8 @@ struct GNUNET_PeerIdentity this_peer;
57 60
58struct GNUNET_IDENTITY_Handle *id; 61struct GNUNET_IDENTITY_Handle *id;
59 62
60const struct GNUNET_IDENTITY_Ego *host_ego; 63const struct GNUNET_SOCIAL_Ego *host_ego;
61const struct GNUNET_IDENTITY_Ego *guest_ego; 64const struct GNUNET_SOCIAL_Ego *guest_ego;
62 65
63const char *host_name = "Host One"; 66const char *host_name = "Host One";
64const char *guest_name = "Guest One"; 67const char *guest_name = "Guest One";
@@ -67,6 +70,8 @@ struct GNUNET_CRYPTO_EddsaPrivateKey *place_key;
67struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key; 70struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key;
68 71
69struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key; 72struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
73struct GNUNET_HashCode place_pub_hash;
74
70struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key; 75struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key;
71struct GNUNET_CRYPTO_EcdsaPublicKey host_pub_key; 76struct GNUNET_CRYPTO_EcdsaPublicKey host_pub_key;
72 77
@@ -111,32 +116,57 @@ struct GNUNET_PSYC_Message *join_resp;
111 116
112uint32_t counter; 117uint32_t counter;
113 118
114uint8_t guest_pkey_added = GNUNET_NO; 119uint8_t is_guest_nym_added = GNUNET_NO;
120uint8_t is_host_reconnected = GNUNET_NO;
121uint8_t is_guest_reconnected = GNUNET_NO;
115 122
116enum 123enum
117{ 124{
118 TEST_NONE = 0, 125 TEST_NONE = 0,
119 TEST_HOST_ANSWER_DOOR_REFUSE = 1, 126 TEST_HOST_CREATE = 1,
120 TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 2, 127 TEST_HOST_ENTER = 2,
121 TEST_HOST_ANSWER_DOOR_ADMIT = 3, 128 TEST_GUEST_CREATE = 3,
122 TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 4, 129 TEST_GUEST_ENTER = 4,
123 TEST_HOST_ANNOUNCE = 5, 130 TEST_HOST_ANSWER_DOOR_REFUSE = 5,
124 TEST_HOST_ANNOUNCE_END = 6, 131 TEST_GUEST_RECV_ENTRY_DCSN_REFUSE = 6,
125 TEST_HOST_ANNOUNCE2 = 7, 132 TEST_HOST_ANSWER_DOOR_ADMIT = 7,
126 TEST_HOST_ANNOUNCE2_END = 8, 133 TEST_GUEST_RECV_ENTRY_DCSN_ADMIT = 8,
127 TEST_GUEST_TALK = 9, 134 TEST_HOST_ANNOUNCE = 9,
128 TEST_GUEST_HISTORY_REPLAY = 10, 135 TEST_HOST_ANNOUNCE_END = 10,
129 TEST_GUEST_HISTORY_REPLAY_LATEST = 11, 136 TEST_HOST_ANNOUNCE2 = 11,
130 TEST_GUEST_LOOK_AT = 12, 137 TEST_HOST_ANNOUNCE2_END = 12,
131 TEST_GUEST_LOOK_FOR = 13, 138 TEST_GUEST_TALK = 13,
132 TEST_GUEST_LEAVE = 14, 139 TEST_GUEST_HISTORY_REPLAY = 14,
133 TEST_HOST_ADVERTISE = 15, 140 TEST_GUEST_HISTORY_REPLAY_LATEST = 15,
134 TEST_GUEST_ENTER_BY_NAME = 16, 141 TEST_GUEST_LOOK_AT = 16,
135 TEST_HOST_LEAVE = 17, 142 TEST_GUEST_LOOK_FOR = 17,
143 TEST_GUEST_LEAVE = 18,
144 TEST_ZONE_ADD_PLACE = 19,
145 TEST_GUEST_ENTER_BY_NAME = 20,
146 TEST_RECONNECT = 21,
147 TEST_GUEST_LEAVE2 = 22,
148 TEST_HOST_LEAVE = 23,
136} test; 149} test;
137 150
138 151
139static void 152static void
153schedule_guest_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
154
155static void
156host_answer_door (void *cls,
157 struct GNUNET_SOCIAL_Nym *nym,
158 const char *method_name,
159 struct GNUNET_ENV_Environment *env,
160 size_t data_size,
161 const void *data);
162
163static void
164host_enter ();
165
166static void
167guest_init ();
168
169static void
140guest_enter (); 170guest_enter ();
141 171
142static void 172static void
@@ -167,18 +197,31 @@ cleanup ()
167 id = NULL; 197 id = NULL;
168 } 198 }
169 199
200 if (NULL != guest_slicer)
201 {
202 GNUNET_SOCIAL_slicer_destroy (guest_slicer);
203 guest_slicer = NULL;
204 }
205
206 if (NULL != host_slicer)
207 {
208 GNUNET_SOCIAL_slicer_destroy (host_slicer);
209 host_slicer = NULL;
210 }
211
170 if (NULL != gst) 212 if (NULL != gst)
171 { 213 {
172 GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, NULL, NULL, NULL); 214 GNUNET_SOCIAL_guest_leave (gst, NULL, NULL, NULL);
173 gst = NULL; 215 gst = NULL;
174 gst_plc = NULL; 216 gst_plc = NULL;
175 } 217 }
176 if (NULL != hst) 218 if (NULL != hst)
177 { 219 {
178 GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, NULL, NULL); 220 GNUNET_SOCIAL_host_leave (hst, NULL, NULL, NULL);
179 hst = NULL; 221 hst = NULL;
180 hst_plc = NULL; 222 hst_plc = NULL;
181 } 223 }
224 GNUNET_SOCIAL_app_disconnect (app);
182 GNUNET_SCHEDULER_shutdown (); 225 GNUNET_SCHEDULER_shutdown ();
183} 226}
184 227
@@ -295,58 +338,186 @@ host_left ()
295{ 338{
296 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 339 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
297 "The host has left the place.\n"); 340 "The host has left the place.\n");
298 GNUNET_SOCIAL_slicer_destroy (host_slicer); 341 end ();
299 host_slicer = NULL; 342}
343
344
345static void
346schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
347{
348 test = TEST_HOST_LEAVE;
349 GNUNET_SOCIAL_host_leave (hst, NULL, &host_left, NULL);
300 hst = NULL; 350 hst = NULL;
301 hst_plc = NULL; 351 hst_plc = NULL;
352}
302 353
303 // TODO: GNUNET_SOCIAL_place_listen_start ()
304 354
305 end (); 355static void
356host_farewell2 (void *cls,
357 const struct GNUNET_SOCIAL_Nym *nym,
358 struct GNUNET_ENV_Environment *env)
359{
360 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
361 "Nym left the place again.\n");
362 GNUNET_SCHEDULER_add_now (schedule_host_leave, NULL);
306} 363}
307 364
308 365
309static void 366static void
310schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 367host_reconnected (void *cls, int result,
368 const struct GNUNET_CRYPTO_EddsaPublicKey *home_pub_key,
369 uint64_t max_message_id)
311{ 370{
312 test = TEST_HOST_LEAVE; 371 place_pub_key = *home_pub_key;
313 GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, &host_left, NULL); 372 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash);
373 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
374 "Test #%u: Host reconnected to place %s\n",
375 test, GNUNET_h2s (&place_pub_hash));
376
377 is_host_reconnected = GNUNET_YES;
378 if (GNUNET_YES == is_guest_reconnected)
379 {
380 GNUNET_SCHEDULER_add_now (schedule_guest_leave, NULL);
381 }
314} 382}
315 383
316 384
317static void 385static void
318id_guest_ego_cb2 (void *cls, const struct GNUNET_IDENTITY_Ego *ego) 386guest_reconnected (void *cls, int result, uint64_t max_message_id)
319{ 387{
320 GNUNET_assert (NULL != ego); 388 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
321 guest_ego = ego; 389 "Test #%u: Guest reconnected to place: %d\n",
390 test, result);
391 GNUNET_assert (0 <= result);
322 392
323 guest_enter_by_name (); 393 is_guest_reconnected = GNUNET_YES;
394 if (GNUNET_YES == is_host_reconnected)
395 {
396 GNUNET_SCHEDULER_add_now (schedule_guest_leave, NULL);
397 }
324} 398}
325 399
326 400
327static void 401static void
328host_recv_advertise_result (void *cls, int32_t success, const char *emsg) 402app_recv_host (void *cls,
403 struct GNUNET_SOCIAL_HostConnection *hconn,
404 struct GNUNET_SOCIAL_Ego *ego,
405 const struct GNUNET_CRYPTO_EddsaPublicKey *host_pub_key)
406{
407 struct GNUNET_HashCode host_pub_hash;
408 GNUNET_CRYPTO_hash (host_pub_key, sizeof (*host_pub_key), &host_pub_hash);
409
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
411 "Got app host place notification: %s\n",
412 GNUNET_h2s (&host_pub_hash));
413
414 if (test == TEST_RECONNECT)
415 {
416 if (0 == memcmp (&place_pub_key, host_pub_key, sizeof (*host_pub_key)))
417 {
418 hst = GNUNET_SOCIAL_host_enter_reconnect (hconn, host_slicer, host_reconnected,
419 host_answer_door, host_farewell2, NULL);
420 }
421 }
422}
423
424
425static void
426app_recv_guest (void *cls,
427 struct GNUNET_SOCIAL_GuestConnection *gconn,
428 struct GNUNET_SOCIAL_Ego *ego,
429 const struct GNUNET_CRYPTO_EddsaPublicKey *guest_pub_key)
430{
431 struct GNUNET_HashCode guest_pub_hash;
432 GNUNET_CRYPTO_hash (guest_pub_key, sizeof (*guest_pub_key), &guest_pub_hash);
433
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
435 "Got app guest place notification: %s\n",
436 GNUNET_h2s (&guest_pub_hash));
437
438 if (test == TEST_RECONNECT)
439 {
440 if (0 == memcmp (&place_pub_key, guest_pub_key, sizeof (*guest_pub_key)))
441 {
442 gst = GNUNET_SOCIAL_guest_enter_reconnect (gconn, guest_slicer,
443 guest_reconnected, NULL);
444 }
445 }
446}
447
448
449static void
450app_recv_ego (void *cls,
451 struct GNUNET_SOCIAL_Ego *ego,
452 const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key,
453 const char *name)
329{ 454{
330 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 455 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
331 "Test #%u: Advertise result: %d (%s).\n", 456 "Got app ego notification: %p %s %s\n",
332 test, success, emsg); 457 ego, name,
333 GNUNET_assert (GNUNET_YES == success); 458 GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key));
459
460 if (NULL != strstr (name, host_name) && TEST_HOST_CREATE == test)
461 {
462 host_ego = ego;
463 host_pub_key = *(GNUNET_SOCIAL_ego_get_pub_key (host_ego));
464 GNUNET_assert (TEST_HOST_CREATE == test);
465 host_enter ();
466 }
467 else if (NULL != strstr (name, guest_name))
468 {
469 guest_ego = ego;
470
471 if (TEST_GUEST_CREATE == test)
472 guest_init ();
473 }
474}
475
476
477static void
478schedule_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
479{
480 test = TEST_RECONNECT;
334 481
335 GNUNET_assert (GNUNET_YES == guest_pkey_added); 482 GNUNET_SOCIAL_host_disconnect (hst, NULL, NULL);
336 GNUNET_IDENTITY_ego_lookup (cfg, guest_name, id_guest_ego_cb2, NULL); 483 GNUNET_SOCIAL_guest_disconnect (gst, NULL, NULL);
484 hst = NULL;
485 gst = NULL;
486
487 GNUNET_SOCIAL_app_disconnect (app);
488 app = GNUNET_SOCIAL_app_connect (cfg, app_id,
489 app_recv_ego,
490 app_recv_host,
491 app_recv_guest,
492 NULL);
337} 493}
338 494
339 495
340static void 496static void
341host_advertise () 497host_recv_zone_add_place_result (void *cls, int64_t result,
498 const void *data, uint16_t data_size)
342{ 499{
343 test = TEST_HOST_ADVERTISE;
344 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 500 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
345 "Test #%u: Advertising place.\n", test); 501 "Test #%u: Zone add place result: %d (%.*s).\n",
502 test, result, data_size, data);
503 GNUNET_assert (GNUNET_YES == result);
346 504
347 GNUNET_SOCIAL_host_advertise (hst, "home", 1, &this_peer, 505 GNUNET_assert (GNUNET_YES == is_guest_nym_added);
506 guest_enter_by_name ();
507}
508
509
510static void
511zone_add_place ()
512{
513 test = TEST_ZONE_ADD_PLACE;
514 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
515 "Test #%u: Adding place to zone.\n", test);
516
517 GNUNET_SOCIAL_zone_add_place (app, host_ego, "home", "let.me*in!",
518 &place_pub_key, &this_peer, 1, &this_peer,
348 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), 519 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
349 "let.me*in!", host_recv_advertise_result, hst); 520 host_recv_zone_add_place_result, app);
350} 521}
351 522
352 523
@@ -356,12 +527,12 @@ host_farewell (void *cls,
356 struct GNUNET_ENV_Environment *env) 527 struct GNUNET_ENV_Environment *env)
357{ 528{
358 const struct GNUNET_CRYPTO_EcdsaPublicKey * 529 const struct GNUNET_CRYPTO_EcdsaPublicKey *
359 nym_key = GNUNET_SOCIAL_nym_get_key (nym); 530 nym_key = GNUNET_SOCIAL_nym_get_pub_key (nym);
360 531
361 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key); 532 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
362 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 533 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
363 "Farewell: nym %s (%s) has left the place.\n", 534 "Farewell: nym %s (%s) has left the place.\n",
364 GNUNET_h2s (GNUNET_SOCIAL_nym_get_key_hash (nym)), str); 535 GNUNET_h2s (GNUNET_SOCIAL_nym_get_pub_key_hash (nym)), str);
365 GNUNET_free (str); 536 GNUNET_free (str);
366 GNUNET_assert (1 == GNUNET_ENV_environment_get_count (env)); 537 GNUNET_assert (1 == GNUNET_ENV_environment_get_count (env));
367 if (0 != memcmp (&guest_pub_key, nym_key, sizeof (*nym_key))) 538 if (0 != memcmp (&guest_pub_key, nym_key, sizeof (*nym_key)))
@@ -372,7 +543,7 @@ host_farewell (void *cls,
372 GNUNET_free (str); 543 GNUNET_free (str);
373 GNUNET_assert (0); 544 GNUNET_assert (0);
374 } 545 }
375 host_advertise (); 546 zone_add_place ();
376} 547}
377 548
378 549
@@ -381,25 +552,24 @@ guest_left (void *cls)
381{ 552{
382 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 553 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
383 "The guest has left the place.\n"); 554 "The guest has left the place.\n");
384 GNUNET_SOCIAL_slicer_destroy (guest_slicer);
385 guest_slicer = NULL;
386 gst = NULL;
387 gst_plc = NULL;
388} 555}
389 556
390 557
391static void 558static void
392guest_leave() 559guest_leave()
393{ 560{
394 test = TEST_GUEST_LEAVE; 561 if (test < TEST_RECONNECT)
562 test = TEST_GUEST_LEAVE;
563 else
564 test = TEST_GUEST_LEAVE2;
395 565
396 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); 566 struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
397 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET, 567 GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET,
398 "_message", DATA2ARG ("Leaving.")); 568 "_message", DATA2ARG ("Leaving."));
399 GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, env, &guest_left, NULL); 569 GNUNET_SOCIAL_guest_leave (gst, env, &guest_left, NULL);
400 GNUNET_ENV_environment_destroy (env); 570 GNUNET_ENV_environment_destroy (env);
401 571 gst = NULL;
402 /* @todo test keep_active */ 572 gst_plc = NULL;
403} 573}
404 574
405 575
@@ -871,7 +1041,7 @@ guest_recv_entry_decision (void *cls,
871 break; 1041 break;
872 1042
873 case TEST_GUEST_ENTER_BY_NAME: 1043 case TEST_GUEST_ENTER_BY_NAME:
874 GNUNET_SCHEDULER_add_now (schedule_host_leave, NULL); 1044 GNUNET_SCHEDULER_add_now (schedule_reconnect, NULL);
875 break; 1045 break;
876 1046
877 default: 1047 default:
@@ -951,7 +1121,7 @@ guest_enter ()
951 emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env, 1121 emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
952 emsg->data, emsg->data_size); 1122 emsg->data, emsg->data_size);
953 1123
954 gst = GNUNET_SOCIAL_guest_enter (cfg, guest_ego, &place_pub_key, 1124 gst = GNUNET_SOCIAL_guest_enter (app, guest_ego, &place_pub_key,
955 &this_peer, 0, NULL, emsg->msg, guest_slicer, 1125 &this_peer, 0, NULL, emsg->msg, guest_slicer,
956 guest_recv_local_enter, 1126 guest_recv_local_enter,
957 guest_recv_entry_decision, NULL); 1127 guest_recv_entry_decision, NULL);
@@ -979,7 +1149,7 @@ guest_enter_by_name ()
979 emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env, 1149 emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
980 emsg->data, emsg->data_size); 1150 emsg->data, emsg->data_size);
981 1151
982 gst = GNUNET_SOCIAL_guest_enter_by_name (cfg, guest_ego, 1152 gst = GNUNET_SOCIAL_guest_enter_by_name (app, guest_ego,
983 "home.host.gnu", "let.me*in!", 1153 "home.host.gnu", "let.me*in!",
984 emsg->msg, guest_slicer, 1154 emsg->msg, guest_slicer,
985 guest_recv_local_enter, 1155 guest_recv_local_enter,
@@ -989,19 +1159,18 @@ guest_enter_by_name ()
989 1159
990 1160
991static void 1161static void
992guest_recv_add_pkey_result (void *cls, int32_t success, const char *emsg) 1162app_recv_zone_add_nym_result (void *cls, int64_t result,
1163 const void *data, uint16_t data_size)
993{ 1164{
994 GNUNET_assert (GNUNET_YES == success); 1165 GNUNET_assert (GNUNET_YES == result);
995 guest_pkey_added = GNUNET_YES; 1166 is_guest_nym_added = GNUNET_YES;
996} 1167}
997 1168
998 1169
999static void 1170static void
1000id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) 1171guest_init ()
1001{ 1172{
1002 GNUNET_assert (NULL != ego); 1173 guest_pub_key = *(GNUNET_SOCIAL_ego_get_pub_key (guest_ego));
1003 guest_ego = ego;
1004 GNUNET_IDENTITY_ego_get_public_key (ego, &guest_pub_key);
1005 1174
1006 guest_slicer = GNUNET_SOCIAL_slicer_create (); 1175 guest_slicer = GNUNET_SOCIAL_slicer_create ();
1007 GNUNET_SOCIAL_slicer_method_add (guest_slicer, "", 1176 GNUNET_SOCIAL_slicer_method_add (guest_slicer, "",
@@ -1011,10 +1180,9 @@ id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
1011 guest_recv_mod_foo_bar, &mod_foo_bar_rcls); 1180 guest_recv_mod_foo_bar, &mod_foo_bar_rcls);
1012 test = TEST_HOST_ANSWER_DOOR_ADMIT; 1181 test = TEST_HOST_ANSWER_DOOR_ADMIT;
1013 1182
1014 GNUNET_SOCIAL_zone_add_pkey (cfg, guest_ego, "host", &host_pub_key, 1183 GNUNET_SOCIAL_zone_add_nym (app, guest_ego, "host", &host_pub_key,
1015 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), 1184 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
1016 guest_recv_add_pkey_result, NULL); 1185 app_recv_zone_add_nym_result, NULL);
1017
1018 guest_enter (); 1186 guest_enter ();
1019} 1187}
1020 1188
@@ -1030,37 +1198,40 @@ id_guest_created (void *cls, const char *emsg)
1030 GNUNET_assert (0); 1198 GNUNET_assert (0);
1031#endif 1199#endif
1032 } 1200 }
1033 1201 if (NULL != guest_ego)
1034 GNUNET_IDENTITY_ego_lookup (cfg, guest_name, &id_guest_ego_cb, NULL); 1202 guest_init ();
1035} 1203}
1036 1204
1037 1205
1038static void 1206static void
1039host_entered (void *cls, int result, uint64_t max_message_id) 1207host_entered (void *cls, int result,
1208 const struct GNUNET_CRYPTO_EddsaPublicKey *home_pub_key,
1209 uint64_t max_message_id)
1040{ 1210{
1041 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host entered to place.\n"); 1211 place_pub_key = *home_pub_key;
1212 GNUNET_CRYPTO_hash (&place_pub_key, sizeof (place_pub_key), &place_pub_hash);
1213 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1214 "Host entered to place %s\n", GNUNET_h2s (&place_pub_hash));
1042 1215
1216 test = TEST_GUEST_CREATE;
1043 GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL); 1217 GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL);
1044} 1218}
1045 1219
1046 1220
1047static void 1221static void
1048id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) 1222host_enter ()
1049{ 1223{
1050 GNUNET_assert (NULL != ego);
1051 host_ego = ego;
1052 GNUNET_IDENTITY_ego_get_public_key (ego, &host_pub_key);
1053
1054 host_slicer = GNUNET_SOCIAL_slicer_create (); 1224 host_slicer = GNUNET_SOCIAL_slicer_create ();
1055 GNUNET_SOCIAL_slicer_method_add (host_slicer, "", 1225 GNUNET_SOCIAL_slicer_method_add (host_slicer, "",
1056 &host_recv_method, &host_recv_modifier, 1226 &host_recv_method, &host_recv_modifier,
1057 &host_recv_data, &host_recv_eom, NULL); 1227 &host_recv_data, &host_recv_eom, NULL);
1058 1228
1059 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n"); 1229 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n");
1060 hst = GNUNET_SOCIAL_host_enter (cfg, host_ego, place_key, 1230 test = TEST_HOST_ENTER;
1061 GNUNET_PSYC_CHANNEL_PRIVATE, host_slicer, 1231 hst = GNUNET_SOCIAL_host_enter (app, host_ego,
1062 host_entered, host_answer_door, 1232 GNUNET_PSYC_CHANNEL_PRIVATE,
1063 host_farewell, NULL); 1233 host_slicer, host_entered,
1234 host_answer_door, host_farewell, NULL);
1064 hst_plc = GNUNET_SOCIAL_host_get_place (hst); 1235 hst_plc = GNUNET_SOCIAL_host_get_place (hst);
1065} 1236}
1066 1237
@@ -1068,6 +1239,12 @@ id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
1068static void 1239static void
1069id_host_created (void *cls, const char *emsg) 1240id_host_created (void *cls, const char *emsg)
1070{ 1241{
1242 if (NULL != core)
1243 {
1244 GNUNET_CORE_disconnect (core);
1245 core = NULL;
1246 }
1247
1071 if (NULL != emsg) 1248 if (NULL != emsg)
1072 { 1249 {
1073 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1077,7 +1254,11 @@ id_host_created (void *cls, const char *emsg)
1077#endif 1254#endif
1078 } 1255 }
1079 1256
1080 GNUNET_IDENTITY_ego_lookup (cfg, host_name, &id_host_ego_cb, NULL); 1257 app = GNUNET_SOCIAL_app_connect (cfg, app_id,
1258 app_recv_ego,
1259 app_recv_host,
1260 app_recv_guest,
1261 NULL);
1081} 1262}
1082 1263
1083 1264
@@ -1085,7 +1266,6 @@ static void
1085identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, 1266identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
1086 void **ctx, const char *name) 1267 void **ctx, const char *name)
1087{ 1268{
1088
1089} 1269}
1090 1270
1091 1271
@@ -1093,8 +1273,9 @@ static void
1093core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity) 1273core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1094{ 1274{
1095 this_peer = *my_identity; 1275 this_peer = *my_identity;
1096
1097 id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL); 1276 id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL);
1277
1278 test = TEST_HOST_CREATE;
1098 GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL); 1279 GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL);
1099} 1280}
1100 1281
@@ -1119,9 +1300,6 @@ run (void *cls,
1119 cfg = c; 1300 cfg = c;
1120 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); 1301 end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
1121 1302
1122 place_key = GNUNET_CRYPTO_eddsa_key_create ();
1123 GNUNET_CRYPTO_eddsa_key_get_public (place_key, &place_pub_key);
1124
1125 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL, 1303 core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
1126 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); 1304 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1127} 1305}