2 * This file is part of GNUnet
3 * (C) 2013 Christian Grothoff (and other contributing authors)
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * @file social/social_api.c
23 * @brief Social service; implements social interactions using the PSYC service.
24 * @author Gabor X Toth
31 #include "gnunet_util_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"
38 #include "gnunet_psyc_util_lib.h"
39 #include "gnunet_social_service.h"
42 #define LOG(kind,...) GNUNET_log_from (kind, "social-api",__VA_ARGS__)
45 static struct GNUNET_CORE_Handle *core;
46 static struct GNUNET_GNS_Handle *gns;
47 static struct GNUNET_NAMESTORE_Handle *namestore;
48 static struct GNUNET_PeerIdentity this_peer;
51 * Handle for a place where social interactions happen.
53 struct GNUNET_SOCIAL_Place
56 * Configuration to use.
58 const struct GNUNET_CONFIGURATION_Handle *cfg;
61 * Client connection to the service.
63 struct GNUNET_CLIENT_MANAGER_Connection *client;
66 * Transmission handle;
68 struct GNUNET_PSYC_TransmitHandle *tmit;
73 struct GNUNET_PSYC_ReceiveHandle *recv;
76 * Message to send on reconnect.
78 struct GNUNET_MessageHeader *connect_msg;
81 * Slicer for processing incoming methods.
83 struct GNUNET_SOCIAL_Slicer *slicer;
86 * Function called after disconnected from the service.
88 GNUNET_ContinuationCallback disconnect_cb;
91 * Closure for @a disconnect_cb.
96 * Public key of the place.
98 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
101 * Private key of the ego.
103 struct GNUNET_CRYPTO_EcdsaPrivateKey ego_key;
106 * Does this place belong to a host (#GNUNET_YES) or guest (#GNUNET_NO)?
111 * Is this place in the process of disconnecting from the service?
112 * #GNUNET_YES or #GNUNET_NO
114 uint8_t is_disconnecting;
119 * Host handle for a place that we entered.
121 struct GNUNET_SOCIAL_Host
123 struct GNUNET_SOCIAL_Place plc;
125 struct GNUNET_CRYPTO_EddsaPrivateKey place_key;
127 GNUNET_SOCIAL_HostEnterCallback enter_cb;
129 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb;
131 GNUNET_SOCIAL_FarewellCallback farewell_cb;
134 * Closure for callbacks.
141 * Guest handle for place that we entered.
143 struct GNUNET_SOCIAL_Guest
145 struct GNUNET_SOCIAL_Place plc;
147 GNUNET_SOCIAL_GuestEnterCallback enter_cb;
149 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb;
152 * Closure for callbacks.
159 * Handle for a pseudonym of another user in the network.
161 struct GNUNET_SOCIAL_Nym
163 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
164 struct GNUNET_HashCode pub_key_hash;
169 * Hash map of all nyms.
170 * pub_key_hash -> struct GNUNET_SOCIAL_Nym *
172 struct GNUNET_CONTAINER_MultiHashMap *nyms;
176 * Handle for a try-and-slice instance.
178 struct GNUNET_SOCIAL_Slicer
181 * Message handlers: method_name -> SlicerCallbacks
183 struct GNUNET_CONTAINER_MultiHashMap *handlers;
187 * Currently being processed message part.
189 const struct GNUNET_MessageHeader *msg;
192 * ID of currently being received message.
197 * Method name of currently being received message.
202 * Public key of the nym the current message originates from.
204 struct GNUNET_CRYPTO_EcdsaPublicKey nym_key;
207 * Size of @a method_name (including terminating \0).
209 uint16_t method_name_size;
214 * Callbacks for a slicer method handler.
216 struct SlicerCallbacks
218 GNUNET_SOCIAL_MethodCallback method_cb;
219 GNUNET_SOCIAL_ModifierCallback modifier_cb;
220 GNUNET_SOCIAL_DataCallback data_cb;
221 GNUNET_SOCIAL_EndOfMessageCallback eom_cb;
226 struct SlicerRemoveClosure
228 struct GNUNET_SOCIAL_Slicer *slicer;
229 struct SlicerCallbacks rm_cbs;
234 * Handle for an announcement request.
236 struct GNUNET_SOCIAL_Announcement
242 struct GNUNET_SOCIAL_WatchHandle
248 struct GNUNET_SOCIAL_LookHandle
257 struct GNUNET_SOCIAL_TalkRequest
266 struct GNUNET_SOCIAL_HistoryLesson
272 static struct GNUNET_SOCIAL_Nym *
273 nym_get_or_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key)
275 struct GNUNET_SOCIAL_Nym *nym = NULL;
276 struct GNUNET_HashCode pub_key_hash;
281 GNUNET_CRYPTO_hash (pub_key, sizeof (*pub_key), &pub_key_hash);
284 nyms = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
286 nym = GNUNET_CONTAINER_multihashmap_get (nyms, &pub_key_hash);
290 nym = GNUNET_new (struct GNUNET_SOCIAL_Nym);
291 nym->pub_key = *pub_key;
292 nym->pub_key_hash = pub_key_hash;
293 GNUNET_CONTAINER_multihashmap_put (nyms, &nym->pub_key_hash, nym,
294 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
301 nym_destroy (struct GNUNET_SOCIAL_Nym *nym)
303 GNUNET_CONTAINER_multihashmap_remove (nyms, &nym->pub_key_hash, nym);
309 * Call a handler for an incoming message part.
318 slicer_handler_notify (void *cls, const struct GNUNET_HashCode *key,
321 struct GNUNET_SOCIAL_Slicer *slicer = cls;
322 const struct GNUNET_MessageHeader *msg = slicer->msg;
323 struct SlicerCallbacks *cbs = value;
324 uint16_t ptype = ntohs (msg->type);
328 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
330 if (NULL == cbs->method_cb)
332 struct GNUNET_PSYC_MessageMethod *
333 meth = (struct GNUNET_PSYC_MessageMethod *) msg;
334 cbs->method_cb (cbs->cls, meth, slicer->message_id,
336 nym_get_or_create (&slicer->nym_key),
337 slicer->method_name);
341 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
343 if (NULL == cbs->modifier_cb)
345 struct GNUNET_PSYC_MessageModifier *
346 mod = (struct GNUNET_PSYC_MessageModifier *) msg;
347 cbs->modifier_cb (cbs->cls, mod, slicer->message_id,
348 mod->oper, (const char *) &mod[1],
349 (const void *) &mod[1] + ntohs (mod->name_size),
350 ntohs (mod->value_size));
354 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
356 if (NULL == cbs->modifier_cb)
358 /* FIXME: concatenate until done */
362 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
364 if (NULL == cbs->data_cb)
366 uint64_t data_offset = 0; // FIXME
367 cbs->data_cb (cbs->cls, msg, slicer->message_id,
368 data_offset, &msg[1], ntohs (msg->size) - sizeof (*msg));
372 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
373 if (NULL == cbs->eom_cb)
375 cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_NO);
378 case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
379 if (NULL == cbs->eom_cb)
381 cbs->eom_cb (cbs->cls, msg, slicer->message_id, GNUNET_YES);
389 * Process an incoming message part and call matching handlers.
396 * Flags for the message.
397 * @see enum GNUNET_PSYC_MessageFlags
399 * The message part. as it arrived from the network.
402 slicer_message (void *cls, uint64_t message_id, uint64_t fragment_offset,
403 uint32_t flags, const struct GNUNET_MessageHeader *msg)
405 struct GNUNET_SOCIAL_Slicer *slicer = cls;
406 uint16_t ptype = ntohs (msg->type);
407 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
409 struct GNUNET_PSYC_MessageMethod *
410 meth = (struct GNUNET_PSYC_MessageMethod *) msg;
411 slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
412 slicer->method_name = GNUNET_malloc (slicer->method_name_size);
413 memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
414 slicer->message_id = message_id;
418 GNUNET_assert (message_id == slicer->message_id);
421 LOG (GNUNET_ERROR_TYPE_WARNING,
422 "Slicer received message of type %u and size %u, "
423 "with ID %" PRIu64 " and method %s\n",
424 ptype, ntohs (msg->size), message_id, slicer->method_name);
427 char *name = GNUNET_malloc (slicer->method_name_size);
428 memcpy (name, slicer->method_name, slicer->method_name_size);
431 struct GNUNET_HashCode key;
432 uint16_t name_len = strlen (name);
433 GNUNET_CRYPTO_hash (name, name_len, &key);
434 GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
435 &slicer_handler_notify, slicer);
436 char *p = strrchr (name, '_');
444 if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
445 GNUNET_free (slicer->method_name);
450 * Create a try-and-slice instance.
452 * @return A new try-and-slice construct.
454 struct GNUNET_SOCIAL_Slicer *
455 GNUNET_SOCIAL_slicer_create (void)
457 struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
458 slicer->handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
464 * Add a method to the try-and-slice instance.
466 * A slicer processes messages and calls methods that match a message. A match
467 * happens whenever the method name of a message starts with the method_name
468 * parameter given here.
470 * @param slicer The try-and-slice instance to extend.
471 * @param method_name Name of the given method, use empty string for default.
472 * @param method Method to invoke.
473 * @param method_cls Closure for method.
476 GNUNET_SOCIAL_slicer_add (struct GNUNET_SOCIAL_Slicer *slicer,
477 const char *method_name,
478 GNUNET_SOCIAL_MethodCallback method_cb,
479 GNUNET_SOCIAL_ModifierCallback modifier_cb,
480 GNUNET_SOCIAL_DataCallback data_cb,
481 GNUNET_SOCIAL_EndOfMessageCallback eom_cb,
484 struct GNUNET_HashCode key;
485 GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
487 struct SlicerCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
488 cbs->method_cb = method_cb;
489 cbs->modifier_cb = modifier_cb;
490 cbs->data_cb = data_cb;
491 cbs->eom_cb = eom_cb;
494 GNUNET_CONTAINER_multihashmap_put (slicer->handlers, &key, cbs,
495 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
500 slicer_remove_handler (void *cls, const struct GNUNET_HashCode *key, void *value)
502 struct SlicerRemoveClosure *rm_cls = cls;
503 struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer;
504 struct SlicerCallbacks *rm_cbs = &rm_cls->rm_cbs;
505 struct SlicerCallbacks *cbs = value;
507 if (cbs->method_cb == rm_cbs->method_cb
508 && cbs->modifier_cb == rm_cbs->modifier_cb
509 && cbs->data_cb == rm_cbs->data_cb
510 && cbs->eom_cb == rm_cbs->eom_cb)
512 GNUNET_CONTAINER_multihashmap_remove (slicer->handlers, key, cbs);
521 * Remove a registered method from the try-and-slice instance.
523 * Removes the first matching handler registered with @a method and the given callbacks.
525 * @param slicer The try-and-slice instance.
526 * @param method_name Name of the method to remove.
527 * @param method Method handler.
529 * @return #GNUNET_OK if a method handler was removed,
530 * #GNUNET_NO if no handler matched the given method name and callbacks.
533 GNUNET_SOCIAL_slicer_remove (struct GNUNET_SOCIAL_Slicer *slicer,
534 const char *method_name,
535 GNUNET_SOCIAL_MethodCallback method_cb,
536 GNUNET_SOCIAL_ModifierCallback modifier_cb,
537 GNUNET_SOCIAL_DataCallback data_cb,
538 GNUNET_SOCIAL_EndOfMessageCallback eom_cb)
540 struct GNUNET_HashCode key;
541 GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
543 struct SlicerRemoveClosure rm_cls;
544 rm_cls.slicer = slicer;
545 struct SlicerCallbacks *rm_cbs = &rm_cls.rm_cbs;
546 rm_cbs->method_cb = method_cb;
547 rm_cbs->modifier_cb = modifier_cb;
548 rm_cbs->data_cb = data_cb;
549 rm_cbs->eom_cb = eom_cb;
553 == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->handlers, &key,
554 &slicer_remove_handler,
562 slicer_free_handler (void *cls, const struct GNUNET_HashCode *key, void *value)
564 struct SlicerCallbacks *cbs = value;
571 * Destroy a given try-and-slice instance.
577 GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
579 GNUNET_CONTAINER_multihashmap_iterate (slicer->handlers, &slicer_free_handler,
581 GNUNET_CONTAINER_multihashmap_destroy (slicer->handlers);
582 GNUNET_free (slicer);
587 place_send_connect_msg (struct GNUNET_SOCIAL_Place *plc)
589 uint16_t cmsg_size = ntohs (plc->connect_msg->size);
590 struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
591 memcpy (cmsg, plc->connect_msg, cmsg_size);
592 GNUNET_CLIENT_MANAGER_transmit_now (plc->client, cmsg);
597 place_recv_message_ack (void *cls,
598 struct GNUNET_CLIENT_MANAGER_Connection *client,
599 const struct GNUNET_MessageHeader *msg)
601 struct GNUNET_SOCIAL_Place *
602 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
603 GNUNET_PSYC_transmit_got_ack (plc->tmit);
608 place_recv_message (void *cls,
609 struct GNUNET_CLIENT_MANAGER_Connection *client,
610 const struct GNUNET_MessageHeader *msg)
612 struct GNUNET_SOCIAL_Place *
613 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
614 GNUNET_PSYC_receive_message (plc->recv,
615 (const struct GNUNET_PSYC_MessageHeader *) msg);
620 place_recv_disconnect (void *cls,
621 struct GNUNET_CLIENT_MANAGER_Connection *client,
622 const struct GNUNET_MessageHeader *msg)
624 struct GNUNET_SOCIAL_Place *
625 plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
627 GNUNET_CLIENT_MANAGER_reconnect (client);
628 place_send_connect_msg (plc);
633 host_recv_enter_ack (void *cls,
634 struct GNUNET_CLIENT_MANAGER_Connection *client,
635 const struct GNUNET_MessageHeader *msg)
637 struct GNUNET_SOCIAL_Host *
638 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
639 sizeof (struct GNUNET_SOCIAL_Place));
641 struct GNUNET_PSYC_CountersResultMessage *
642 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
643 if (NULL != hst->enter_cb)
644 hst->enter_cb (hst->cb_cls, GNUNET_ntohll (cres->max_message_id));
649 host_recv_enter_request (void *cls,
650 struct GNUNET_CLIENT_MANAGER_Connection *client,
651 const struct GNUNET_MessageHeader *msg)
653 struct GNUNET_SOCIAL_Host *
654 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
655 sizeof (struct GNUNET_SOCIAL_Place));
656 if (NULL == hst->answer_door_cb)
659 const char *method_name = NULL;
660 struct GNUNET_ENV_Environment *env = NULL;
661 const void *data = NULL;
662 uint16_t data_size = 0;
664 const struct GNUNET_PSYC_JoinRequestMessage *
665 req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
666 const struct GNUNET_PSYC_Message *entry_msg = NULL;
667 if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size))
669 entry_msg = (struct GNUNET_PSYC_Message *) &req[1];
670 LOG (GNUNET_ERROR_TYPE_DEBUG,
671 "Received entry_msg of type %u and size %u.\n",
672 ntohs (entry_msg->header.type), ntohs (entry_msg->header.size));
674 env = GNUNET_ENV_environment_create ();
675 if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_msg, &method_name, env,
678 LOG (GNUNET_ERROR_TYPE_WARNING,
679 "Ignoring invalid entry request from nym %s.\n",
680 GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key));
682 GNUNET_ENV_environment_destroy (env);
687 struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_key);
688 hst->answer_door_cb (hst->cb_cls, nym, method_name, env,
692 GNUNET_ENV_environment_destroy (env);
697 guest_recv_enter_ack (void *cls,
698 struct GNUNET_CLIENT_MANAGER_Connection *client,
699 const struct GNUNET_MessageHeader *msg)
701 struct GNUNET_SOCIAL_Guest *
702 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
703 sizeof (struct GNUNET_SOCIAL_Place));
705 struct GNUNET_PSYC_CountersResultMessage *
706 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
707 if (NULL != gst->enter_cb)
708 gst->enter_cb (gst->cb_cls, ntohl (cres->result_code),
709 GNUNET_ntohll (cres->max_message_id));
714 guest_recv_join_decision (void *cls,
715 struct GNUNET_CLIENT_MANAGER_Connection *client,
716 const struct GNUNET_MessageHeader *msg)
718 struct GNUNET_SOCIAL_Guest *
719 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
720 sizeof (struct GNUNET_SOCIAL_Place));
721 const struct GNUNET_PSYC_JoinDecisionMessage *
722 dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg;
724 struct GNUNET_PSYC_Message *pmsg = NULL;
725 if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
726 pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1];
728 if (NULL != gst->entry_dcsn_cb)
729 gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg);
733 static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
735 { &host_recv_enter_ack, NULL,
736 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
737 sizeof (struct CountersResult), GNUNET_NO },
739 { &host_recv_enter_request, NULL,
740 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
741 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
743 { &place_recv_message, NULL,
744 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
745 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
747 { &place_recv_message_ack, NULL,
748 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
749 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
751 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
753 { NULL, NULL, 0, 0, GNUNET_NO }
757 static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
759 { &guest_recv_enter_ack, NULL,
760 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
761 sizeof (struct CountersResult), GNUNET_NO },
763 { &host_recv_enter_request, NULL,
764 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
765 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
767 { &place_recv_message, NULL,
768 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
769 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
771 { &place_recv_message_ack, NULL,
772 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
773 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
775 { &guest_recv_join_decision, NULL,
776 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
777 sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES },
779 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
781 { NULL, NULL, 0, 0, GNUNET_NO }
786 place_cleanup (struct GNUNET_SOCIAL_Place *plc)
788 GNUNET_PSYC_transmit_destroy (plc->tmit);
789 GNUNET_PSYC_receive_destroy (plc->recv);
790 GNUNET_free (plc->connect_msg);
791 if (NULL != plc->disconnect_cb)
792 plc->disconnect_cb (plc->disconnect_cls);
797 host_cleanup (void *cls)
799 struct GNUNET_SOCIAL_Host *hst = cls;
800 place_cleanup (&hst->plc);
806 guest_cleanup (void *cls)
808 struct GNUNET_SOCIAL_Guest *gst = cls;
809 place_cleanup (&gst->plc);
815 * Enter a place as host.
817 * A place is created upon first entering, and it is active until permanently
818 * left using GNUNET_SOCIAL_host_leave().
821 * Configuration to contact the social service.
823 * Identity of the host.
825 * Private-public key pair of the place.
826 * NULL for ephemeral places.
828 * Policy specifying entry and history restrictions for the place.
830 * Slicer to handle incoming messages.
831 * @param answer_door_cb
832 * Function to handle new nyms that want to enter.
834 * Function to handle departing nyms.
836 * Closure for the callbacks.
838 * @return Handle for the host.
840 struct GNUNET_SOCIAL_Host *
841 GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
842 const struct GNUNET_IDENTITY_Ego *ego,
843 const struct GNUNET_CRYPTO_EddsaPrivateKey *place_key,
844 enum GNUNET_PSYC_Policy policy,
845 struct GNUNET_SOCIAL_Slicer *slicer,
846 GNUNET_SOCIAL_HostEnterCallback enter_cb,
847 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
848 GNUNET_SOCIAL_FarewellCallback farewell_cb,
851 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
852 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
853 struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req));
855 if (NULL != place_key)
857 hst->place_key = *place_key;
861 struct GNUNET_CRYPTO_EddsaPrivateKey *
862 ephemeral_key = GNUNET_CRYPTO_eddsa_key_create ();
863 hst->place_key = *ephemeral_key;
864 GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key);
865 GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key);
866 GNUNET_free (ephemeral_key);
868 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
870 req->header.size = htons (sizeof (*req));
871 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
872 req->policy = policy;
873 req->place_key = hst->place_key;
874 req->host_key = plc->ego_key;
876 plc->connect_msg = (struct GNUNET_MessageHeader *) req;
878 plc->is_host = GNUNET_YES;
879 plc->slicer = slicer;
881 hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
882 hst->enter_cb = enter_cb;
883 hst->answer_door_cb = answer_door_cb;
886 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers);
887 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
889 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
890 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
892 place_send_connect_msg (plc);
898 * Enter a place as host.
900 * A place is created upon first entering, and it is active until permanently
901 * left using GNUNET_SOCIAL_host_leave().
904 * Configuration to contact the social service.
906 * Identity of the host.
908 * GNS name in the zone of the @a ego that contains the
909 * public key of the place in a PLACE record.
911 * Policy specifying entry and history restrictions for the place.
913 * Slicer to handle incoming messages.
914 * @param answer_door_cb
915 * Function to handle new nyms that want to enter.
917 * Function to handle departing nyms.
919 * Closure for the callbacks.
921 * @return Handle for the host.
923 struct GNUNET_SOCIAL_Host *
924 GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
925 struct GNUNET_IDENTITY_Ego *ego,
926 const char *gns_name,
927 enum GNUNET_PSYC_Policy policy,
928 struct GNUNET_SOCIAL_Slicer *slicer,
929 GNUNET_SOCIAL_HostEnterCallback enter_cb,
930 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
931 GNUNET_SOCIAL_FarewellCallback farewell_cb,
934 struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {};
937 * 1. get public key by looking up PLACE entry under gns_name
938 * in the zone of the ego.
939 * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH
942 return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer,
943 enter_cb, answer_door_cb, farewell_cb, cls);
948 * Decision whether to admit @a nym into the place or refuse entry.
953 * Handle for the entity that wanted to enter.
955 * #GNUNET_YES if @a nym is admitted,
956 * #GNUNET_NO if @a nym is refused entry,
957 * #GNUNET_SYSERR if we cannot answer the request.
959 * Method name for the rejection message.
961 * Environment containing variables for the message, or NULL.
963 * Data for the rejection message to send back.
965 * Number of bytes in @a data for method.
966 * @return #GNUNET_OK on success,
967 * #GNUNET_SYSERR if the message is too large.
970 GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
971 struct GNUNET_SOCIAL_Nym *nym,
973 const struct GNUNET_PSYC_Message *entry_resp)
975 struct GNUNET_PSYC_JoinDecisionMessage *dcsn;
976 uint16_t entry_resp_size
977 = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0;
979 if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size)
980 return GNUNET_SYSERR;
982 dcsn = GNUNET_malloc (sizeof (*dcsn) + entry_resp_size);
983 dcsn->header.size = htons (sizeof (*dcsn) + entry_resp_size);
984 dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION);
985 dcsn->is_admitted = htonl (is_admitted);
986 dcsn->slave_key = nym->pub_key;
988 if (0 < entry_resp_size)
989 memcpy (&dcsn[1], entry_resp, entry_resp_size);
991 GNUNET_CLIENT_MANAGER_transmit (hst->plc.client, &dcsn->header);
997 * Throw @a nym out of the place.
999 * The @a nym reference will remain valid until the
1000 * #GNUNET_SOCIAL_FarewellCallback is invoked,
1001 * which should be very soon after this call.
1003 * @param host Host of the place.
1004 * @param nym Handle for the entity to be ejected.
1007 GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *host,
1008 struct GNUNET_SOCIAL_Nym *nym)
1015 * Get the public key of a @a nym.
1017 * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
1019 * @param nym Pseudonym to map to a cryptographic identifier.
1020 * @param[out] nym_key Set to the public key of the nym.
1022 struct GNUNET_CRYPTO_EcdsaPublicKey *
1023 GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym)
1025 return &nym->pub_key;
1030 * Obtain the private-public key pair of the hosted place.
1032 * The public part is suitable for storing in GNS within a PLACE record,
1033 * along with peer IDs to join at.
1036 * Host of the place.
1038 * @return Private-public key pair of the hosted place.
1040 const struct GNUNET_CRYPTO_EddsaPrivateKey *
1041 GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst)
1043 return &hst->place_key;
1048 namestore_result_host_advertise (void *cls, int32_t success, const char *emsg)
1055 * Connected to core service.
1058 core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1060 this_peer = *my_identity;
1066 * Advertise the place in the GNS zone of the @e ego of the @a host.
1068 * @param hst Host of the place.
1069 * @param name The name for the PLACE record to put in the zone.
1070 * @param peer_count Number of elements in the @a peers array.
1071 * @param peers List of peers in the PLACE record that can be used to send join
1073 * @param expiration_time Expiration time of the record, use 0 to remove the record.
1074 * @param password Password used to encrypt the record.
1077 GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst,
1080 const struct GNUNET_PeerIdentity *peers,
1081 struct GNUNET_TIME_Relative expiration_time,
1082 const char *password)
1084 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1085 if (NULL == namestore)
1086 namestore = GNUNET_NAMESTORE_connect (plc->cfg);
1088 core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL,
1089 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1091 struct GNUNET_GNSRECORD_Data rd = { 0 };
1092 rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
1093 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1095 = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, 1).rel_value_us;
1097 struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec));
1098 rec->place_key = plc->pub_key;
1099 rec->origin = this_peer;
1100 rec->relay_count = htons (0); // FIXME
1102 rd.data_size = sizeof (*rec);
1105 GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key,
1106 name, 1, &rd, namestore_result_host_advertise,
1112 * Send a message to all nyms that are present in the place.
1114 * This function is restricted to the host. Nyms can only send requests
1115 * to the host who can decide to relay it to everyone in the place.
1117 * @param host Host of the place.
1118 * @param method_name Method to use for the announcement.
1119 * @param env Environment containing variables for the message and operations
1120 * on objects of the place. Can be NULL.
1121 * @param notify Function to call to get the payload of the announcement.
1122 * @param notify_cls Closure for @a notify.
1123 * @param flags Flags for this announcement.
1125 * @return NULL on error (announcement already in progress?).
1127 struct GNUNET_SOCIAL_Announcement *
1128 GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
1129 const char *method_name,
1130 const struct GNUNET_ENV_Environment *env,
1131 GNUNET_PSYC_TransmitNotifyData notify_data,
1132 void *notify_data_cls,
1133 enum GNUNET_SOCIAL_AnnounceFlags flags)
1136 GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
1137 NULL, notify_data, notify_data_cls, flags));
1138 return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit;
1143 * Resume transmitting announcement.
1146 * The announcement to resume.
1149 GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a)
1151 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a);
1156 * Cancel announcement.
1159 * The announcement to cancel.
1162 GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a)
1164 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a);
1169 * Obtain handle for a hosted place.
1171 * The returned handle can be used to access the place API.
1173 * @param host Handle for the host.
1175 * @return Handle for the hosted place, valid as long as @a host is valid.
1177 struct GNUNET_SOCIAL_Place *
1178 GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst)
1185 * Stop hosting a place.
1187 * Invalidates host handle.
1189 * @param host Host leaving the place.
1190 * @param keep_active Keep the place active after last host disconnected.
1193 GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
1195 GNUNET_ContinuationCallback leave_cb,
1198 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1200 /* FIXME: send msg to service */
1202 plc->is_disconnecting = GNUNET_YES;
1203 plc->disconnect_cb = leave_cb;
1204 plc->disconnect_cls = leave_cls;
1206 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1207 &host_cleanup, hst);
1211 static struct GuestEnterRequest *
1212 guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key,
1213 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
1214 const struct GNUNET_PeerIdentity *origin,
1216 const struct GNUNET_PeerIdentity *relays,
1217 const struct GNUNET_PSYC_Message *join_msg)
1219 uint16_t join_msg_size = ntohs (join_msg->header.size);
1220 uint16_t relay_size = relay_count * sizeof (*relays);
1222 struct GuestEnterRequest *
1223 req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size);
1225 req->header.size = htons (sizeof (*req) + relay_size + join_msg_size);
1226 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
1227 req->place_key = *place_key;
1228 req->guest_key = *guest_key;
1229 req->origin = *origin;
1230 req->relay_count = relay_count;
1232 uint16_t p = sizeof (*req);
1235 memcpy ((char *) req + p, relays, relay_size);
1239 memcpy ((char *) req + p, join_msg, join_msg_size);
1244 * Request entry to a place as a guest.
1246 * @param cfg Configuration to contact the social service.
1247 * @param ego Identity of the guest.
1248 * @param crypto_address Public key of the place to enter.
1249 * @param origin Peer identity of the origin of the underlying multicast group.
1250 * @param relay_count Number of elements in the @a relays array.
1251 * @param relays Relays for the underlying multicast group.
1252 * @param method_name Method name for the message.
1253 * @param env Environment containing variables for the message, or NULL.
1254 * @param data Payload for the message to give to the enter callback.
1255 * @param data_size Number of bytes in @a data.
1256 * @param slicer Slicer to use for processing incoming requests from guests.
1258 * @return NULL on errors, otherwise handle for the guest.
1260 struct GNUNET_SOCIAL_Guest *
1261 GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1262 const struct GNUNET_IDENTITY_Ego *ego,
1263 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
1264 const struct GNUNET_PeerIdentity *origin,
1265 uint32_t relay_count,
1266 const struct GNUNET_PeerIdentity *relays,
1267 const struct GNUNET_PSYC_Message *entry_msg,
1268 struct GNUNET_SOCIAL_Slicer *slicer,
1269 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
1270 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
1273 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1274 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1276 struct GuestEnterRequest *
1277 req = guest_enter_request_create (&plc->ego_key, place_key, origin,
1278 relay_count, relays, entry_msg);
1279 plc->connect_msg = &req->header;
1280 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1281 plc->pub_key = *place_key;
1283 plc->is_host = GNUNET_YES;
1284 plc->slicer = slicer;
1286 gst->enter_cb = local_enter_cb;
1287 gst->entry_dcsn_cb = entry_dcsn_cb;
1290 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1291 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1293 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1294 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
1296 place_send_connect_msg (plc);
1302 * Result of a GNS name lookup for entering a place.
1304 * @see GNUNET_SOCIAL_guest_enter_by_name
1307 gns_result_guest_enter (void *cls, uint32_t rd_count,
1308 const struct GNUNET_GNSRECORD_Data *rd)
1310 struct GNUNET_SOCIAL_Guest *gst = cls;
1311 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1313 const struct GNUNET_GNSRECORD_PlaceData *
1314 rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
1318 if (NULL != gst->enter_cb)
1319 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1324 if (rd->data_size < sizeof (*rec))
1326 GNUNET_break_op (0);
1327 if (NULL != gst->enter_cb)
1328 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1332 struct GuestEnterRequest *
1333 req = (struct GuestEnterRequest *) plc->connect_msg;
1334 uint16_t req_size = ntohs (req->header.size);
1336 struct GNUNET_PeerIdentity *relays = NULL;
1337 uint16_t relay_count = ntohs (rec->relay_count);
1339 if (0 < relay_count)
1341 uint16_t relay_size = relay_count * sizeof (struct GNUNET_PeerIdentity);
1342 struct GuestEnterRequest *
1343 req2 = GNUNET_malloc (req_size + relay_size);
1345 req2->header.size = htons (req_size + relay_size);
1346 req2->header.type = req->header.type;
1347 req2->guest_key = req->guest_key;
1349 uint16_t p = sizeof (*req);
1352 memcpy ((char *) req2 + p, relays, relay_size);
1356 memcpy ((char *) req + p, &req[1], req_size - sizeof (*req));
1358 plc->connect_msg = &req2->header;
1363 req->place_key = rec->place_key;
1364 req->origin = rec->origin;
1365 req->relay_count = rec->relay_count;
1366 memcpy (&req[1], &rec[1],
1367 ntohl (rec->relay_count) * sizeof (struct GNUNET_PeerIdentity));
1369 plc->connect_msg = &req->header;
1370 plc->pub_key = req->place_key;
1372 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1373 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc);
1375 place_send_connect_msg (plc);
1379 * Request entry to a place as a guest.
1381 * @param cfg Configuration to contact the social service.
1382 * @param ego Identity of the guest.
1383 * @param address GNS name of the place to enter. Either in the form of
1384 * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to
1385 * the 'PLACE' record of the empty label ("+") in the GNS zone with the
1386 * nym's public key 'NYMPUBKEY', and can be used to request entry to a
1387 * pseudonym's place directly.
1388 * @param method_name Method name for the message.
1389 * @param env Environment containing variables for the message, or NULL.
1390 * @param data Payload for the message to give to the enter callback.
1391 * @param data_size Number of bytes in @a data.
1392 * @param slicer Slicer to use for processing incoming requests from guests.
1394 * @return NULL on errors, otherwise handle for the guest.
1396 struct GNUNET_SOCIAL_Guest *
1397 GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
1398 struct GNUNET_IDENTITY_Ego *ego,
1400 const struct GNUNET_PSYC_Message *join_msg,
1401 struct GNUNET_SOCIAL_Slicer *slicer,
1402 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
1403 GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb,
1406 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1407 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1409 gst->enter_cb = local_enter_cb;
1412 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1414 plc->is_host = GNUNET_NO;
1415 plc->slicer = slicer;
1417 struct GuestEnterRequest *
1418 req = guest_enter_request_create (&plc->ego_key, NULL, NULL, 0, NULL,
1420 plc->connect_msg = &req->header;
1422 /* FIXME: get the public key of the origin and relays
1423 * by looking up the PLACE record of gns_name.
1426 gns = GNUNET_GNS_connect (cfg);
1428 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1429 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1431 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
1432 GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key);
1433 GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key,
1434 GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT,
1435 NULL, gns_result_guest_enter, gst);
1442 * Talk to the host of the place.
1445 * Place where we want to talk to the host.
1446 * @param method_name
1447 * Method to invoke on the host.
1449 * Environment containing variables for the message, or NULL.
1450 * @param notify_data
1451 * Function to use to get the payload for the method.
1452 * @param notify_data_cls
1453 * Closure for @a notify_data.
1455 * Flags for the message being sent.
1457 * @return NULL if we are already trying to talk to the host,
1458 * otherwise handle to cancel the request.
1460 struct GNUNET_SOCIAL_TalkRequest *
1461 GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *guest,
1462 const char *method_name,
1463 const struct GNUNET_ENV_Environment *env,
1464 GNUNET_PSYC_TransmitNotifyData notify_data,
1465 void *notify_data_cls,
1466 enum GNUNET_SOCIAL_TalkFlags flags)
1473 * Resume talking to the host of the place.
1476 * Talk request to resume.
1479 GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr)
1481 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr);
1486 * Cancel talking to the host of the place.
1489 * Talk request to cancel.
1492 GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
1494 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr);
1499 * Leave a place permanently.
1501 * Notifies the owner of the place about leaving, and destroys the place handle.
1503 * @param place Place to leave permanently.
1504 * @param keep_active Keep place active after last application disconnected.
1507 GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
1509 GNUNET_ContinuationCallback leave_cb,
1512 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1514 /* FIXME: send msg to service */
1516 plc->is_disconnecting = GNUNET_YES;
1517 plc->disconnect_cb = leave_cb;
1518 plc->disconnect_cls = leave_cls;
1520 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1521 &guest_cleanup, gst);
1526 * Obtain handle for a place entered as guest.
1528 * The returned handle can be used to access the place API.
1530 * @param guest Handle for the guest.
1532 * @return Handle for the place, valid as long as @a guest is valid.
1534 struct GNUNET_SOCIAL_Place *
1535 GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst)
1544 struct GNUNET_SOCIAL_HistoryLesson;
1547 * Learn about the history of a place.
1549 * Sends messages through the slicer function of the place where
1550 * start_message_id <= message_id <= end_message_id.
1551 * The messages will have the #GNUNET_PSYC_MESSAGE_HISTORIC flag set.
1553 * To get the latest message, use 0 for both the start and end message ID.
1555 * @param place Place we want to learn more about.
1556 * @param start_message_id First historic message we are interested in.
1557 * @param end_message_id Last historic message we are interested in (inclusive).
1558 * @param slicer Slicer to use to process history. Can be the same as the
1559 * slicer of the place, as the HISTORIC flag allows distinguishing
1560 * old messages from fresh ones.
1561 * @param finish_cb Function called after the last message in the history lesson
1562 * is passed through the @a slicer. NULL if not needed.
1563 * @param finish_cb_cls Closure for @a finish_cb.
1564 * @return Handle to abort history lesson, never NULL (multiple lessons
1565 * at the same time are allowed).
1567 struct GNUNET_SOCIAL_HistoryLesson *
1568 GNUNET_SOCIAL_place_get_history (struct GNUNET_SOCIAL_Place *place,
1569 uint64_t start_message_id,
1570 uint64_t end_message_id,
1571 const struct GNUNET_SOCIAL_Slicer *slicer,
1572 void (*finish_cb)(void *),
1573 void *finish_cb_cls)
1580 * Stop processing messages from the history lesson.
1582 * Must not be called after the finish callback of the history lesson is called.
1584 * @param hist History lesson to cancel.
1587 GNUNET_SOCIAL_place_get_history_cancel (struct GNUNET_SOCIAL_HistoryLesson *hist)
1593 struct GNUNET_SOCIAL_WatchHandle;
1596 * Watch a place for changed objects.
1598 * @param place Place to watch.
1599 * @param object_filter Object prefix to match.
1600 * @param state_cb Function to call when an object/state changes.
1601 * @param state_cb_cls Closure for callback.
1603 * @return Handle that can be used to cancel watching.
1605 struct GNUNET_SOCIAL_WatchHandle *
1606 GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place,
1607 const char *object_filter,
1608 GNUNET_PSYC_StateCallback state_cb,
1616 * Cancel watching a place for changed objects.
1618 * @param wh Watch handle to cancel.
1621 GNUNET_SOCIAL_place_watch_cancel (struct GNUNET_SOCIAL_WatchHandle *wh)
1627 struct GNUNET_SOCIAL_LookHandle;
1631 * Look at objects in the place with a matching name prefix.
1633 * @param place The place to look its objects at.
1634 * @param name_prefix Look at objects with names beginning with this value.
1635 * @param state_cb Function to call for each object found.
1636 * @param state_cb_cls Closure for callback function.
1638 * @return Handle that can be used to stop looking at objects.
1640 struct GNUNET_SOCIAL_LookHandle *
1641 GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place,
1642 const char *name_prefix,
1643 GNUNET_PSYC_StateCallback state_cb,
1651 * Stop looking at objects.
1653 * @param lh Look handle to stop.
1656 GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *lh)
1664 * Look at a particular object in the place.
1666 * The best matching object is returned (its name might be less specific than
1667 * what was requested).
1669 * @param place The place to look the object at.
1670 * @param full_name Full name of the object.
1671 * @param value_size Set to the size of the returned value.
1672 * @return NULL if there is no such object at this place.
1675 GNUNET_SOCIAL_place_look_at (struct GNUNET_SOCIAL_Place *place,
1676 const char *full_name,
1683 /* end of social_api.c */