+ GNUNET_free (filename);
+}
+
+
+/**
+ * Received a data fragment to be saved to disk.
+ *
+ * Append data fragment to the file.
+ */
+static void
+place_recv_save_data (void *cls,
+ const struct GNUNET_PSYC_MessageHeader *msg,
+ const struct GNUNET_MessageHeader *pmsg,
+ uint64_t message_id,
+ const void *data,
+ uint16_t data_size)
+{
+ struct Place *plc = cls;
+ if (GNUNET_YES != plc->file_save)
+ return;
+
+ char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key);
+ char *filename = NULL;
+ GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%" PRIu64 ".part",
+ dir_social, DIR_SEPARATOR,
+ "files", DIR_SEPARATOR,
+ place_pub_str, DIR_SEPARATOR,
+ GNUNET_ntohll (msg->message_id));
+ GNUNET_free (place_pub_str);
+ if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "create", filename);
+ GNUNET_free (filename);
+ return;
+ }
+
+ struct GNUNET_DISK_FileHandle *
+ fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL != fh)
+ {
+ if (plc->file_offset != GNUNET_DISK_file_seek
+ (fh, plc->file_offset, GNUNET_DISK_SEEK_SET)) {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "seek", filename);
+ GNUNET_DISK_file_close (fh);
+ GNUNET_free (filename);
+ return;
+ }
+ GNUNET_DISK_file_write (fh, data, data_size);
+ GNUNET_DISK_file_close (fh);
+ GNUNET_free (filename);
+ }
+ else
+ {
+ GNUNET_free (filename);
+ GNUNET_break (0);
+ }
+ plc->file_offset += data_size;
+}
+
+
+/**
+ * Received end of message to be saved to disk.
+ *
+ * Remove .part ending from the filename.
+ */
+static void
+place_recv_save_eom (void *cls,
+ const struct GNUNET_PSYC_MessageHeader *msg,
+ const struct GNUNET_MessageHeader *pmsg,
+ uint64_t message_id,
+ uint8_t is_cancelled)
+{
+ struct Place *plc = cls;
+ if (GNUNET_YES != plc->file_save)
+ return;
+
+ char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&plc->pub_key);
+ char *fn = NULL;
+ GNUNET_asprintf (&fn, "%s%c%s%c%s%c%" PRIu64,
+ dir_social, DIR_SEPARATOR,
+ "files", DIR_SEPARATOR,
+ place_pub_str, DIR_SEPARATOR,
+ GNUNET_ntohll (msg->message_id));
+ GNUNET_free (place_pub_str);
+ char *fn_part = NULL;
+ GNUNET_asprintf (&fn_part, "%s.part", fn);
+
+ if (rename (fn_part, fn)) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to rename %s into %s: %s (%d)\n",
+ fn_part, fn, strerror (errno), errno);
+ }
+
+ GNUNET_free (fn);
+ GNUNET_free (fn_part);
+}
+
+
+/**
+ * Initialize place data structure.
+ */
+static void
+place_init (struct Place *plc)
+{
+ plc->slicer = GNUNET_PSYC_slicer_create ();
+}
+
+
+/**
+ * Add a place to the @e places hash map.
+ *
+ * @param ereq
+ * Entry request.
+ *
+ * @return #GNUNET_OK if the place was added
+ * #GNUNET_NO if the place already exists in the hash map
+ * #GNUNET_SYSERR on error
+ */
+static int
+place_add (const struct PlaceEnterRequest *ereq)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding place to hashmap:\n");
+
+ struct EgoPlacePublicKey ego_place_pub_key = {
+ .ego_pub_key = ereq->ego_pub_key,
+ .place_pub_key = ereq->place_pub_key,
+ };
+ struct GNUNET_HashCode ego_place_pub_hash;
+ GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
+
+ struct GNUNET_MessageHeader *
+ place_msg = GNUNET_CONTAINER_multihashmap_get (places, &ego_place_pub_hash);
+ if (NULL != place_msg)
+ return GNUNET_NO;
+
+ place_msg = GNUNET_copy_message (&ereq->header);
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places, &ego_place_pub_hash, place_msg,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ {
+ GNUNET_break (0);
+ GNUNET_free (place_msg);
+ return GNUNET_SYSERR;
+ }
+
+ return GNUNET_OK;
+}
+
+/**
+ * Add a place to the @e app_places hash map.
+ *
+ * @param app_id
+ * Application ID.
+ * @param ereq
+ * Entry request.
+ *
+ * @return #GNUNET_OK if the place was added
+ * #GNUNET_NO if the place already exists in the hash map
+ * #GNUNET_SYSERR on error
+ */
+static int
+app_place_add (const char *app_id,
+ const struct PlaceEnterRequest *ereq)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding app place to hashmap:\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " app_id = %s\n", app_id);
+
+ struct GNUNET_HashCode app_id_hash;
+ GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
+
+ struct EgoPlacePublicKey ego_place_pub_key = {
+ .ego_pub_key = ereq->ego_pub_key,
+ .place_pub_key = ereq->place_pub_key,
+ };
+ struct GNUNET_HashCode ego_place_pub_hash;
+ GNUNET_CRYPTO_hash (&ego_place_pub_key, sizeof (ego_place_pub_key), &ego_place_pub_hash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " ego_place_pub_hash = %s\n", GNUNET_h2s (&ego_place_pub_hash));
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
+ if (NULL == app_places)
+ {
+ app_places = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ GNUNET_CONTAINER_multihashmap_put (apps_places, &app_id_hash, app_places,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ }
+
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (app_places, &ego_place_pub_hash))
+ return GNUNET_NO;
+
+ if (GNUNET_SYSERR == place_add (ereq))
+ return GNUNET_SYSERR;
+
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (app_places, &ego_place_pub_hash, NULL,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ struct GNUNET_HashCode place_pub_hash;
+ GNUNET_CRYPTO_hash (&ereq->place_pub_key, sizeof (ereq->place_pub_key), &place_pub_hash);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash);
+ if (NULL == place_apps)
+ {
+ place_apps = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (places_apps, &place_pub_hash, place_apps,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ {
+ GNUNET_break (0);
+ }
+ }
+
+ size_t app_id_size = strlen (app_id) + 1;
+ void *app_id_value = GNUNET_malloc (app_id_size);
+ GNUNET_memcpy (app_id_value, app_id, app_id_size);
+
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (place_apps, &app_id_hash, app_id_value,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+ {
+ GNUNET_break (0);
+ }
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Save place entry message to disk.
+ *
+ * @param app_id
+ * Application ID.
+ * @param ereq
+ * Entry request message.
+ */
+static int
+app_place_save (const char *app_id,
+ const struct PlaceEnterRequest *ereq)
+{
+ app_place_add (app_id, ereq);
+
+ if (NULL == dir_places)
+ return GNUNET_SYSERR;
+
+ char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ereq->ego_pub_key);
+ char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&ereq->place_pub_key);
+ char *filename = NULL;
+ GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s",
+ dir_social, DIR_SEPARATOR,
+ "places", DIR_SEPARATOR,
+ ego_pub_str, DIR_SEPARATOR,
+ place_pub_str);
+ int ret = GNUNET_DISK_directory_create_for_file (filename);
+ if (GNUNET_OK != ret
+ || 0 > GNUNET_DISK_fn_write (filename, ereq, ntohs (ereq->header.size),
+ GNUNET_DISK_PERM_USER_READ
+ | GNUNET_DISK_PERM_USER_WRITE))
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ }
+ GNUNET_free (filename);
+
+ if (ret == GNUNET_OK)
+ {
+ GNUNET_asprintf (&filename, "%s%c" "%s%c" "%s%c" "%s%c" "%s",
+ dir_social, DIR_SEPARATOR,
+ "apps", DIR_SEPARATOR,
+ app_id, DIR_SEPARATOR,
+ ego_pub_str, DIR_SEPARATOR,
+ place_pub_str);
+ ret = GNUNET_DISK_directory_create_for_file (filename);
+ if (GNUNET_OK != ret
+ || 0 > GNUNET_DISK_fn_write (filename, "", 0,
+ GNUNET_DISK_PERM_USER_READ
+ | GNUNET_DISK_PERM_USER_WRITE))
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ }
+ GNUNET_free (filename);
+ }
+ GNUNET_free (ego_pub_str);
+ GNUNET_free (place_pub_str);
+ return ret;
+}
+
+
+int
+app_place_remove (const char *app_id,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *ego_pub_key,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key)
+{
+ struct GNUNET_HashCode ego_pub_hash;
+ struct GNUNET_HashCode place_pub_hash;
+ GNUNET_CRYPTO_hash (ego_pub_key, sizeof (*ego_pub_key), &ego_pub_hash);
+ GNUNET_CRYPTO_hash (place_pub_key, sizeof (*place_pub_key), &place_pub_hash);
+
+ char *ego_pub_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (ego_pub_key);
+ char *place_pub_str = GNUNET_CRYPTO_eddsa_public_key_to_string (place_pub_key);
+ char *app_place_filename = NULL;
+ GNUNET_asprintf (&app_place_filename,
+ "%s%c" "%s%c" "%s%c" "%s%c" "%s",
+ dir_social, DIR_SEPARATOR,
+ "apps", DIR_SEPARATOR,
+ app_id, DIR_SEPARATOR,
+ ego_pub_str, DIR_SEPARATOR,
+ place_pub_str);
+ GNUNET_free (ego_pub_str);
+ GNUNET_free (place_pub_str);
+
+ struct GNUNET_HashCode app_id_hash;
+ GNUNET_CRYPTO_hash (app_id, strlen (app_id) + 1, &app_id_hash);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ app_places = GNUNET_CONTAINER_multihashmap_get (apps_places, &app_id_hash);
+
+ if (NULL != app_places)
+ GNUNET_CONTAINER_multihashmap_remove (app_places, &place_pub_hash, NULL);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ place_apps = GNUNET_CONTAINER_multihashmap_get (places_apps, &place_pub_hash);
+ if (NULL != place_apps)
+ {
+ void *app_id_value = GNUNET_CONTAINER_multihashmap_get (place_apps, &app_id_hash);
+ if (NULL != app_id_value)
+ {
+ GNUNET_CONTAINER_multihashmap_remove (place_apps, &app_id_hash, app_id_value);
+ GNUNET_free (app_id_value);
+ }
+ }
+
+ int ret = GNUNET_OK;
+
+ if (0 != unlink (app_place_filename))
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error removing app place file: %s: %s (%d)\n",
+ app_place_filename, strerror (errno), errno);
+ ret = GNUNET_SYSERR;
+ }
+ GNUNET_free (app_place_filename);
+
+ return ret;
+}
+
+
+/**
+ * Enter place as host.
+ *
+ * @param hreq
+ * Host entry request.
+ * @param[out] ret_hst
+ * Returned Host struct.
+ *
+ * @return #GNUNET_YES if the host entered the place just now,
+ * #GNUNET_NO if the place is already entered,
+ * #GNUNET_SYSERR if place_pub_key was set
+ * but its private key was not found
+ */
+static int
+host_enter (const struct HostEnterRequest *hreq, struct Host **ret_hst)
+{
+ int ret = GNUNET_NO;
+ struct GNUNET_HashCode place_pub_hash;
+ GNUNET_CRYPTO_hash (&hreq->place_pub_key, sizeof (hreq->place_pub_key),
+ &place_pub_hash);
+ struct Host *hst = GNUNET_CONTAINER_multihashmap_get (hosts, &place_pub_hash);
+
+ if (NULL == hst)
+ {
+ hst = GNUNET_new (struct Host);
+ hst->policy = hreq->policy;
+ hst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+ hst->relay_msgs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+
+ struct Place *plc = &hst->place;
+ place_init (plc);
+ plc->is_host = GNUNET_YES;
+ plc->pub_key = hreq->place_pub_key;
+ plc->pub_key_hash = place_pub_hash;
+
+ GNUNET_CONTAINER_multihashmap_put (hosts, &plc->pub_key_hash, plc,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ hst->master = GNUNET_PSYC_master_start (cfg, &hreq->place_key, hst->policy,
+ &psyc_master_started,
+ &psyc_recv_join_request,
+ &psyc_recv_message, NULL, hst);
+ plc->channel = GNUNET_PSYC_master_get_channel (hst->master);
+ ret = GNUNET_YES;
+ }
+
+ if (NULL != ret_hst)
+ *ret_hst = hst;
+ return ret;
+}
+
+
+static int
+msg_proc_parse (const struct MsgProcRequest *mpreq,
+ uint32_t *flags,
+ const char **method_prefix,
+ struct GNUNET_HashCode *method_hash)
+{
+ uint8_t method_size = ntohs (mpreq->header.size) - sizeof (*mpreq);
+ uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &mpreq[1],
+ method_size, 1, method_prefix);
+
+ if (0 == offset || offset != method_size || *method_prefix == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "offset = %u, method_size = %u, method_name = %s\n",
+ offset, method_size, *method_prefix);
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_CRYPTO_hash (*method_prefix, method_size, method_hash);
+ *flags = ntohl (mpreq->flags);
+ return GNUNET_OK;
+}
+
+
+static int
+check_client_msg_proc_set (void *cls,
+ const struct MsgProcRequest *mpreq)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle a client setting message proccesing flags for a method prefix.
+ */
+static void
+handle_client_msg_proc_set (void *cls,
+ const struct MsgProcRequest *mpreq)
+{
+ struct Client *c = cls;
+ struct GNUNET_SERVICE_Client *client = c->client;
+ struct Place *plc = c->place;
+ if (NULL == plc)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (client);
+ return;
+ }
+
+ const char *method_prefix = NULL;
+ uint32_t flags = 0;
+ struct GNUNET_HashCode method_hash;
+
+ if (GNUNET_OK !=
+ msg_proc_parse (mpreq, &flags, &method_prefix, &method_hash))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (client);
+ return;
+ }
+#if 0
+ GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix,
+ place_recv_relay_method,
+ place_recv_relay_modifier,
+ place_recv_relay_data,
+ place_recv_relay_eom);
+ GNUNET_PSYC_slicer_method_remove (plc->slicer, method_prefix,
+ place_recv_save_method,
+ NULL,
+ place_recv_save_data,
+ place_recv_save_eom);
+#endif
+ if (flags & GNUNET_SOCIAL_MSG_PROC_RELAY)
+ {
+ GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL,
+ place_recv_relay_method,
+ place_recv_relay_modifier,
+ place_recv_relay_data,
+ place_recv_relay_eom,
+ plc);
+ }
+ if (flags & GNUNET_SOCIAL_MSG_PROC_SAVE)
+ {
+ GNUNET_PSYC_slicer_method_add (plc->slicer, method_prefix, NULL,
+ place_recv_save_method,
+ NULL,
+ place_recv_save_data,
+ place_recv_save_eom,
+ plc);
+ }
+
+ /** @todo Save flags to be able to resume relaying/saving after restart */
+
+ GNUNET_SERVICE_client_continue (client);
+}
+
+
+/**
+ * Handle a connecting client requesting to clear all relay rules.
+ */
+static void
+handle_client_msg_proc_clear (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct Client *c = cls;
+ struct GNUNET_SERVICE_Client *client = c->client;
+ struct Place *plc = c->place;
+ if (NULL == plc)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (client);
+ return;
+ }
+
+ GNUNET_PSYC_slicer_clear (plc->slicer);
+
+ GNUNET_SERVICE_client_continue (client);
+}
+
+
+static int
+check_client_host_enter (void *cls,
+ const struct HostEnterRequest *hr)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle a connecting client entering a place as host.
+ */
+static void
+handle_client_host_enter (void *cls,
+ const struct HostEnterRequest *hr)
+{
+ struct Client *c = cls;
+ struct GNUNET_SERVICE_Client *client = c->client;
+
+ struct HostEnterRequest *
+ hreq = (struct HostEnterRequest *) GNUNET_copy_message (&hr->header);
+
+ uint8_t app_id_size = ntohs (hreq->header.size) - sizeof (*hreq);
+ const char *app_id = NULL;
+ uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &hreq[1],
+ app_id_size, 1, &app_id);
+ if (0 == offset || offset != app_id_size || app_id == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "offset = %u, app_id_size = %u, app_id = %s\n",
+ offset, app_id_size, app_id);
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (client);
+ return;
+ }
+
+ struct Host *hst = NULL;
+ struct Place *plc = NULL;
+ int ret = GNUNET_OK;
+
+ struct GNUNET_CRYPTO_EddsaPublicKey empty_pub_key;
+ memset (&empty_pub_key, 0, sizeof (empty_pub_key));
+
+ if (0 == memcmp (&hreq->place_pub_key, &empty_pub_key, sizeof (empty_pub_key)))
+ { // no public key set: create new private key & save the place
+ struct GNUNET_CRYPTO_EddsaPrivateKey *
+ place_key = GNUNET_CRYPTO_eddsa_key_create ();
+ hreq->place_key = *place_key;
+ GNUNET_CRYPTO_eddsa_key_get_public (place_key, &hreq->place_pub_key);
+ GNUNET_CRYPTO_eddsa_key_clear (place_key);
+ GNUNET_free (place_key);
+
+ app_place_save (app_id, (const struct PlaceEnterRequest *) hreq);
+ }
+
+ switch (host_enter (hreq, &hst))
+ {
+ case GNUNET_YES:
+ plc = c->place = &hst->place;
+ plc->host = hst;
+ break;
+
+ case GNUNET_NO:
+ {
+ plc = c->place = &hst->place;
+ plc->host = hst;
+ client_send_host_enter_ack (client, hst, GNUNET_OK);
+ break;
+ }
+ case GNUNET_SYSERR:
+ ret = GNUNET_SYSERR;
+ }
+
+ if (ret != GNUNET_SYSERR)
+ {
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%p Client connected as host to place %s.\n",
+ hst, GNUNET_h2s (&plc->pub_key_hash));
+
+ struct ClientListItem *cli = GNUNET_new (struct ClientListItem);
+ cli->client = client;
+ GNUNET_CONTAINER_DLL_insert (plc->clients_head, plc->clients_tail, cli);
+ c->place = plc;
+ }
+
+ GNUNET_CRYPTO_eddsa_key_clear (&hreq->place_key);
+ GNUNET_free (hreq);
+
+ if (GNUNET_OK == ret)
+ GNUNET_SERVICE_client_continue (client);
+ else
+ GNUNET_SERVICE_client_drop (client);
+}
+
+
+/**
+ * Enter place as guest.
+ *
+ * @param greq
+ * Guest entry request.
+ * @param[out] ret_gst
+ * Returned Guest struct.
+ *
+ * @return #GNUNET_YES if the guest entered the place just now,
+ * #GNUNET_NO if the place is already entered,
+ * #GNUNET_SYSERR on error.
+ */
+static int
+guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
+{
+ int ret = GNUNET_NO;
+ uint16_t greq_size = ntohs (greq->header.size);
+
+ struct GNUNET_CRYPTO_EcdsaPublicKey ego_pub_key = greq->ego_pub_key;
+ struct GNUNET_HashCode ego_pub_hash;
+ GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
+ struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
+
+ if (NULL == ego)
+ return GNUNET_SYSERR;
+
+ struct GNUNET_HashCode place_pub_hash;
+ GNUNET_CRYPTO_hash (&greq->place_pub_key, sizeof (greq->place_pub_key),
+ &place_pub_hash);
+
+ struct GNUNET_CONTAINER_MultiHashMap *
+ plc_gst = GNUNET_CONTAINER_multihashmap_get (place_guests, &place_pub_hash);
+ struct Guest *gst = NULL;
+
+ if (NULL != plc_gst)
+ gst = GNUNET_CONTAINER_multihashmap_get (plc_gst, &ego_pub_hash);
+
+ if (NULL == gst || NULL == gst->slave)