2 * This file is part of GNUnet
3 * Copyright (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 int32_t result = ntohl (cres->result_code) + INT32_MIN;
644 if (NULL != hst->enter_cb)
645 hst->enter_cb (hst->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
650 host_recv_enter_request (void *cls,
651 struct GNUNET_CLIENT_MANAGER_Connection *client,
652 const struct GNUNET_MessageHeader *msg)
654 struct GNUNET_SOCIAL_Host *
655 hst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
656 sizeof (struct GNUNET_SOCIAL_Place));
657 if (NULL == hst->answer_door_cb)
660 const char *method_name = NULL;
661 struct GNUNET_ENV_Environment *env = NULL;
662 const void *data = NULL;
663 uint16_t data_size = 0;
665 const struct GNUNET_PSYC_JoinRequestMessage *
666 req = (const struct GNUNET_PSYC_JoinRequestMessage *) msg;
667 const struct GNUNET_PSYC_Message *entry_msg = NULL;
669 if (sizeof (*req) + sizeof (*entry_msg) <= ntohs (req->header.size))
671 entry_msg = (struct GNUNET_PSYC_Message *) &req[1];
672 LOG (GNUNET_ERROR_TYPE_DEBUG,
673 "Received entry_msg of type %u and size %u.\n",
674 ntohs (entry_msg->header.type), ntohs (entry_msg->header.size));
676 env = GNUNET_ENV_environment_create ();
677 if (GNUNET_OK != GNUNET_PSYC_message_parse (entry_msg, &method_name, env,
681 str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&req->slave_key);
682 LOG (GNUNET_ERROR_TYPE_WARNING,
683 "Ignoring invalid entry request from nym %s.\n",
686 GNUNET_ENV_environment_destroy (env);
691 struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&req->slave_key);
692 hst->answer_door_cb (hst->cb_cls, nym, method_name, env,
696 GNUNET_ENV_environment_destroy (env);
701 guest_recv_enter_ack (void *cls,
702 struct GNUNET_CLIENT_MANAGER_Connection *client,
703 const struct GNUNET_MessageHeader *msg)
705 struct GNUNET_SOCIAL_Guest *
706 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
707 sizeof (struct GNUNET_SOCIAL_Place));
709 struct GNUNET_PSYC_CountersResultMessage *
710 cres = (struct GNUNET_PSYC_CountersResultMessage *) msg;
711 int32_t result = ntohl (cres->result_code) + INT32_MIN;
712 if (NULL != gst->enter_cb)
713 gst->enter_cb (gst->cb_cls, result, GNUNET_ntohll (cres->max_message_id));
718 guest_recv_join_decision (void *cls,
719 struct GNUNET_CLIENT_MANAGER_Connection *client,
720 const struct GNUNET_MessageHeader *msg)
722 struct GNUNET_SOCIAL_Guest *
723 gst = GNUNET_CLIENT_MANAGER_get_user_context_ (client,
724 sizeof (struct GNUNET_SOCIAL_Place));
725 const struct GNUNET_PSYC_JoinDecisionMessage *
726 dcsn = (const struct GNUNET_PSYC_JoinDecisionMessage *) msg;
728 struct GNUNET_PSYC_Message *pmsg = NULL;
729 if (ntohs (dcsn->header.size) <= sizeof (*dcsn) + sizeof (*pmsg))
730 pmsg = (struct GNUNET_PSYC_Message *) &dcsn[1];
732 if (NULL != gst->entry_dcsn_cb)
733 gst->entry_dcsn_cb (gst->cb_cls, ntohl (dcsn->is_admitted), pmsg);
737 static struct GNUNET_CLIENT_MANAGER_MessageHandler host_handlers[] =
739 { &host_recv_enter_ack, NULL,
740 GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
741 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
743 { &host_recv_enter_request, NULL,
744 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
745 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
747 { &place_recv_message, NULL,
748 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
749 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
751 { &place_recv_message_ack, NULL,
752 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
753 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
755 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
757 { NULL, NULL, 0, 0, GNUNET_NO }
761 static struct GNUNET_CLIENT_MANAGER_MessageHandler guest_handlers[] =
763 { &guest_recv_enter_ack, NULL,
764 GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
765 sizeof (struct GNUNET_PSYC_CountersResultMessage), GNUNET_NO },
767 { &host_recv_enter_request, NULL,
768 GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
769 sizeof (struct GNUNET_PSYC_JoinRequestMessage), GNUNET_YES },
771 { &place_recv_message, NULL,
772 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE,
773 sizeof (struct GNUNET_PSYC_MessageHeader), GNUNET_YES },
775 { &place_recv_message_ack, NULL,
776 GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK,
777 sizeof (struct GNUNET_MessageHeader), GNUNET_NO },
779 { &guest_recv_join_decision, NULL,
780 GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
781 sizeof (struct GNUNET_PSYC_JoinDecisionMessage), GNUNET_YES },
783 { &place_recv_disconnect, NULL, 0, 0, GNUNET_NO },
785 { NULL, NULL, 0, 0, GNUNET_NO }
790 place_cleanup (struct GNUNET_SOCIAL_Place *plc)
792 GNUNET_PSYC_transmit_destroy (plc->tmit);
793 GNUNET_PSYC_receive_destroy (plc->recv);
794 GNUNET_free (plc->connect_msg);
795 if (NULL != plc->disconnect_cb)
796 plc->disconnect_cb (plc->disconnect_cls);
801 host_cleanup (void *cls)
803 struct GNUNET_SOCIAL_Host *hst = cls;
804 place_cleanup (&hst->plc);
810 guest_cleanup (void *cls)
812 struct GNUNET_SOCIAL_Guest *gst = cls;
813 place_cleanup (&gst->plc);
819 * Enter a place as host.
821 * A place is created upon first entering, and it is active until permanently
822 * left using GNUNET_SOCIAL_host_leave().
825 * Configuration to contact the social service.
827 * Identity of the host.
829 * Private-public key pair of the place.
830 * NULL for ephemeral places.
832 * Policy specifying entry and history restrictions for the place.
834 * Slicer to handle incoming messages.
835 * @param answer_door_cb
836 * Function to handle new nyms that want to enter.
838 * Function to handle departing nyms.
840 * Closure for the callbacks.
842 * @return Handle for the host.
844 struct GNUNET_SOCIAL_Host *
845 GNUNET_SOCIAL_host_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
846 const struct GNUNET_IDENTITY_Ego *ego,
847 const struct GNUNET_CRYPTO_EddsaPrivateKey *place_key,
848 enum GNUNET_PSYC_Policy policy,
849 struct GNUNET_SOCIAL_Slicer *slicer,
850 GNUNET_SOCIAL_HostEnterCallback enter_cb,
851 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
852 GNUNET_SOCIAL_FarewellCallback farewell_cb,
855 struct GNUNET_SOCIAL_Host *hst = GNUNET_malloc (sizeof (*hst));
856 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
857 struct HostEnterRequest *req = GNUNET_malloc (sizeof (*req));
859 if (NULL != place_key)
861 hst->place_key = *place_key;
865 struct GNUNET_CRYPTO_EddsaPrivateKey *
866 ephemeral_key = GNUNET_CRYPTO_eddsa_key_create ();
867 hst->place_key = *ephemeral_key;
868 GNUNET_CRYPTO_eddsa_key_get_public (&hst->place_key, &plc->pub_key);
869 GNUNET_CRYPTO_eddsa_key_clear (ephemeral_key);
870 GNUNET_free (ephemeral_key);
872 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
874 req->header.size = htons (sizeof (*req));
875 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER);
876 req->policy = policy;
877 req->place_key = hst->place_key;
878 req->host_key = plc->ego_key;
880 plc->connect_msg = (struct GNUNET_MessageHeader *) req;
882 plc->is_host = GNUNET_YES;
883 plc->slicer = slicer;
885 hst->plc.ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
886 hst->enter_cb = enter_cb;
887 hst->answer_door_cb = answer_door_cb;
890 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", host_handlers);
891 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, hst, sizeof (*plc));
893 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
894 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
896 place_send_connect_msg (plc);
902 * Enter a place as host.
904 * A place is created upon first entering, and it is active until permanently
905 * left using GNUNET_SOCIAL_host_leave().
908 * Configuration to contact the social service.
910 * Identity of the host.
912 * GNS name in the zone of the @a ego that contains the
913 * public key of the place in a PLACE record.
915 * Policy specifying entry and history restrictions for the place.
917 * Slicer to handle incoming messages.
918 * @param answer_door_cb
919 * Function to handle new nyms that want to enter.
921 * Function to handle departing nyms.
923 * Closure for the callbacks.
925 * @return Handle for the host.
927 struct GNUNET_SOCIAL_Host *
928 GNUNET_SOCIAL_host_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
929 struct GNUNET_IDENTITY_Ego *ego,
930 const char *gns_name,
931 enum GNUNET_PSYC_Policy policy,
932 struct GNUNET_SOCIAL_Slicer *slicer,
933 GNUNET_SOCIAL_HostEnterCallback enter_cb,
934 GNUNET_SOCIAL_AnswerDoorCallback answer_door_cb,
935 GNUNET_SOCIAL_FarewellCallback farewell_cb,
938 struct GNUNET_CRYPTO_EddsaPrivateKey place_key = {};
941 * 1. get public key by looking up PLACE entry under gns_name
942 * in the zone of the ego.
943 * 2. get private key from $GNUNET_DATA_HOME/social/places/PUB_KEY_HASH
946 return GNUNET_SOCIAL_host_enter (cfg, ego, &place_key, policy, slicer,
947 enter_cb, answer_door_cb, farewell_cb, cls);
952 * Decision whether to admit @a nym into the place or refuse entry.
957 * Handle for the entity that wanted to enter.
959 * #GNUNET_YES if @a nym is admitted,
960 * #GNUNET_NO if @a nym is refused entry,
961 * #GNUNET_SYSERR if we cannot answer the request.
963 * Method name for the rejection message.
965 * Environment containing variables for the message, or NULL.
967 * Data for the rejection message to send back.
969 * Number of bytes in @a data for method.
970 * @return #GNUNET_OK on success,
971 * #GNUNET_SYSERR if the message is too large.
974 GNUNET_SOCIAL_host_entry_decision (struct GNUNET_SOCIAL_Host *hst,
975 struct GNUNET_SOCIAL_Nym *nym,
977 const struct GNUNET_PSYC_Message *entry_resp)
979 struct GNUNET_PSYC_JoinDecisionMessage *dcsn;
980 uint16_t entry_resp_size
981 = (NULL != entry_resp) ? ntohs (entry_resp->header.size) : 0;
983 if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < sizeof (*dcsn) + entry_resp_size)
984 return GNUNET_SYSERR;
986 dcsn = GNUNET_malloc (sizeof (*dcsn) + entry_resp_size);
987 dcsn->header.size = htons (sizeof (*dcsn) + entry_resp_size);
988 dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION);
989 dcsn->is_admitted = htonl (is_admitted);
990 dcsn->slave_key = nym->pub_key;
992 if (0 < entry_resp_size)
993 memcpy (&dcsn[1], entry_resp, entry_resp_size);
995 GNUNET_CLIENT_MANAGER_transmit (hst->plc.client, &dcsn->header);
1001 * Throw @a nym out of the place.
1003 * The @a nym reference will remain valid until the
1004 * #GNUNET_SOCIAL_FarewellCallback is invoked,
1005 * which should be very soon after this call.
1007 * @param host Host of the place.
1008 * @param nym Handle for the entity to be ejected.
1011 GNUNET_SOCIAL_host_eject (struct GNUNET_SOCIAL_Host *host,
1012 struct GNUNET_SOCIAL_Nym *nym)
1019 * Get the public key of a @a nym.
1021 * Suitable, for example, to be used with GNUNET_NAMESTORE_zone_to_name().
1023 * @param nym Pseudonym to map to a cryptographic identifier.
1024 * @param[out] nym_key Set to the public key of the nym.
1026 struct GNUNET_CRYPTO_EcdsaPublicKey *
1027 GNUNET_SOCIAL_nym_get_key (struct GNUNET_SOCIAL_Nym *nym)
1029 return &nym->pub_key;
1034 * Obtain the private-public key pair of the hosted place.
1036 * The public part is suitable for storing in GNS within a PLACE record,
1037 * along with peer IDs to join at.
1040 * Host of the place.
1042 * @return Private-public key pair of the hosted place.
1044 const struct GNUNET_CRYPTO_EddsaPrivateKey *
1045 GNUNET_SOCIAL_host_get_place_key (struct GNUNET_SOCIAL_Host *hst)
1047 return &hst->place_key;
1052 namestore_result_host_advertise (void *cls, int32_t success, const char *emsg)
1059 * Connected to core service.
1062 core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1064 this_peer = *my_identity;
1070 * Advertise the place in the GNS zone of the @e ego of the @a host.
1072 * @param hst Host of the place.
1073 * @param name The name for the PLACE record to put in the zone.
1074 * @param peer_count Number of elements in the @a peers array.
1075 * @param peers List of peers in the PLACE record that can be used to send join
1077 * @param expiration_time Expiration time of the record, use 0 to remove the record.
1078 * @param password Password used to encrypt the record.
1081 GNUNET_SOCIAL_host_advertise (struct GNUNET_SOCIAL_Host *hst,
1084 const struct GNUNET_PeerIdentity *peers,
1085 struct GNUNET_TIME_Relative expiration_time,
1086 const char *password)
1088 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1089 if (NULL == namestore)
1090 namestore = GNUNET_NAMESTORE_connect (plc->cfg);
1092 core = GNUNET_CORE_connect (plc->cfg, NULL, core_connected_cb, NULL, NULL,
1093 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1095 struct GNUNET_GNSRECORD_Data rd = { 0 };
1096 rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
1097 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1099 = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, 1).rel_value_us;
1101 struct GNUNET_GNSRECORD_PlaceData *rec = GNUNET_malloc (sizeof (*rec));
1102 rec->place_key = plc->pub_key;
1103 rec->origin = this_peer;
1104 rec->relay_count = htons (0); // FIXME
1106 rd.data_size = sizeof (*rec);
1109 GNUNET_NAMESTORE_records_store (namestore, &hst->plc.ego_key,
1110 name, 1, &rd, namestore_result_host_advertise,
1116 * Send a message to all nyms that are present in the place.
1118 * This function is restricted to the host. Nyms can only send requests
1119 * to the host who can decide to relay it to everyone in the place.
1121 * @param host Host of the place.
1122 * @param method_name Method to use for the announcement.
1123 * @param env Environment containing variables for the message and operations
1124 * on objects of the place. Can be NULL.
1125 * @param notify Function to call to get the payload of the announcement.
1126 * @param notify_cls Closure for @a notify.
1127 * @param flags Flags for this announcement.
1129 * @return NULL on error (announcement already in progress?).
1131 struct GNUNET_SOCIAL_Announcement *
1132 GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
1133 const char *method_name,
1134 const struct GNUNET_ENV_Environment *env,
1135 GNUNET_PSYC_TransmitNotifyData notify_data,
1136 void *notify_data_cls,
1137 enum GNUNET_SOCIAL_AnnounceFlags flags)
1140 GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
1141 NULL, notify_data, notify_data_cls, flags));
1142 return (struct GNUNET_SOCIAL_Announcement *) hst->plc.tmit;
1147 * Resume transmitting announcement.
1150 * The announcement to resume.
1153 GNUNET_SOCIAL_host_announce_resume (struct GNUNET_SOCIAL_Announcement *a)
1155 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) a);
1160 * Cancel announcement.
1163 * The announcement to cancel.
1166 GNUNET_SOCIAL_host_announce_cancel (struct GNUNET_SOCIAL_Announcement *a)
1168 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) a);
1173 * Obtain handle for a hosted place.
1175 * The returned handle can be used to access the place API.
1177 * @param host Handle for the host.
1179 * @return Handle for the hosted place, valid as long as @a host is valid.
1181 struct GNUNET_SOCIAL_Place *
1182 GNUNET_SOCIAL_host_get_place (struct GNUNET_SOCIAL_Host *hst)
1189 * Stop hosting a place.
1191 * Invalidates host handle.
1193 * @param host Host leaving the place.
1194 * @param keep_active Keep the place active after last host disconnected.
1197 GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
1199 GNUNET_ContinuationCallback leave_cb,
1202 struct GNUNET_SOCIAL_Place *plc = &hst->plc;
1204 /* FIXME: send msg to service */
1206 plc->is_disconnecting = GNUNET_YES;
1207 plc->disconnect_cb = leave_cb;
1208 plc->disconnect_cls = leave_cls;
1210 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1211 &host_cleanup, hst);
1215 static struct GuestEnterRequest *
1216 guest_enter_request_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key,
1217 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
1218 const struct GNUNET_PeerIdentity *origin,
1220 const struct GNUNET_PeerIdentity *relays,
1221 const struct GNUNET_PSYC_Message *join_msg)
1223 uint16_t join_msg_size = ntohs (join_msg->header.size);
1224 uint16_t relay_size = relay_count * sizeof (*relays);
1226 struct GuestEnterRequest *
1227 req = GNUNET_malloc (sizeof (*req) + relay_size + join_msg_size);
1229 req->header.size = htons (sizeof (*req) + relay_size + join_msg_size);
1230 req->header.type = htons (GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER);
1231 req->place_key = *place_key;
1232 req->guest_key = *guest_key;
1233 req->origin = *origin;
1234 req->relay_count = relay_count;
1236 uint16_t p = sizeof (*req);
1239 memcpy ((char *) req + p, relays, relay_size);
1243 memcpy ((char *) req + p, join_msg, join_msg_size);
1248 * Request entry to a place as a guest.
1250 * @param cfg Configuration to contact the social service.
1251 * @param ego Identity of the guest.
1252 * @param crypto_address Public key of the place to enter.
1253 * @param origin Peer identity of the origin of the underlying multicast group.
1254 * @param relay_count Number of elements in the @a relays array.
1255 * @param relays Relays for the underlying multicast group.
1256 * @param method_name Method name for the message.
1257 * @param env Environment containing variables for the message, or NULL.
1258 * @param data Payload for the message to give to the enter callback.
1259 * @param data_size Number of bytes in @a data.
1260 * @param slicer Slicer to use for processing incoming requests from guests.
1262 * @return NULL on errors, otherwise handle for the guest.
1264 struct GNUNET_SOCIAL_Guest *
1265 GNUNET_SOCIAL_guest_enter (const struct GNUNET_CONFIGURATION_Handle *cfg,
1266 const struct GNUNET_IDENTITY_Ego *ego,
1267 const struct GNUNET_CRYPTO_EddsaPublicKey *place_key,
1268 const struct GNUNET_PeerIdentity *origin,
1269 uint32_t relay_count,
1270 const struct GNUNET_PeerIdentity *relays,
1271 const struct GNUNET_PSYC_Message *entry_msg,
1272 struct GNUNET_SOCIAL_Slicer *slicer,
1273 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
1274 GNUNET_SOCIAL_EntryDecisionCallback entry_dcsn_cb,
1277 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1278 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1280 struct GuestEnterRequest *
1281 req = guest_enter_request_create (&plc->ego_key, place_key, origin,
1282 relay_count, relays, entry_msg);
1283 plc->connect_msg = &req->header;
1284 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1285 plc->pub_key = *place_key;
1287 plc->is_host = GNUNET_YES;
1288 plc->slicer = slicer;
1290 gst->enter_cb = local_enter_cb;
1291 gst->entry_dcsn_cb = entry_dcsn_cb;
1294 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1295 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1297 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1298 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc->slicer);
1300 place_send_connect_msg (plc);
1306 * Result of a GNS name lookup for entering a place.
1308 * @see GNUNET_SOCIAL_guest_enter_by_name
1311 gns_result_guest_enter (void *cls, uint32_t rd_count,
1312 const struct GNUNET_GNSRECORD_Data *rd)
1314 struct GNUNET_SOCIAL_Guest *gst = cls;
1315 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1317 const struct GNUNET_GNSRECORD_PlaceData *
1318 rec = (const struct GNUNET_GNSRECORD_PlaceData *) rd->data;
1322 if (NULL != gst->enter_cb)
1323 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1328 if (rd->data_size < sizeof (*rec))
1330 GNUNET_break_op (0);
1331 if (NULL != gst->enter_cb)
1332 gst->enter_cb (gst->cb_cls, GNUNET_SYSERR, 0);
1336 struct GuestEnterRequest *
1337 req = (struct GuestEnterRequest *) plc->connect_msg;
1338 uint16_t req_size = ntohs (req->header.size);
1340 struct GNUNET_PeerIdentity *relays = NULL;
1341 uint16_t relay_count = ntohs (rec->relay_count);
1343 if (0 < relay_count)
1345 uint16_t relay_size = relay_count * sizeof (struct GNUNET_PeerIdentity);
1346 struct GuestEnterRequest *
1347 req2 = GNUNET_malloc (req_size + relay_size);
1349 req2->header.size = htons (req_size + relay_size);
1350 req2->header.type = req->header.type;
1351 req2->guest_key = req->guest_key;
1353 uint16_t p = sizeof (*req);
1356 memcpy ((char *) req2 + p, relays, relay_size);
1360 memcpy ((char *) req + p, &req[1], req_size - sizeof (*req));
1362 plc->connect_msg = &req2->header;
1367 req->place_key = rec->place_key;
1368 req->origin = rec->origin;
1369 req->relay_count = rec->relay_count;
1370 memcpy (&req[1], &rec[1],
1371 ntohl (rec->relay_count) * sizeof (struct GNUNET_PeerIdentity));
1373 plc->connect_msg = &req->header;
1374 plc->pub_key = req->place_key;
1376 plc->tmit = GNUNET_PSYC_transmit_create (plc->client);
1377 plc->recv = GNUNET_PSYC_receive_create (NULL, &slicer_message, plc);
1379 place_send_connect_msg (plc);
1383 * Request entry to a place as a guest.
1385 * @param cfg Configuration to contact the social service.
1386 * @param ego Identity of the guest.
1387 * @param address GNS name of the place to enter. Either in the form of
1388 * 'room.friend.gnu', or 'NYMPUBKEY.zkey'. This latter case refers to
1389 * the 'PLACE' record of the empty label ("+") in the GNS zone with the
1390 * nym's public key 'NYMPUBKEY', and can be used to request entry to a
1391 * pseudonym's place directly.
1392 * @param method_name Method name for the message.
1393 * @param env Environment containing variables for the message, or NULL.
1394 * @param data Payload for the message to give to the enter callback.
1395 * @param data_size Number of bytes in @a data.
1396 * @param slicer Slicer to use for processing incoming requests from guests.
1398 * @return NULL on errors, otherwise handle for the guest.
1400 struct GNUNET_SOCIAL_Guest *
1401 GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_CONFIGURATION_Handle *cfg,
1402 struct GNUNET_IDENTITY_Ego *ego,
1404 const struct GNUNET_PSYC_Message *join_msg,
1405 struct GNUNET_SOCIAL_Slicer *slicer,
1406 GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
1407 GNUNET_SOCIAL_EntryDecisionCallback entry_decision_cb,
1410 struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
1411 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1413 gst->enter_cb = local_enter_cb;
1416 plc->ego_key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1418 plc->is_host = GNUNET_NO;
1419 plc->slicer = slicer;
1421 struct GuestEnterRequest *
1422 req = guest_enter_request_create (&plc->ego_key, NULL, NULL, 0, NULL,
1424 plc->connect_msg = &req->header;
1426 /* FIXME: get the public key of the origin and relays
1427 * by looking up the PLACE record of gns_name.
1430 gns = GNUNET_GNS_connect (cfg);
1432 plc->client = GNUNET_CLIENT_MANAGER_connect (cfg, "social", guest_handlers);
1433 GNUNET_CLIENT_MANAGER_set_user_context_ (plc->client, gst, sizeof (*plc));
1435 struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key;
1436 GNUNET_IDENTITY_ego_get_public_key (ego, &ego_pub_key);
1437 GNUNET_GNS_lookup (gns, gns_name, &ego_pub_key,
1438 GNUNET_GNSRECORD_TYPE_PLACE, GNUNET_GNS_LO_DEFAULT,
1439 NULL, gns_result_guest_enter, gst);
1446 * Talk to the host of the place.
1449 * Place where we want to talk to the host.
1450 * @param method_name
1451 * Method to invoke on the host.
1453 * Environment containing variables for the message, or NULL.
1454 * @param notify_data
1455 * Function to use to get the payload for the method.
1456 * @param notify_data_cls
1457 * Closure for @a notify_data.
1459 * Flags for the message being sent.
1461 * @return NULL if we are already trying to talk to the host,
1462 * otherwise handle to cancel the request.
1464 struct GNUNET_SOCIAL_TalkRequest *
1465 GNUNET_SOCIAL_guest_talk (struct GNUNET_SOCIAL_Guest *gst,
1466 const char *method_name,
1467 const struct GNUNET_ENV_Environment *env,
1468 GNUNET_PSYC_TransmitNotifyData notify_data,
1469 void *notify_data_cls,
1470 enum GNUNET_SOCIAL_TalkFlags flags)
1473 GNUNET_PSYC_transmit_message (gst->plc.tmit, method_name, env,
1474 NULL, notify_data, notify_data_cls, flags));
1475 return (struct GNUNET_SOCIAL_TalkRequest *) gst->plc.tmit;
1480 * Resume talking to the host of the place.
1483 * Talk request to resume.
1486 GNUNET_SOCIAL_guest_talk_resume (struct GNUNET_SOCIAL_TalkRequest *tr)
1488 GNUNET_PSYC_transmit_resume ((struct GNUNET_PSYC_TransmitHandle *) tr);
1493 * Cancel talking to the host of the place.
1496 * Talk request to cancel.
1499 GNUNET_SOCIAL_guest_talk_cancel (struct GNUNET_SOCIAL_TalkRequest *tr)
1501 GNUNET_PSYC_transmit_cancel ((struct GNUNET_PSYC_TransmitHandle *) tr);
1506 * Leave a place permanently.
1508 * Notifies the owner of the place about leaving, and destroys the place handle.
1510 * @param place Place to leave permanently.
1511 * @param keep_active Keep place active after last application disconnected.
1514 GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
1516 GNUNET_ContinuationCallback leave_cb,
1519 struct GNUNET_SOCIAL_Place *plc = &gst->plc;
1521 /* FIXME: send msg to service */
1523 plc->is_disconnecting = GNUNET_YES;
1524 plc->disconnect_cb = leave_cb;
1525 plc->disconnect_cls = leave_cls;
1527 GNUNET_CLIENT_MANAGER_disconnect (plc->client, GNUNET_YES,
1528 &guest_cleanup, gst);
1533 * Obtain handle for a place entered as guest.
1535 * The returned handle can be used to access the place API.
1537 * @param guest Handle for the guest.
1539 * @return Handle for the place, valid as long as @a guest is valid.
1541 struct GNUNET_SOCIAL_Place *
1542 GNUNET_SOCIAL_guest_get_place (struct GNUNET_SOCIAL_Guest *gst)
1551 struct GNUNET_SOCIAL_HistoryLesson;
1554 * Learn about the history of a place.
1556 * Sends messages through the slicer function of the place where
1557 * start_message_id <= message_id <= end_message_id.
1558 * The messages will have the #GNUNET_PSYC_MESSAGE_HISTORIC flag set.
1560 * To get the latest message, use 0 for both the start and end message ID.
1562 * @param place Place we want to learn more about.
1563 * @param start_message_id First historic message we are interested in.
1564 * @param end_message_id Last historic message we are interested in (inclusive).
1565 * @param slicer Slicer to use to process history. Can be the same as the
1566 * slicer of the place, as the HISTORIC flag allows distinguishing
1567 * old messages from fresh ones.
1568 * @param finish_cb Function called after the last message in the history lesson
1569 * is passed through the @a slicer. NULL if not needed.
1570 * @param finish_cb_cls Closure for @a finish_cb.
1571 * @return Handle to abort history lesson, never NULL (multiple lessons
1572 * at the same time are allowed).
1574 struct GNUNET_SOCIAL_HistoryLesson *
1575 GNUNET_SOCIAL_place_get_history (struct GNUNET_SOCIAL_Place *place,
1576 uint64_t start_message_id,
1577 uint64_t end_message_id,
1578 const struct GNUNET_SOCIAL_Slicer *slicer,
1579 void (*finish_cb)(void *),
1580 void *finish_cb_cls)
1587 * Stop processing messages from the history lesson.
1589 * Must not be called after the finish callback of the history lesson is called.
1591 * @param hist History lesson to cancel.
1594 GNUNET_SOCIAL_place_get_history_cancel (struct GNUNET_SOCIAL_HistoryLesson *hist)
1600 struct GNUNET_SOCIAL_WatchHandle;
1603 * Watch a place for changed objects.
1607 * @param object_filter
1608 * Object prefix to match.
1609 * @param state_var_cb
1610 * Function to call when an object/state var changes.
1612 * Closure for callback.
1614 * @return Handle that can be used to cancel watching.
1616 struct GNUNET_SOCIAL_WatchHandle *
1617 GNUNET_SOCIAL_place_watch (struct GNUNET_SOCIAL_Place *place,
1618 const char *object_filter,
1619 GNUNET_PSYC_StateVarCallback state_var_cb,
1627 * Cancel watching a place for changed objects.
1629 * @param wh Watch handle to cancel.
1632 GNUNET_SOCIAL_place_watch_cancel (struct GNUNET_SOCIAL_WatchHandle *wh)
1638 struct GNUNET_SOCIAL_LookHandle;
1642 * Look at objects in the place with a matching name prefix.
1645 * The place to look its objects at.
1646 * @param name_prefix
1647 * Look at objects with names beginning with this value.
1648 * @param state_var_cb
1649 * Function to call for each object found.
1651 * Closure for callback function.
1653 * @return Handle that can be used to stop looking at objects.
1655 struct GNUNET_SOCIAL_LookHandle *
1656 GNUNET_SOCIAL_place_look (struct GNUNET_SOCIAL_Place *place,
1657 const char *name_prefix,
1658 GNUNET_PSYC_StateVarCallback state_var_cb,
1666 * Stop looking at objects.
1668 * @param lh Look handle to stop.
1671 GNUNET_SOCIAL_place_look_cancel (struct GNUNET_SOCIAL_LookHandle *lh)
1679 * Look at a particular object in the place.
1681 * The best matching object is returned (its name might be less specific than
1682 * what was requested).
1684 * @param place The place to look the object at.
1685 * @param full_name Full name of the object.
1686 * @param value_size Set to the size of the returned value.
1687 * @return NULL if there is no such object at this place.
1690 GNUNET_SOCIAL_place_look_at (struct GNUNET_SOCIAL_Place *place,
1691 const char *full_name,
1698 /* end of social_api.c */