+static void
+namestore_recv_records_store_result (void *cls, int32_t result,
+ const char *err_msg)
+{
+ struct OperationClosure *ocls = cls;
+ client_send_result (ocls->client, ocls->op_id, result, err_msg,
+ (NULL != err_msg) ? strlen (err_msg) : 0);
+ GNUNET_free (ocls);
+}
+
+
+/**
+ * Handle request to add PLACE record to GNS zone.
+ */
+static void
+client_recv_zone_add_place (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct ZoneAddPlaceRequest *preq
+ = (const struct ZoneAddPlaceRequest *) msg;
+
+ uint16_t remaining = ntohs (preq->header.size) - sizeof (*preq);
+ const char *p = (const char *) &preq[1];
+ const char *name = NULL, *password = NULL;
+ uint16_t offset = GNUNET_STRINGS_buffer_tokenize (p, remaining, 2,
+ &name, &password);
+ remaining -= offset;
+ p += offset;
+ const struct GNUNET_PeerIdentity *
+ relays = (const struct GNUNET_PeerIdentity *) p;
+ uint16_t relay_size = ntohl (preq->relay_count) * sizeof (*relays);
+
+ if (0 == offset || remaining != relay_size)
+ {
+ GNUNET_break (0);
+ client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+
+ struct GNUNET_GNSRECORD_Data rd = { };
+ rd.record_type = GNUNET_GNSRECORD_TYPE_PLACE;
+ rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd.expiration_time = GNUNET_ntohll (preq->expiration_time);
+
+ struct GNUNET_GNSRECORD_PlaceData *
+ rec = GNUNET_malloc (sizeof (*rec) + relay_size);
+ rec->place_pub_key = preq->place_pub_key;
+ rec->origin = this_peer;
+ rec->relay_count = preq->relay_count;
+ memcpy (&rec[1], relays, relay_size);
+
+ rd.data = rec;
+ rd.data_size = sizeof (*rec) + relay_size;
+
+ struct GNUNET_HashCode ego_pub_hash;
+ GNUNET_CRYPTO_hash (&preq->ego_pub_key, sizeof (preq->ego_pub_key), &ego_pub_hash);
+ struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
+ if (NULL == ego)
+ {
+ client_send_result (client, preq->op_id, GNUNET_SYSERR, NULL, 0);
+ }
+ else
+ {
+ struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls));
+ ocls->client = client;
+ ocls->op_id = preq->op_id;
+ GNUNET_NAMESTORE_records_store (namestore, &ego->key,
+ name, 1, &rd,
+ namestore_recv_records_store_result, ocls);
+ }
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Handle request to add PLACE record to GNS zone.
+ */
+static void
+client_recv_zone_add_nym (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg)
+{
+ const struct ZoneAddNymRequest *nreq
+ = (const struct ZoneAddNymRequest *) msg;
+
+ uint16_t name_size = ntohs (nreq->header.size) - sizeof (*nreq);
+ const char *name = NULL;
+ uint16_t offset = GNUNET_STRINGS_buffer_tokenize ((const char *) &nreq[1],
+ name_size, 1, &name);
+ if (0 == offset || offset != name_size)
+ {
+ GNUNET_break (0);
+ client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+
+ struct GNUNET_GNSRECORD_Data rd = { };
+ rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
+ rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd.expiration_time = GNUNET_ntohll (nreq->expiration_time);
+ rd.data = &nreq->nym_pub_key;
+ rd.data_size = sizeof (nreq->nym_pub_key);
+
+ struct GNUNET_HashCode ego_pub_hash;
+ GNUNET_CRYPTO_hash (&nreq->ego_pub_key, sizeof (nreq->ego_pub_key), &ego_pub_hash);
+ struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
+ if (NULL == ego)
+ {
+ client_send_result (client, nreq->op_id, GNUNET_SYSERR, NULL, 0);
+ }
+ else
+ {
+ struct OperationClosure *ocls = GNUNET_malloc (sizeof (*ocls));
+ ocls->client = client;
+ ocls->op_id = nreq->op_id;
+ GNUNET_NAMESTORE_records_store (namestore, &ego->key,
+ name, 1, &rd,
+ namestore_recv_records_store_result, ocls);
+ }
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+