2 This file is part of GNUnet.
3 (C) 2012 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 namestore/gnunet-service-namestore.c
23 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
37 * A namestore operation.
39 struct GNUNET_NAMESTORE_ZoneIteration
42 * Next element in the DLL
44 struct GNUNET_NAMESTORE_ZoneIteration *next;
47 * Previous element in the DLL
49 struct GNUNET_NAMESTORE_ZoneIteration *prev;
52 * Namestore client which intiated this zone iteration
54 struct GNUNET_NAMESTORE_Client *client;
57 * GNUNET_YES if we iterate over a specific zone
58 * GNUNET_NO if we iterate over all zones
63 * Hash of the specific zone if 'has_zone' is GNUNET_YES,
64 * othwerwise set to '\0'
66 struct GNUNET_CRYPTO_ShortHashCode zone;
69 * The operation id fot the zone iteration in the response for the client
74 * Offset of the zone iteration used to address next result of the zone
75 * iteration in the store
77 * Initialy set to 0 in handle_iteration_start
78 * Incremented with by every call to handle_iteration_next
84 * Which flags must be included
86 uint16_t must_have_flags;
89 * Which flags must not be included
91 uint16_t must_not_have_flags;
98 struct GNUNET_NAMESTORE_Client
101 * Next element in the DLL
103 struct GNUNET_NAMESTORE_Client *next;
106 * Previous element in the DLL
108 struct GNUNET_NAMESTORE_Client *prev;
113 struct GNUNET_SERVER_Client *client;
117 * Zone iteration operations in progress initiated by this client
119 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
123 * Zone iteration operations in progress initiated by this client
125 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
130 * A container struct to store information belonging to a zone crypto key pair
132 struct GNUNET_NAMESTORE_CryptoContainer
135 * Filename where to store the container
140 * Short hash of the zone's public key
142 struct GNUNET_CRYPTO_ShortHashCode zone;
147 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
152 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
157 * Configuration handle.
159 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
164 struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
169 static char *zonefile_directory;
172 * Name of the database plugin
174 static char *db_lib_name;
177 * Our notification context.
179 static struct GNUNET_SERVER_NotificationContext *snc;
182 * Head of the Client DLL
184 static struct GNUNET_NAMESTORE_Client *client_head;
187 * Tail of the Client DLL
189 static struct GNUNET_NAMESTORE_Client *client_tail;
192 * Hashmap containing the zone keys this namestore has is authoritative for
194 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
195 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
197 struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
201 * Writes the encrypted private key of a zone in a file
203 * @param filename where to store the zone
204 * @param c the crypto container containing private key of the zone
205 * @return GNUNET_OK on success, GNUNET_SYSERR on fail
208 write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c)
210 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
211 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
212 struct GNUNET_DISK_FileHandle *fd;
214 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
216 struct GNUNET_CRYPTO_ShortHashCode zone;
217 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
218 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
220 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
223 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
224 _("File zone `%s' but corrupt content already exists, failed to write! \n"),
225 GNUNET_short_h2s (&zone));
226 return GNUNET_SYSERR;
229 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
230 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
231 GNUNET_CRYPTO_rsa_key_free (privkey);
233 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
236 _("File zone `%s' containing this key already exists\n"), GNUNET_short_h2s (&zone));
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
242 _("File zone `%s' but different zone key already exists, failed to write! \n"),
243 GNUNET_short_h2s (&zone));
247 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
252 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
254 /* must exist but not be accessible, fail for good! */
255 if (0 != ACCESS (filename, R_OK))
256 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
258 GNUNET_break (0); /* what is going on!? */
259 return GNUNET_SYSERR;
262 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
263 return GNUNET_SYSERR;
266 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
268 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
269 return GNUNET_SYSERR;
271 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
272 GNUNET_assert (enc != NULL);
273 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
275 GNUNET_DISK_file_sync (fd);
276 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
277 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
278 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "Stored zonekey for zone `%s' in file `%s'\n",
282 GNUNET_short_h2s(&c->zone), c->filename);
288 * Write all zone keys to disk.
289 * Iterates over all entries of the hashmap 'zonekeys'
292 * @param key zone key
293 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
295 * @return GNUNET_OK to continue iteration
298 zone_to_disk_it (void *cls,
299 const struct GNUNET_HashCode *key,
302 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
303 if (c->filename != NULL)
304 write_key_to_file(c->filename, c);
307 GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_short_h2s (&c->zone));
308 write_key_to_file(c->filename, c);
311 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
312 GNUNET_CRYPTO_rsa_key_free (c->privkey);
313 GNUNET_free (c->pubkey);
314 GNUNET_free (c->filename);
322 * Returns the expiration time of the given block of records
323 * The block expiration time is the expiration time of the block with smallest
326 * @param rd_count number of records given in 'rd'
327 * @param rd array of records
328 * @return absolute expiration time
330 static struct GNUNET_TIME_Absolute
331 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
334 struct GNUNET_TIME_Absolute expire = GNUNET_TIME_UNIT_FOREVER_ABS;
335 struct GNUNET_TIME_Absolute at;
336 struct GNUNET_TIME_Relative rt;
339 return GNUNET_TIME_UNIT_ZERO_ABS;
340 for (c = 0; c < rd_count; c++)
342 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
344 rt.rel_value = rd[c].expiration_time;
345 at = GNUNET_TIME_relative_to_absolute (rt);
349 at.abs_value = rd[c].expiration_time;
351 expire = GNUNET_TIME_absolute_min (at, expire);
357 * Task run during shutdown.
363 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
366 struct GNUNET_NAMESTORE_ZoneIteration *no;
367 struct GNUNET_NAMESTORE_ZoneIteration *tmp;
368 struct GNUNET_NAMESTORE_Client *nc;
369 struct GNUNET_NAMESTORE_Client *next;
373 GNUNET_SERVER_notification_context_destroy (snc);
376 GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL);
377 GNUNET_CONTAINER_multihashmap_destroy(zonekeys);
379 for (nc = client_head; nc != NULL; nc = next)
382 for (no = nc->op_head; no != NULL; no = tmp)
384 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
388 GNUNET_SERVER_client_drop(nc->client);
389 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
393 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
394 GNUNET_free (db_lib_name);
395 GNUNET_free_non_null(zonefile_directory);
398 static struct GNUNET_NAMESTORE_Client *
399 client_lookup (struct GNUNET_SERVER_Client *client)
401 struct GNUNET_NAMESTORE_Client *nc;
403 GNUNET_assert (NULL != client);
405 for (nc = client_head; nc != NULL; nc = nc->next)
407 if (client == nc->client)
415 * Called whenever a client is disconnected.
416 * Frees our resources associated with that client.
419 * @param client identification of the client
422 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
424 struct GNUNET_NAMESTORE_ZoneIteration *no;
425 struct GNUNET_NAMESTORE_Client *nc;
429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
431 nc = client_lookup (client);
433 if ((NULL == client) || (NULL == nc))
439 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
444 GNUNET_SERVER_client_drop(nc->client);
445 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
452 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
455 * @param client GNUNET_SERVER_Client sending the message
456 * @param message unused
459 handle_start (void *cls,
460 struct GNUNET_SERVER_Client *client,
461 const struct GNUNET_MessageHeader *message)
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
465 struct GNUNET_NAMESTORE_Client *nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
467 GNUNET_SERVER_notification_context_add (snc, client);
468 GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
469 GNUNET_SERVER_client_keep (client);
470 GNUNET_SERVER_receive_done (client, GNUNET_OK);
477 * Context for name lookups passed from 'handle_lookup_name' to
478 * 'handle_lookup_name_it' as closure
480 struct LookupNameContext
483 * The client to send the response to
485 struct GNUNET_NAMESTORE_Client *nc;
488 * Operation id for the name lookup
493 * Requested specific record type
495 uint32_t record_type;
500 struct GNUNET_CRYPTO_ShortHashCode *zone;
510 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
512 * @param cls a 'struct LookupNameContext *' with information about the request
513 * @param zone_key zone key of the zone
514 * @param expire expiration time
516 * @param rd_count number of records
517 * @param rd array of records
518 * @param signature signature
521 handle_lookup_name_it (void *cls,
522 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
523 struct GNUNET_TIME_Absolute expire,
525 unsigned int rd_count,
526 const struct GNUNET_NAMESTORE_RecordData *rd,
527 const struct GNUNET_CRYPTO_RsaSignature *signature)
530 struct LookupNameContext *lnc = cls;
531 struct LookupNameResponseMessage *lnr_msg;
532 struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
533 struct GNUNET_NAMESTORE_CryptoContainer *cc;
534 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
535 struct GNUNET_TIME_Absolute e;
536 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
537 struct GNUNET_HashCode long_hash;
544 int copied_elements = 0;
545 int contains_signature = GNUNET_NO;
546 int authoritative = GNUNET_NO;
550 name_len = strlen(name) + 1;
552 /* count records to copy */
555 if (lnc->record_type != 0)
557 /* special record type needed */
558 for (c = 0; c < rd_count; c ++)
559 if (rd[c].record_type == lnc->record_type)
560 copied_elements++; /* found matching record */
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
562 copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone));
563 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
565 for (c = 0; c < rd_count; c ++)
567 if (rd[c].record_type == lnc->record_type)
569 /* found matching record */
570 memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
577 copied_elements = rd_count;
578 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
586 expire = GNUNET_TIME_UNIT_ZERO_ABS;
589 rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
590 char rd_ser[rd_ser_len];
591 GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
594 copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone));
596 if ((copied_elements == rd_count) && (NULL != signature))
597 contains_signature = GNUNET_YES; /* returning all records, so include signature */
599 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
602 if ((NULL != zone_key) && (copied_elements == rd_count))
604 GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
605 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
606 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
608 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
609 e = get_block_expiration_time(rd_count, rd);
610 signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
611 GNUNET_assert (signature_new != NULL);
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for name `%s' with %u records in zone `%s'\n",name, copied_elements, GNUNET_short_h2s(&zone_key_hash));
613 authoritative = GNUNET_YES;
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash));
619 r_size = sizeof (struct LookupNameResponseMessage) +
620 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
625 lnr_msg = GNUNET_malloc (r_size);
626 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
627 lnr_msg->gns_header.header.size = ntohs (r_size);
628 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
629 lnr_msg->rd_count = htons (copied_elements);
630 lnr_msg->rd_len = htons (rd_ser_len);
631 lnr_msg->name_len = htons (name_len);
632 lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
634 if (rd_selected != rd)
635 GNUNET_free (rd_selected);
637 if (zone_key != NULL)
638 lnr_msg->public_key = (*zone_key);
640 memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
642 if (GNUNET_YES == authoritative)
643 { /* use new created signature */
644 lnr_msg->contains_sig = htons (GNUNET_YES);
645 GNUNET_assert (signature_new != NULL);
646 lnr_msg->signature = *signature_new;
647 GNUNET_free (signature_new);
649 else if (GNUNET_YES == contains_signature)
651 /* use existing signature */
652 lnr_msg->contains_sig = htons (GNUNET_YES);
653 GNUNET_assert (signature != NULL);
654 lnr_msg->signature = *signature;
658 /* use no signature */
659 memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
662 name_tmp = (char *) &lnr_msg[1];
663 rd_tmp = &name_tmp[name_len];
665 memcpy (name_tmp, name, name_len);
666 memcpy (rd_tmp, rd_ser, rd_ser_len);
668 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
669 GNUNET_free (lnr_msg);
673 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
676 * @param client GNUNET_SERVER_Client sending the message
677 * @param message message of type 'struct LookupNameMessage'
680 handle_lookup_name (void *cls,
681 struct GNUNET_SERVER_Client *client,
682 const struct GNUNET_MessageHeader *message)
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
685 struct LookupNameContext lnc;
686 struct GNUNET_NAMESTORE_Client *nc;
692 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
695 GNUNET_SERVER_receive_done (client, GNUNET_OK);
699 nc = client_lookup(client);
703 GNUNET_SERVER_receive_done (client, GNUNET_OK);
707 struct LookupNameMessage *ln_msg = (struct LookupNameMessage *) message;
708 rid = ntohl (ln_msg->gns_header.r_id);
709 name_len = ntohl (ln_msg->name_len);
710 type = ntohl (ln_msg->record_type);
712 if ((name_len == 0) || (name_len > 256))
715 GNUNET_SERVER_receive_done (client, GNUNET_OK);
719 name = (char *) &ln_msg[1];
720 if (name[name_len -1] != '\0')
723 GNUNET_SERVER_receive_done (client, GNUNET_OK);
728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone));
730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_short_h2s(&ln_msg->zone));
732 /* do the actual lookup */
733 lnc.request_id = rid;
735 lnc.record_type = type;
737 lnc.zone = &ln_msg->zone;
738 GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
740 GNUNET_SERVER_receive_done (client, GNUNET_OK);
745 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
748 * @param client GNUNET_SERVER_Client sending the message
749 * @param message message of type 'struct RecordPutMessage'
752 handle_record_put (void *cls,
753 struct GNUNET_SERVER_Client *client,
754 const struct GNUNET_MessageHeader *message)
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
757 struct GNUNET_NAMESTORE_Client *nc;
758 struct RecordPutMessage *rp_msg;
759 struct GNUNET_TIME_Absolute expire;
760 struct GNUNET_CRYPTO_RsaSignature *signature;
761 struct RecordPutResponseMessage rpr_msg;
762 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
771 int res = GNUNET_SYSERR;
773 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
776 GNUNET_SERVER_receive_done (client, GNUNET_OK);
780 nc = client_lookup (client);
784 GNUNET_SERVER_receive_done (client, GNUNET_OK);
788 rp_msg = (struct RecordPutMessage *) message;
789 rid = ntohl (rp_msg->gns_header.r_id);
790 msg_size = ntohs (rp_msg->gns_header.header.size);
791 name_len = ntohs (rp_msg->name_len);
792 rd_count = ntohs (rp_msg->rd_count);
793 rd_ser_len = ntohs(rp_msg->rd_len);
795 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
798 GNUNET_SERVER_receive_done (client, GNUNET_OK);
802 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
805 GNUNET_SERVER_receive_done (client, GNUNET_OK);
809 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
810 if (msg_size != msg_size_exp)
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
814 GNUNET_SERVER_receive_done (client, GNUNET_OK);
817 if ((name_len == 0) || (name_len > 256))
820 GNUNET_SERVER_receive_done (client, GNUNET_OK);
824 name = (char *) &rp_msg[1];
826 if (name[name_len -1] != '\0')
829 GNUNET_SERVER_receive_done (client, GNUNET_OK);
833 expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
834 signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
836 rd_ser = &name[name_len];
837 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
838 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
839 if (res != GNUNET_OK)
845 GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash));
848 /* Database operation */
849 res = GSN_database->put_records(GSN_database->cls,
856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
857 name, (res == GNUNET_OK) ? "OK" : "FAIL");
861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
862 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
863 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
864 rpr_msg.gns_header.r_id = htonl (rid);
865 rpr_msg.op_result = htonl (res);
866 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
868 GNUNET_SERVER_receive_done (client, GNUNET_OK);
873 * CreateRecordContext
875 * Context for record create operations passed from 'handle_record_create' to
876 * 'handle_create_record_it' as closure
878 struct CreateRecordContext
883 struct GNUNET_NAMESTORE_RecordData *rd;
888 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
893 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
896 * Record expiration time
898 struct GNUNET_TIME_Absolute expire;
901 * Name for the record to create
906 * result returned from 'handle_create_record_it'
907 * GNUNET_SYSERR: failed to create the record
908 * GNUNET_NO: we updated an existing record or identical entry existed
909 * GNUNET_YES : we created a new record
916 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
917 * in handle_record_create
919 * @param cls a 'struct CreateRecordContext *' with information about the request
920 * @param pubkey zone key of the zone
921 * @param expire expiration time
923 * @param rd_count number of records
924 * @param rd array of records
925 * @param signature signature
928 handle_create_record_it (void *cls,
929 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
930 struct GNUNET_TIME_Absolute expire,
932 unsigned int rd_count,
933 const struct GNUNET_NAMESTORE_RecordData *rd,
934 const struct GNUNET_CRYPTO_RsaSignature *signature)
936 struct CreateRecordContext *crc = cls;
937 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
938 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
939 struct GNUNET_TIME_Absolute block_expiration;
941 int exist = GNUNET_SYSERR;
942 int update = GNUNET_NO;
944 int rd_count_new = 0;
946 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
947 for (c = 0; c < rd_count; c++)
949 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) &&
950 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
952 /* Update unique PKEY */
957 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) &&
958 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
960 /* Update unique PSEU */
965 if ((crc->rd->record_type == rd[c].record_type) &&
966 (crc->rd->data_size == rd[c].data_size) &&
967 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 "Found existing records for `%s' to update expiration date!\n",
973 if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
974 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
975 == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
981 if (exist == GNUNET_SYSERR)
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984 "No existing record for name `%s'!\n",
986 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
987 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
988 rd_count_new = rd_count + 1;
989 rd_new[rd_count] = *(crc->rd);
991 else if (update == GNUNET_NO)
993 /* Exact same record already exists */
994 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
995 "Matching record for %s' exists, no change required!\n",
1003 GNUNET_assert (GNUNET_YES == update);
1004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005 "Updating existing records for `%s'!\n",
1007 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
1008 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1009 rd_count_new = rd_count;
1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1011 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1012 ? "Updating absolute expiration from %llu to %llu!\n"
1013 : "Updating relative expiration from %llu to %llu!\n",
1014 rd_new[exist].expiration_time, crc->rd->expiration_time);
1015 rd_new[exist] = *(crc->rd);
1018 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1019 if (block_expiration.abs_value != expire.abs_value)
1020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1021 "Updated block expiration time\n");
1023 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1025 /* Database operation */
1026 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1027 res = GSN_database->put_records(GSN_database->cls,
1028 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1031 rd_count_new, rd_new,
1033 GNUNET_break (GNUNET_OK == res);
1034 if (res == GNUNET_OK)
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1041 GNUNET_free_non_null (rd_new);
1045 /* failed to create the record */
1046 crc->res = GNUNET_SYSERR;
1049 /* database operations OK */
1050 if (GNUNET_YES == update)
1052 /* we updated an existing record */
1053 crc->res = GNUNET_NO;
1057 /* we created a new record */
1058 crc->res = GNUNET_YES;
1062 /* identical entry existed, so we did nothing */
1063 crc->res = GNUNET_NO;
1068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1073 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1076 * @param client GNUNET_SERVER_Client sending the message
1077 * @param message message of type 'struct RecordCreateMessage'
1080 handle_record_create (void *cls,
1081 struct GNUNET_SERVER_Client *client,
1082 const struct GNUNET_MessageHeader *message)
1084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1085 struct GNUNET_NAMESTORE_Client *nc;
1086 struct RecordCreateMessage *rp_msg;
1087 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1088 struct CreateRecordContext crc;
1089 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1090 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1091 struct RecordCreateResponseMessage rcr_msg;
1092 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1093 struct GNUNET_HashCode long_hash;
1096 size_t msg_size_exp;
1105 int res = GNUNET_SYSERR;
1106 crc.res = GNUNET_SYSERR;
1108 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1110 GNUNET_break_op (0);
1111 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1115 nc = client_lookup(client);
1118 GNUNET_break_op (0);
1119 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1123 rp_msg = (struct RecordCreateMessage *) message;
1124 rid = ntohl (rp_msg->gns_header.r_id);
1125 name_len = ntohs (rp_msg->name_len);
1126 msg_size = ntohs (message->size);
1127 rd_count = ntohs (rp_msg->rd_count);
1128 rd_ser_len = ntohs (rp_msg->rd_len);
1129 key_len = ntohs (rp_msg->pkey_len);
1130 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1132 if (msg_size != msg_size_exp)
1134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1135 GNUNET_break_op (0);
1136 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1140 if ((name_len == 0) || (name_len > 256))
1142 GNUNET_break_op (0);
1143 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1147 pkey_tmp = (char *) &rp_msg[1];
1148 name_tmp = &pkey_tmp[key_len];
1149 rd_ser = &name_tmp[name_len];
1151 if (name_tmp[name_len -1] != '\0')
1153 GNUNET_break_op (0);
1154 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1158 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1160 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1161 if ((res != GNUNET_OK) || (rd_count != 1))
1163 GNUNET_break_op (0);
1166 /* Extracting and converting private key */
1167 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1168 GNUNET_assert (pkey != NULL);
1169 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1170 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1171 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1173 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1177 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1178 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1179 cc->pubkey = GNUNET_malloc(sizeof (pub));
1180 memcpy (cc->pubkey, &pub, sizeof(pub));
1181 cc->zone = pubkey_hash;
1182 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1185 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1186 crc.res = GNUNET_SYSERR;
1190 crc.name = name_tmp;
1192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1194 /* Get existing records for name */
1195 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1196 if (res != GNUNET_SYSERR)
1198 GNUNET_CRYPTO_rsa_key_free(pkey);
1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1204 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1205 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1206 rcr_msg.gns_header.r_id = htonl (rid);
1207 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1208 rcr_msg.op_result = htonl (GNUNET_YES);
1209 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1210 rcr_msg.op_result = htonl (GNUNET_NO);
1212 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1213 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1215 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1220 * RemoveRecordContext
1222 * Context for record remove operations passed from 'handle_record_remove' to
1223 * 'handle_record_remove_it' as closure
1225 struct RemoveRecordContext
1230 struct GNUNET_NAMESTORE_RecordData *rd;
1233 * Zone's private keys
1235 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1244 * 1 : Could not find record to remove, empty result set
1245 * 2 : Could not find record to remove, record did not exist in result set
1246 * 3 : Could not remove records from database
1247 * 4 : Could not put records into database
1257 handle_record_remove_it (void *cls,
1258 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1259 struct GNUNET_TIME_Absolute expire,
1261 unsigned int rd_count,
1262 const struct GNUNET_NAMESTORE_RecordData *rd,
1263 const struct GNUNET_CRYPTO_RsaSignature *signature)
1265 struct RemoveRecordContext *rrc = cls;
1269 unsigned int rd_count_new;
1271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1275 /* Could not find record to remove */
1280 /* Find record to remove */
1281 found = GNUNET_SYSERR;
1282 for (c = 0; c < rd_count; c++)
1285 if (rd[c].flags != rrc->rd->flags)
1287 if (rd[c].record_type != rrc->rd->record_type)
1290 if (rd[c].data_size != rrc->rd->data_size)
1293 if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1300 if (GNUNET_SYSERR == found)
1302 /* Could not find record to remove */
1307 if (rd_count-1 == 0)
1309 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1310 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1311 res = GSN_database->remove_records (GSN_database->cls,
1314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1315 "No records left for name `%s', removing name\n",
1317 if (GNUNET_OK != res)
1319 /* Could not remove records from database */
1327 rd_count_new = rd_count -1;
1328 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1330 unsigned int c2 = 0;
1331 for (c = 0; c < rd_count; c++)
1335 GNUNET_assert (c2 < rd_count_new);
1341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1343 /* Create dummy signature */
1344 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1345 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1349 res = GSN_database->put_records(GSN_database->cls,
1353 rd_count_new, rd_new,
1355 if (GNUNET_OK != res)
1357 /* Could not put records into database */
1367 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1370 * @param client GNUNET_SERVER_Client sending the message
1371 * @param message message of type 'struct RecordRemoveMessage'
1374 handle_record_remove (void *cls,
1375 struct GNUNET_SERVER_Client *client,
1376 const struct GNUNET_MessageHeader *message)
1378 struct GNUNET_NAMESTORE_Client *nc;
1379 const struct RecordRemoveMessage *rr_msg;
1380 struct RecordRemoveResponseMessage rrr_msg;
1381 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1382 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1383 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1384 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1385 struct GNUNET_HashCode long_hash;
1386 const char *pkey_tmp;
1387 const char *name_tmp;
1393 size_t msg_size_exp = 0;
1397 int res = GNUNET_SYSERR;
1399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1400 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1402 GNUNET_break_op (0);
1403 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1407 nc = client_lookup(client);
1410 GNUNET_break_op (0);
1411 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1415 rr_msg = (const struct RecordRemoveMessage *) message;
1416 rid = ntohl (rr_msg->gns_header.r_id);
1417 name_len = ntohs (rr_msg->name_len);
1418 rd_ser_len = ntohs (rr_msg->rd_len);
1419 rd_count = ntohs (rr_msg->rd_count);
1420 key_len = ntohs (rr_msg->pkey_len);
1421 msg_size = ntohs (message->size);
1423 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1425 GNUNET_break_op (0);
1426 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1430 if ((name_len >=256) || (name_len == 0))
1432 GNUNET_break_op (0);
1433 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1437 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1438 if (msg_size != msg_size_exp)
1440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1441 GNUNET_break_op (0);
1442 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1446 pkey_tmp = (const char *) &rr_msg[1];
1447 name_tmp = &pkey_tmp[key_len];
1448 rd_ser = &name_tmp[name_len];
1451 if ((name_len == 0) || (name_len > 256))
1453 GNUNET_break_op (0);
1454 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1458 if (name_tmp[name_len -1] != '\0')
1460 GNUNET_break_op (0);
1461 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1465 /* Extracting and converting private key */
1466 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1467 GNUNET_assert (pkey != NULL);
1468 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1469 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1470 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1472 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475 "Received new private key for zone `%s'\n",
1476 GNUNET_short_h2s(&pubkey_hash));
1477 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1478 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1479 cc->pubkey = GNUNET_malloc(sizeof (pub));
1480 memcpy (cc->pubkey, &pub, sizeof(pub));
1481 cc->zone = pubkey_hash;
1483 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1487 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1488 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1489 if ((res != GNUNET_OK) || (rd_count > 1))
1491 GNUNET_break_op (0);
1497 /* remove the whole name and all records */
1498 /* Database operation */
1499 res = GSN_database->remove_records (GSN_database->cls,
1502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1503 name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1505 if (GNUNET_OK != res)
1506 /* Could not remove entry from database */
1513 /* remove a single record */
1514 struct RemoveRecordContext rrc;
1518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1520 /* Database operation */
1521 res = GSN_database->iterate_records (GSN_database->cls,
1525 handle_record_remove_it, &rrc);
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1528 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1534 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1535 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1536 rrr_msg.gns_header.r_id = htonl (rid);
1537 rrr_msg.op_result = htonl (res);
1538 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1540 GNUNET_CRYPTO_rsa_key_free (pkey);
1542 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1548 * Context for record remove operations passed from 'handle_zone_to_name' to
1549 * 'handle_zone_to_name_it' as closure
1551 struct ZoneToNameCtx
1556 struct GNUNET_NAMESTORE_Client *nc;
1566 * Zone to name iterator
1568 * @param cls struct ZoneToNameCtx *
1569 * @param zone_key the zone key
1570 * @param expire expiration date
1572 * @param rd_count number of records
1573 * @param rd record data
1574 * @param signature signature
1577 handle_zone_to_name_it (void *cls,
1578 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1579 struct GNUNET_TIME_Absolute expire,
1581 unsigned int rd_count,
1582 const struct GNUNET_NAMESTORE_RecordData *rd,
1583 const struct GNUNET_CRYPTO_RsaSignature *signature)
1585 struct ZoneToNameCtx *ztn_ctx = cls;
1586 struct ZoneToNameResponseMessage *ztnr_msg;
1587 int16_t res = GNUNET_SYSERR;
1588 uint16_t name_len = 0;
1589 uint16_t rd_ser_len = 0 ;
1590 int32_t contains_sig = 0;
1591 size_t msg_size = 0;
1593 char *rd_ser = NULL;
1598 if ((zone_key != NULL) && (name != NULL))
1601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1603 name_len = strlen (name) +1;
1607 /* no result found */
1608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1615 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1616 rd_ser = GNUNET_malloc (rd_ser_len);
1617 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1622 if (signature != NULL)
1623 contains_sig = GNUNET_YES;
1625 contains_sig = GNUNET_NO;
1627 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1628 ztnr_msg = GNUNET_malloc (msg_size);
1630 name_tmp = (char *) &ztnr_msg[1];
1631 rd_tmp = &name_tmp[name_len];
1632 sig_tmp = &rd_tmp[rd_ser_len];
1634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1635 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1636 ztnr_msg->gns_header.header.size = htons (msg_size);
1637 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1638 ztnr_msg->res = htons (res);
1639 ztnr_msg->rd_len = htons (rd_ser_len);
1640 ztnr_msg->rd_count = htons (rd_count);
1641 ztnr_msg->name_len = htons (name_len);
1642 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1643 if (zone_key != NULL)
1644 ztnr_msg->zone_key = *zone_key;
1646 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1648 if ((name_len > 0) && (name != NULL))
1649 memcpy (name_tmp, name, name_len);
1651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name is `%s', has %u records, rd ser len %u msg_size %u\n", name, rd_count, rd_ser_len, msg_size);
1652 if ((rd_ser_len > 0) && (rd_ser != NULL))
1653 memcpy (rd_tmp, rd_ser, rd_ser_len);
1654 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1655 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1657 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1658 GNUNET_free (ztnr_msg);
1659 GNUNET_free_non_null (rd_ser);
1664 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1667 * @param client GNUNET_SERVER_Client sending the message
1668 * @param message message of type 'struct ZoneToNameMessage'
1671 handle_zone_to_name (void *cls,
1672 struct GNUNET_SERVER_Client *client,
1673 const struct GNUNET_MessageHeader *message)
1675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1676 struct GNUNET_NAMESTORE_Client *nc;
1677 struct ZoneToNameMessage *ztn_msg;
1678 struct ZoneToNameCtx ztn_ctx;
1679 size_t msg_size = 0;
1682 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1684 GNUNET_break_op (0);
1685 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1689 nc = client_lookup(client);
1692 GNUNET_break_op (0);
1693 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1697 ztn_msg = (struct ZoneToNameMessage *) message;
1699 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1701 GNUNET_break_op (0);
1702 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1706 rid = ntohl (ztn_msg->gns_header.r_id);
1711 struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1712 GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1715 GNUNET_short_h2s (&ztn_msg->value_zone));
1717 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1719 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1724 * Copy record, data has to be free'd separetely
1726 * @param src source record
1727 * @param dest destination record
1730 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1732 memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1733 dest->data = GNUNET_malloc (src->data_size);
1734 memcpy ((void *) dest->data, src->data, src->data_size);
1739 * ZoneIterationProcResult
1741 * Context for record remove operations passed from
1742 * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1744 struct ZoneIterationProcResult
1747 * The zone iteration handle
1749 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1752 * Iteration result: iteration done?
1754 int res_iteration_finished;
1757 * Iteration result: number of records included
1759 int records_included;
1762 * Iteration result: is a valid signature included?
1774 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1779 struct GNUNET_NAMESTORE_RecordData *rd;
1784 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1789 struct GNUNET_CRYPTO_RsaSignature signature;
1794 struct GNUNET_TIME_Absolute expire;
1799 * Process results for zone iteration from database
1801 * @param cls struct ZoneIterationProcResult *proc
1802 * @param zone_key the zone key
1803 * @param expire expiration time
1805 * @param rd_count number of records for this name
1806 * @param rd record data
1807 * @param signature block signature
1810 zone_iteraterate_proc (void *cls,
1811 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1812 struct GNUNET_TIME_Absolute expire,
1814 unsigned int rd_count,
1815 const struct GNUNET_NAMESTORE_RecordData *rd,
1816 const struct GNUNET_CRYPTO_RsaSignature *signature)
1818 struct ZoneIterationProcResult *proc = cls;
1819 struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1820 struct GNUNET_CRYPTO_RsaSignature *new_signature;
1821 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1822 struct GNUNET_CRYPTO_ShortHashCode hash;
1823 struct GNUNET_HashCode long_hash;
1824 struct GNUNET_TIME_Absolute e;
1825 unsigned int rd_count_filtered = 0;
1829 proc->res_iteration_finished = GNUNET_NO;
1830 proc->records_included = 0;
1832 if ((zone_key == NULL) && (name == NULL))
1834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1835 proc->res_iteration_finished = GNUNET_YES;
1839 else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1841 rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1843 for (c = 0; c < rd_count; c++)
1845 include = GNUNET_YES;
1846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1847 c, rd[c].flags, proc->zi->must_have_flags);
1848 /* Checking must have flags */
1849 if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1857 include = GNUNET_NO;
1860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1861 c, rd[c].flags, proc->zi->must_not_have_flags);
1862 if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1865 include = GNUNET_NO;
1870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1872 if (GNUNET_YES == include)
1874 copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1875 rd_count_filtered++;
1879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1881 proc->records_included = rd_count_filtered;
1882 if (0 == rd_count_filtered)
1884 GNUNET_free (rd_filtered);
1887 proc->rd = rd_filtered;
1888 proc->name = GNUNET_strdup(name);
1889 memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1892 proc->has_signature = GNUNET_NO;
1893 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1894 GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1895 proc->zone_hash = hash;
1897 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1899 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1900 e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1902 new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1903 GNUNET_assert (signature != NULL);
1904 proc->signature = (*new_signature);
1905 GNUNET_free (new_signature);
1906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1907 name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1908 proc->has_signature = GNUNET_YES;
1910 else if (rd_count_filtered == rd_count)
1912 proc->expire = expire;
1913 if (NULL != signature)
1915 proc->signature = (*signature);
1916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1917 name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1918 proc->has_signature = GNUNET_YES;
1922 memset (&proc->signature, '\0', sizeof (proc->signature));
1923 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1936 * Find next zone iteration result in database
1937 * @param proc the zone iteration processing to use
1940 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1943 struct GNUNET_CRYPTO_ShortHashCode *zone;
1945 if (GNUNET_YES == proc->zi->has_zone)
1946 zone = &proc->zi->zone;
1952 GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc);
1955 while ((0 == proc->records_included) && (GNUNET_NO == proc->res_iteration_finished));
1960 * Send zone iteration result to client
1961 * @param proc the zone iteration processing result to send
1964 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1966 struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1968 if (GNUNET_YES == proc->res_iteration_finished)
1970 struct ZoneIterationResponseMessage zir_msg;
1971 if (zi->has_zone == GNUNET_YES)
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone));
1974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1977 zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1978 zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1979 zir_msg.gns_header.r_id = htonl(zi->request_id);
1980 zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
1981 zir_msg.name_len = htons (0);
1982 zir_msg.reserved = htons (0);
1983 zir_msg.rd_count = htons (0);
1984 zir_msg.rd_len = htons (0);
1985 memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1986 memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1987 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1990 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1995 GNUNET_assert (proc->records_included > 0);
1997 struct ZoneIterationResponseMessage *zir_msg;
2004 if (zi->has_zone == GNUNET_YES)
2005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
2006 proc->name, GNUNET_short_h2s(&zi->zone));
2007 if (zi->has_zone == GNUNET_NO)
2008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
2010 name_len = strlen (proc->name) +1;
2011 rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
2012 char rd_ser[rd_ser_len];
2013 GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser);
2014 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
2015 zir_msg = GNUNET_malloc(msg_size);
2016 name_tmp = (char *) &zir_msg[1];
2017 rd_tmp = &name_tmp[name_len];
2018 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
2019 zir_msg->gns_header.header.size = htons (msg_size);
2020 zir_msg->gns_header.r_id = htonl(zi->request_id);
2021 zir_msg->expire = GNUNET_TIME_absolute_hton(proc->expire);
2022 zir_msg->reserved = htons (0);
2023 zir_msg->name_len = htons (name_len);
2024 zir_msg->rd_count = htons (proc->records_included);
2025 zir_msg->rd_len = htons (rd_ser_len);
2026 zir_msg->signature = proc->signature;
2027 zir_msg->public_key = proc->zone_key;
2028 memcpy (name_tmp, proc->name, name_len);
2029 memcpy (rd_tmp, rd_ser, rd_ser_len);
2031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2032 "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
2033 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client,
2034 (const struct GNUNET_MessageHeader *) zir_msg,
2036 GNUNET_free (zir_msg);
2041 * Clean up after zone iteration
2042 * @param proc the zone iteration processor
2045 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2049 GNUNET_free_non_null (proc->name);
2050 for (c = 0; c < proc->records_included; c++)
2052 GNUNET_free ((void *) proc->rd[c].data);
2054 GNUNET_free_non_null (proc->rd);
2061 * Perform the next round of the zone iteration.
2063 * @param zi zone iterator to process
2066 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
2068 struct ZoneIterationProcResult proc;
2070 memset (&proc, 0, sizeof (proc));
2072 find_next_zone_iteration_result (&proc);
2073 if (GNUNET_YES == proc.res_iteration_finished)
2075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2076 "Zone iteration done\n");
2078 else if (0 != proc.records_included)
2080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2081 "Zone iteration return %u records\n",
2082 proc.records_included);
2084 send_zone_iteration_result (&proc);
2085 clean_up_zone_iteration_result (&proc);
2090 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2093 * @param client GNUNET_SERVER_Client sending the message
2094 * @param message message of type 'struct ZoneIterationStartMessage'
2097 handle_iteration_start (void *cls,
2098 struct GNUNET_SERVER_Client *client,
2099 const struct GNUNET_MessageHeader *message)
2101 static struct GNUNET_CRYPTO_ShortHashCode zeros;
2102 const struct ZoneIterationStartMessage *zis_msg;
2103 struct GNUNET_NAMESTORE_Client *nc;
2104 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2107 nc = client_lookup (client);
2110 GNUNET_break_op (0);
2111 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2114 zis_msg = (const struct ZoneIterationStartMessage *) message;
2115 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2116 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2119 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2120 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2121 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
2123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2124 zi->zone = zis_msg->zone;
2125 zi->has_zone = GNUNET_NO;
2129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2130 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2131 zi->zone = zis_msg->zone;
2132 zi->has_zone = GNUNET_YES;
2134 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2135 run_zone_iteration_round (zi);
2136 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2141 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2144 * @param client GNUNET_SERVER_Client sending the message
2145 * @param message message of type 'struct ZoneIterationStopMessage'
2148 handle_iteration_stop (void *cls,
2149 struct GNUNET_SERVER_Client *client,
2150 const struct GNUNET_MessageHeader *message)
2152 struct GNUNET_NAMESTORE_Client *nc;
2153 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2154 struct ZoneIterationStopMessage *zis_msg;
2157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2158 "Received `%s' message\n",
2159 "ZONE_ITERATION_STOP");
2160 nc = client_lookup(client);
2164 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2167 zis_msg = (struct ZoneIterationStopMessage *) message;
2168 rid = ntohl (zis_msg->gns_header.r_id);
2169 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2170 if (zi->request_id == rid)
2175 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2178 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2179 if (GNUNET_YES == zi->has_zone)
2180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2181 "Stopped zone iteration for zone `%s'\n",
2182 GNUNET_short_h2s (&zi->zone));
2184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2185 "Stopped zone iteration over all zones\n");
2187 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2192 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2195 * @param client GNUNET_SERVER_Client sending the message
2196 * @param message message of type 'struct ZoneIterationNextMessage'
2199 handle_iteration_next (void *cls,
2200 struct GNUNET_SERVER_Client *client,
2201 const struct GNUNET_MessageHeader *message)
2203 struct GNUNET_NAMESTORE_Client *nc;
2204 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2205 const struct ZoneIterationNextMessage *zis_msg;
2208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2209 nc = client_lookup(client);
2213 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2216 zis_msg = (const struct ZoneIterationNextMessage *) message;
2217 rid = ntohl (zis_msg->gns_header.r_id);
2218 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2219 if (zi->request_id == rid)
2224 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2227 run_zone_iteration_round (zi);
2228 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2233 * Load zone keys from directory by reading all .zkey files in this directory
2235 * @param cls int * 'counter' to store the number of files found
2236 * @param filename directory to scan
2237 * @return GNUNET_OK to continue
2240 zonekey_file_it (void *cls, const char *filename)
2242 unsigned int *counter = cls;
2243 struct GNUNET_HashCode long_hash;
2244 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2245 struct GNUNET_NAMESTORE_CryptoContainer *c;
2247 if ((NULL == filename) ||
2248 (NULL == strstr(filename, ".zkey")))
2250 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
2251 if (NULL == privkey)
2253 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2254 _("Could not parse zone key file `%s'\n"),
2258 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2259 c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2260 c->privkey = privkey;
2261 GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2262 GNUNET_CRYPTO_short_hash(c->pubkey,
2263 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2266 "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2267 GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2268 GNUNET_assert (GNUNET_OK ==
2269 GNUNET_CONTAINER_multihashmap_put (zonekeys, &long_hash, c,
2270 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2277 * Process namestore requests.
2279 * @param cls closure
2280 * @param server the initialized server
2281 * @param cfg configuration to use
2284 run (void *cls, struct GNUNET_SERVER_Handle *server,
2285 const struct GNUNET_CONFIGURATION_Handle *cfg)
2287 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2288 {&handle_start, NULL,
2289 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2290 {&handle_lookup_name, NULL,
2291 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2292 {&handle_record_put, NULL,
2293 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2294 {&handle_record_create, NULL,
2295 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2296 {&handle_record_remove, NULL,
2297 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2298 {&handle_zone_to_name, NULL,
2299 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, 0},
2300 {&handle_iteration_start, NULL,
2301 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
2302 {&handle_iteration_next, NULL,
2303 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
2304 {&handle_iteration_stop, NULL,
2305 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, 0},
2309 unsigned int counter;
2311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2314 /* Load private keys from disk */
2316 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2317 "zonefile_directory",
2318 &zonefile_directory))
2320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2321 _("No directory to load zonefiles specified in configuration\n"));
2322 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2326 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2328 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2330 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2331 _("Creating directory `%s' for zone files failed!\n"),
2332 zonefile_directory);
2333 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2337 "Created directory `%s' for zone files\n",
2338 zonefile_directory);
2341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2342 "Scanning directory `%s' for zone files\n", zonefile_directory);
2343 zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2345 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2347 "Found %u zone files\n",
2350 /* Loading database plugin */
2352 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2356 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2357 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2358 GNUNET_free (database);
2359 if (NULL == GSN_database)
2361 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2362 "Could not load database backend `%s'\n",
2364 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2368 /* Configuring server handles */
2369 GNUNET_SERVER_add_handlers (server, handlers);
2370 snc = GNUNET_SERVER_notification_context_create (server, 16);
2371 GNUNET_SERVER_disconnect_notify (server,
2372 &client_disconnect_notification,
2374 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2380 * The main function for the template service.
2382 * @param argc number of arguments from the command line
2383 * @param argv command line arguments
2384 * @return 0 ok, 1 on error
2387 main (int argc, char *const *argv)
2389 return (GNUNET_OK ==
2390 GNUNET_SERVICE_run (argc, argv, "namestore",
2391 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2394 /* end of gnunet-service-namestore.c */