2 This file is part of GNUnet.
3 (C) 2009 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;
178 * Our notification context.
180 static struct GNUNET_SERVER_NotificationContext *snc;
183 * Head of the Client DLL
185 static struct GNUNET_NAMESTORE_Client *client_head;
188 * Tail of the Client DLL
190 static struct GNUNET_NAMESTORE_Client *client_tail;
193 * Hashmap containing the zone keys this namestore has is authoritative for
195 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
196 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
198 struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
202 * Writes the encrypted private key of a zone in a file
204 * @param filename where to store the zone
205 * @param c the crypto container containing private key of the zone
206 * @return GNUNET_OK on success, GNUNET_SYSERR on fail
209 write_key_to_file (const char *filename, struct GNUNET_NAMESTORE_CryptoContainer *c)
211 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
212 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
213 struct GNUNET_DISK_FileHandle *fd;
215 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
217 struct GNUNET_CRYPTO_ShortHashCode zone;
218 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
219 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
221 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 _("File zone `%s' but corrupt content already exists, failed to write! \n"), 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"), GNUNET_short_h2s (&zone));
246 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);
251 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
253 /* must exist but not be accessible, fail for good! */
254 if (0 != ACCESS (filename, R_OK))
255 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
257 GNUNET_break (0); /* what is going on!? */
258 return GNUNET_SYSERR;
261 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
262 return GNUNET_SYSERR;
265 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
267 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
268 return GNUNET_SYSERR;
270 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
271 GNUNET_assert (enc != NULL);
272 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
274 GNUNET_DISK_file_sync (fd);
275 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
276 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
277 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280 _("Stored zonekey for zone `%s' in file `%s'\n"), GNUNET_short_h2s(&c->zone), c->filename);
286 * Write all zone keys to disk.
287 * Iterates over all entries of the hashmap 'zonekeys'
290 * @param key zone key
291 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
293 * @return GNUNET_OK to continue iteration
296 zone_to_disk_it (void *cls,
297 const struct GNUNET_HashCode *key,
300 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
301 if (c->filename != NULL)
302 write_key_to_file(c->filename, c);
305 GNUNET_asprintf(&c->filename, "%s/%s.zkey", zonefile_directory, GNUNET_short_h2s (&c->zone));
306 write_key_to_file(c->filename, c);
309 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
310 GNUNET_CRYPTO_rsa_key_free (c->privkey);
311 GNUNET_free (c->pubkey);
312 GNUNET_free (c->filename);
320 * Returns the expiration time of the given block of records
321 * The block expiration time is the expiration time of the block with smallest
324 * @param rd_count number of records given in 'rd'
325 * @param rd array of records
326 * @return absolute expiration time
328 static struct GNUNET_TIME_Absolute
329 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
332 struct GNUNET_TIME_Absolute expire = GNUNET_TIME_UNIT_FOREVER_ABS;
333 struct GNUNET_TIME_Absolute at;
334 struct GNUNET_TIME_Relative rt;
337 return GNUNET_TIME_UNIT_ZERO_ABS;
338 for (c = 0; c < rd_count; c++)
340 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
342 rt.rel_value = rd[c].expiration_time;
343 at = GNUNET_TIME_relative_to_absolute (rt);
347 at.abs_value = rd[c].expiration_time;
349 expire = GNUNET_TIME_absolute_min (at, expire);
355 * Task run during shutdown.
361 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
364 struct GNUNET_NAMESTORE_ZoneIteration *no;
365 struct GNUNET_NAMESTORE_ZoneIteration *tmp;
366 struct GNUNET_NAMESTORE_Client *nc;
367 struct GNUNET_NAMESTORE_Client *next;
371 GNUNET_SERVER_notification_context_destroy (snc);
374 GNUNET_CONTAINER_multihashmap_iterate(zonekeys, &zone_to_disk_it, NULL);
375 GNUNET_CONTAINER_multihashmap_destroy(zonekeys);
377 for (nc = client_head; nc != NULL; nc = next)
380 for (no = nc->op_head; no != NULL; no = tmp)
382 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
386 GNUNET_SERVER_client_drop(nc->client);
387 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
391 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
392 GNUNET_free (db_lib_name);
393 GNUNET_free_non_null(zonefile_directory);
396 static struct GNUNET_NAMESTORE_Client *
397 client_lookup (struct GNUNET_SERVER_Client *client)
399 struct GNUNET_NAMESTORE_Client *nc;
401 GNUNET_assert (NULL != client);
403 for (nc = client_head; nc != NULL; nc = nc->next)
405 if (client == nc->client)
413 * Called whenever a client is disconnected.
414 * Frees our resources associated with that client.
417 * @param client identification of the client
420 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
422 struct GNUNET_NAMESTORE_ZoneIteration *no;
423 struct GNUNET_NAMESTORE_Client *nc;
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
429 nc = client_lookup (client);
431 if ((NULL == client) || (NULL == nc))
437 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
442 GNUNET_SERVER_client_drop(nc->client);
443 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
450 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
453 * @param client GNUNET_SERVER_Client sending the message
454 * @param message unused
457 handle_start (void *cls,
458 struct GNUNET_SERVER_Client *client,
459 const struct GNUNET_MessageHeader *message)
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
463 struct GNUNET_NAMESTORE_Client *nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
465 GNUNET_SERVER_notification_context_add (snc, client);
466 GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
467 GNUNET_SERVER_client_keep (client);
468 GNUNET_SERVER_receive_done (client, GNUNET_OK);
475 * Context for name lookups passed from 'handle_lookup_name' to
476 * 'handle_lookup_name_it' as closure
478 struct LookupNameContext
481 * The client to send the response to
483 struct GNUNET_NAMESTORE_Client *nc;
486 * Operation id for the name lookup
491 * Requested specific record type
493 uint32_t record_type;
498 struct GNUNET_CRYPTO_ShortHashCode *zone;
508 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
510 * @param cls a 'struct LookupNameContext *' with information about the request
511 * @param zone_key zone key of the zone
512 * @param expire expiration time
514 * @param rd_count number of records
515 * @param rd array of records
516 * @param signature signature
519 handle_lookup_name_it (void *cls,
520 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
521 struct GNUNET_TIME_Absolute expire,
523 unsigned int rd_count,
524 const struct GNUNET_NAMESTORE_RecordData *rd,
525 const struct GNUNET_CRYPTO_RsaSignature *signature)
528 struct LookupNameContext *lnc = cls;
529 struct LookupNameResponseMessage *lnr_msg;
530 struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
531 struct GNUNET_NAMESTORE_CryptoContainer *cc;
532 struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
533 struct GNUNET_TIME_Absolute e;
534 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
535 struct GNUNET_HashCode long_hash;
542 int copied_elements = 0;
543 int contains_signature = GNUNET_NO;
544 int authoritative = GNUNET_NO;
548 name_len = strlen(name) + 1;
550 /* count records to copy */
553 if (lnc->record_type != 0)
555 /* special record type needed */
556 for (c = 0; c < rd_count; c ++)
557 if (rd[c].record_type == lnc->record_type)
558 copied_elements++; /* found matching record */
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
560 copied_elements, lnc->record_type, lnc->name, GNUNET_short_h2s(lnc->zone));
561 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
563 for (c = 0; c < rd_count; c ++)
565 if (rd[c].record_type == lnc->record_type)
567 /* found matching record */
568 memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
575 copied_elements = rd_count;
576 rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
584 expire = GNUNET_TIME_UNIT_ZERO_ABS;
587 rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
588 char rd_ser[rd_ser_len];
589 GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
592 copied_elements, lnc->name, GNUNET_short_h2s(lnc->zone));
594 if ((copied_elements == rd_count) && (NULL != signature))
595 contains_signature = GNUNET_YES; /* returning all records, so include signature */
597 contains_signature = GNUNET_NO; /* returning not all records, so do not include signature */
600 if ((NULL != zone_key) && (copied_elements == rd_count))
602 GNUNET_CRYPTO_short_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_key_hash);
603 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
604 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
606 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
607 e = get_block_expiration_time(rd_count, rd);
608 signature_new = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd, rd_count);
609 GNUNET_assert (signature_new != NULL);
610 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));
611 authoritative = GNUNET_YES;
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am not authoritative for name `%s' in zone `%s'\n",name, GNUNET_short_h2s(&zone_key_hash));
617 r_size = sizeof (struct LookupNameResponseMessage) +
618 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
623 lnr_msg = GNUNET_malloc (r_size);
624 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
625 lnr_msg->gns_header.header.size = ntohs (r_size);
626 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
627 lnr_msg->rd_count = htons (copied_elements);
628 lnr_msg->rd_len = htons (rd_ser_len);
629 lnr_msg->name_len = htons (name_len);
630 lnr_msg->expire = GNUNET_TIME_absolute_hton(get_block_expiration_time(copied_elements, rd_selected));
632 if (rd_selected != rd)
633 GNUNET_free (rd_selected);
635 if (zone_key != NULL)
636 lnr_msg->public_key = (*zone_key);
638 memset(&lnr_msg->public_key, '\0', sizeof (lnr_msg->public_key));
640 if (GNUNET_YES == authoritative)
641 { /* use new created signature */
642 lnr_msg->contains_sig = htons (GNUNET_YES);
643 GNUNET_assert (signature_new != NULL);
644 lnr_msg->signature = *signature_new;
645 GNUNET_free (signature_new);
647 else if (GNUNET_YES == contains_signature)
649 /* use existing signature */
650 lnr_msg->contains_sig = htons (GNUNET_YES);
651 GNUNET_assert (signature != NULL);
652 lnr_msg->signature = *signature;
656 /* use no signature */
657 memset (&lnr_msg->signature, '\0', sizeof (lnr_msg->signature));
660 name_tmp = (char *) &lnr_msg[1];
661 rd_tmp = &name_tmp[name_len];
663 memcpy (name_tmp, name, name_len);
664 memcpy (rd_tmp, rd_ser, rd_ser_len);
666 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
667 GNUNET_free (lnr_msg);
671 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
674 * @param client GNUNET_SERVER_Client sending the message
675 * @param message message of type 'struct LookupNameMessage'
678 handle_lookup_name (void *cls,
679 struct GNUNET_SERVER_Client *client,
680 const struct GNUNET_MessageHeader *message)
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
683 struct LookupNameContext lnc;
684 struct GNUNET_NAMESTORE_Client *nc;
690 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
693 GNUNET_SERVER_receive_done (client, GNUNET_OK);
697 nc = client_lookup(client);
701 GNUNET_SERVER_receive_done (client, GNUNET_OK);
705 struct LookupNameMessage *ln_msg = (struct LookupNameMessage *) message;
706 rid = ntohl (ln_msg->gns_header.r_id);
707 name_len = ntohl (ln_msg->name_len);
708 type = ntohl (ln_msg->record_type);
710 if ((name_len == 0) || (name_len > 256))
713 GNUNET_SERVER_receive_done (client, GNUNET_OK);
717 name = (char *) &ln_msg[1];
718 if (name[name_len -1] != '\0')
721 GNUNET_SERVER_receive_done (client, GNUNET_OK);
726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_short_h2s(&ln_msg->zone));
728 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));
730 /* do the actual lookup */
731 lnc.request_id = rid;
733 lnc.record_type = type;
735 lnc.zone = &ln_msg->zone;
736 GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
738 GNUNET_SERVER_receive_done (client, GNUNET_OK);
743 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
746 * @param client GNUNET_SERVER_Client sending the message
747 * @param message message of type 'struct RecordPutMessage'
750 handle_record_put (void *cls,
751 struct GNUNET_SERVER_Client *client,
752 const struct GNUNET_MessageHeader *message)
754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
755 struct GNUNET_NAMESTORE_Client *nc;
756 struct RecordPutMessage *rp_msg;
757 struct GNUNET_TIME_Absolute expire;
758 struct GNUNET_CRYPTO_RsaSignature *signature;
759 struct RecordPutResponseMessage rpr_msg;
760 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
769 int res = GNUNET_SYSERR;
771 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
774 GNUNET_SERVER_receive_done (client, GNUNET_OK);
778 nc = client_lookup (client);
782 GNUNET_SERVER_receive_done (client, GNUNET_OK);
786 rp_msg = (struct RecordPutMessage *) message;
787 rid = ntohl (rp_msg->gns_header.r_id);
788 msg_size = ntohs (rp_msg->gns_header.header.size);
789 name_len = ntohs (rp_msg->name_len);
790 rd_count = ntohs (rp_msg->rd_count);
791 rd_ser_len = ntohs(rp_msg->rd_len);
793 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
796 GNUNET_SERVER_receive_done (client, GNUNET_OK);
800 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
803 GNUNET_SERVER_receive_done (client, GNUNET_OK);
807 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
808 if (msg_size != msg_size_exp)
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
812 GNUNET_SERVER_receive_done (client, GNUNET_OK);
815 if ((name_len == 0) || (name_len > 256))
818 GNUNET_SERVER_receive_done (client, GNUNET_OK);
822 name = (char *) &rp_msg[1];
824 if (name[name_len -1] != '\0')
827 GNUNET_SERVER_receive_done (client, GNUNET_OK);
831 expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
832 signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
834 rd_ser = &name[name_len];
835 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
836 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
837 if (res != GNUNET_OK)
843 GNUNET_CRYPTO_short_hash (&rp_msg->public_key, sizeof (rp_msg->public_key), &zone_hash);
844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_short_h2s(&zone_hash));
846 /* Database operation */
847 res = GSN_database->put_records(GSN_database->cls,
854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
855 name, (res == GNUNET_OK) ? "OK" : "FAIL");
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
860 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
861 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
862 rpr_msg.gns_header.r_id = htonl (rid);
863 rpr_msg.op_result = htonl (res);
864 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
866 GNUNET_SERVER_receive_done (client, GNUNET_OK);
871 * CreateRecordContext
873 * Context for record create operations passed from 'handle_record_create' to
874 * 'handle_create_record_it' as closure
876 struct CreateRecordContext
881 struct GNUNET_NAMESTORE_RecordData *rd;
886 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
891 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
894 * Record expiration time
896 struct GNUNET_TIME_Absolute expire;
899 * Name for the record to create
904 * result returned from 'handle_create_record_it'
905 * GNUNET_SYSERR: failed to create the record
906 * GNUNET_NO: we updated an existing record or identical entry existed
907 * GNUNET_YES : we created a new record
914 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
915 * in handle_record_create
917 * @param cls a 'struct CreateRecordContext *' with information about the request
918 * @param pubkey zone key of the zone
919 * @param expire expiration time
921 * @param rd_count number of records
922 * @param rd array of records
923 * @param signature signature
926 handle_create_record_it (void *cls,
927 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
928 struct GNUNET_TIME_Absolute expire,
930 unsigned int rd_count,
931 const struct GNUNET_NAMESTORE_RecordData *rd,
932 const struct GNUNET_CRYPTO_RsaSignature *signature)
934 struct CreateRecordContext *crc = cls;
935 struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
936 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
937 struct GNUNET_TIME_Absolute block_expiration;
939 int exist = GNUNET_SYSERR;
940 int update = GNUNET_NO;
942 int rd_count_new = 0;
944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
945 for (c = 0; c < rd_count; c++)
947 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PKEY) &&
948 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PKEY))
950 /* Update unique PKEY */
955 if ( (crc->rd->record_type == GNUNET_NAMESTORE_TYPE_PSEU) &&
956 (rd[c].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
958 /* Update unique PSEU */
963 if ((crc->rd->record_type == rd[c].record_type) &&
964 (crc->rd->data_size == rd[c].data_size) &&
965 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
968 "Found existing records for `%s' to update expiration date!\n",
971 if ( (crc->rd->expiration_time != rd[c].expiration_time) &&
972 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
973 == (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION) ) )
979 if (exist == GNUNET_SYSERR)
981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
982 "No existing record for name `%s'!\n",
984 rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
985 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
986 rd_count_new = rd_count + 1;
987 rd_new[rd_count] = *(crc->rd);
989 else if (update == GNUNET_NO)
991 /* Exact same record already exists */
992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
993 "Matching record for %s' exists, no change required!\n",
1001 GNUNET_assert (GNUNET_YES == update);
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Updating existing records for `%s'!\n",
1005 rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
1006 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1007 rd_count_new = rd_count;
1008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1009 (0 == (crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1010 ? "Updating absolute expiration from %llu to %llu!\n"
1011 : "Updating relative expiration from %llu to %llu!\n",
1012 rd_new[exist].expiration_time, crc->rd->expiration_time);
1013 rd_new[exist] = *(crc->rd);
1016 block_expiration = GNUNET_TIME_absolute_max(crc->expire, expire);
1017 if (block_expiration.abs_value != expire.abs_value)
1018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1019 "Updated block expiration time\n");
1021 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1023 /* Database operation */
1024 GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
1025 res = GSN_database->put_records(GSN_database->cls,
1026 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
1029 rd_count_new, rd_new,
1031 GNUNET_break (GNUNET_OK == res);
1032 if (res == GNUNET_OK)
1033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully put record for `%s' in database \n", crc->name);
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to put record for `%s' in database \n", crc->name);
1039 GNUNET_free_non_null (rd_new);
1043 /* failed to create the record */
1044 crc->res = GNUNET_SYSERR;
1047 /* database operations OK */
1048 if (GNUNET_YES == update)
1050 /* we updated an existing record */
1051 crc->res = GNUNET_NO;
1055 /* we created a new record */
1056 crc->res = GNUNET_YES;
1060 /* identical entry existed, so we did nothing */
1061 crc->res = GNUNET_NO;
1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
1071 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1074 * @param client GNUNET_SERVER_Client sending the message
1075 * @param message message of type 'struct RecordCreateMessage'
1078 handle_record_create (void *cls,
1079 struct GNUNET_SERVER_Client *client,
1080 const struct GNUNET_MessageHeader *message)
1082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1083 struct GNUNET_NAMESTORE_Client *nc;
1084 struct RecordCreateMessage *rp_msg;
1085 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1086 struct CreateRecordContext crc;
1087 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1088 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1089 struct RecordCreateResponseMessage rcr_msg;
1090 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1091 struct GNUNET_HashCode long_hash;
1094 size_t msg_size_exp;
1103 int res = GNUNET_SYSERR;
1104 crc.res = GNUNET_SYSERR;
1106 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1108 GNUNET_break_op (0);
1109 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1113 nc = client_lookup(client);
1116 GNUNET_break_op (0);
1117 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1121 rp_msg = (struct RecordCreateMessage *) message;
1122 rid = ntohl (rp_msg->gns_header.r_id);
1123 name_len = ntohs (rp_msg->name_len);
1124 msg_size = ntohs (message->size);
1125 rd_count = ntohs (rp_msg->rd_count);
1126 rd_ser_len = ntohs (rp_msg->rd_len);
1127 key_len = ntohs (rp_msg->pkey_len);
1128 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1130 if (msg_size != msg_size_exp)
1132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1133 GNUNET_break_op (0);
1134 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1138 if ((name_len == 0) || (name_len > 256))
1140 GNUNET_break_op (0);
1141 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1145 pkey_tmp = (char *) &rp_msg[1];
1146 name_tmp = &pkey_tmp[key_len];
1147 rd_ser = &name_tmp[name_len];
1149 if (name_tmp[name_len -1] != '\0')
1151 GNUNET_break_op (0);
1152 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1156 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1158 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1159 if ((res != GNUNET_OK) || (rd_count != 1))
1161 GNUNET_break_op (0);
1164 /* Extracting and converting private key */
1165 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1166 GNUNET_assert (pkey != NULL);
1167 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1168 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1169 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1171 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received new private key for zone `%s'\n",GNUNET_short_h2s(&pubkey_hash));
1175 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1176 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1177 cc->pubkey = GNUNET_malloc(sizeof (pub));
1178 memcpy (cc->pubkey, &pub, sizeof(pub));
1179 cc->zone = pubkey_hash;
1180 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1183 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1184 crc.res = GNUNET_SYSERR;
1188 crc.name = name_tmp;
1190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1192 /* Get existing records for name */
1193 res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
1194 if (res != GNUNET_SYSERR)
1196 GNUNET_CRYPTO_rsa_key_free(pkey);
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1202 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1203 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1204 rcr_msg.gns_header.r_id = htonl (rid);
1205 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1206 rcr_msg.op_result = htonl (GNUNET_YES);
1207 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1208 rcr_msg.op_result = htonl (GNUNET_NO);
1210 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1211 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
1213 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1217 * RemoveRecordContext
1219 * Context for record remove operations passed from 'handle_record_remove' to
1220 * 'handle_record_remove_it' as closure
1222 struct RemoveRecordContext
1227 struct GNUNET_NAMESTORE_RecordData *rd;
1230 * Zone's private keys
1232 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1241 * 1 : Could not find record to remove, empty result set
1242 * 2 : Could not find record to remove, record did not exist in result set
1243 * 3 : Could not remove records from database
1244 * 4 : Could not put records into database
1250 handle_record_remove_it (void *cls,
1251 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1252 struct GNUNET_TIME_Absolute expire,
1254 unsigned int rd_count,
1255 const struct GNUNET_NAMESTORE_RecordData *rd,
1256 const struct GNUNET_CRYPTO_RsaSignature *signature)
1258 struct RemoveRecordContext *rrc = cls;
1262 unsigned int rd_count_new;
1264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
1268 /* Could not find record to remove */
1273 /* Find record to remove */
1274 found = GNUNET_SYSERR;
1275 for (c = 0; c < rd_count; c++)
1278 if (rd[c].flags != rrc->rd->flags)
1280 if (rd[c].record_type != rrc->rd->record_type)
1283 if (rd[c].data_size != rrc->rd->data_size)
1286 if (0 != memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size))
1289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1293 if (GNUNET_SYSERR == found)
1295 /* Could not find record to remove */
1300 if (rd_count-1 == 0)
1302 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1303 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1304 res = GSN_database->remove_records (GSN_database->cls,
1307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1308 "No records left for name `%s', removing name\n",
1310 if (GNUNET_OK != res)
1312 /* Could not remove records from database */
1320 rd_count_new = rd_count -1;
1321 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
1323 unsigned int c2 = 0;
1324 for (c = 0; c < rd_count; c++)
1328 GNUNET_assert (c2 < rd_count_new);
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
1336 /* Create dummy signature */
1337 struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1338 memset (&dummy_signature, '\0', sizeof (dummy_signature));
1342 res = GSN_database->put_records(GSN_database->cls,
1346 rd_count_new, rd_new,
1348 if (GNUNET_OK != res)
1350 /* Could not put records into database */
1359 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1362 * @param client GNUNET_SERVER_Client sending the message
1363 * @param message message of type 'struct RecordRemoveMessage'
1366 handle_record_remove (void *cls,
1367 struct GNUNET_SERVER_Client *client,
1368 const struct GNUNET_MessageHeader *message)
1370 struct GNUNET_NAMESTORE_Client *nc;
1371 const struct RecordRemoveMessage *rr_msg;
1372 struct RecordRemoveResponseMessage rrr_msg;
1373 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1374 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1375 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1376 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1377 struct GNUNET_HashCode long_hash;
1378 const char *pkey_tmp;
1379 const char *name_tmp;
1385 size_t msg_size_exp = 0;
1389 int res = GNUNET_SYSERR;
1391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
1392 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1394 GNUNET_break_op (0);
1395 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1399 nc = client_lookup(client);
1402 GNUNET_break_op (0);
1403 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1407 rr_msg = (const struct RecordRemoveMessage *) message;
1408 rid = ntohl (rr_msg->gns_header.r_id);
1409 name_len = ntohs (rr_msg->name_len);
1410 rd_ser_len = ntohs (rr_msg->rd_len);
1411 rd_count = ntohs (rr_msg->rd_count);
1412 key_len = ntohs (rr_msg->pkey_len);
1413 msg_size = ntohs (message->size);
1415 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1417 GNUNET_break_op (0);
1418 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1422 if ((name_len >=256) || (name_len == 0))
1424 GNUNET_break_op (0);
1425 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1429 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1430 if (msg_size != msg_size_exp)
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
1433 GNUNET_break_op (0);
1434 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1438 pkey_tmp = (const char *) &rr_msg[1];
1439 name_tmp = &pkey_tmp[key_len];
1440 rd_ser = &name_tmp[name_len];
1443 if ((name_len == 0) || (name_len > 256))
1445 GNUNET_break_op (0);
1446 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1450 if (name_tmp[name_len -1] != '\0')
1452 GNUNET_break_op (0);
1453 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1457 /* Extracting and converting private key */
1458 pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1459 GNUNET_assert (pkey != NULL);
1460 GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1461 GNUNET_CRYPTO_short_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1462 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
1464 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1466 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1467 "Received new private key for zone `%s'\n",
1468 GNUNET_short_h2s(&pubkey_hash));
1469 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
1470 cc->privkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1471 cc->pubkey = GNUNET_malloc(sizeof (pub));
1472 memcpy (cc->pubkey, &pub, sizeof(pub));
1473 cc->zone = pubkey_hash;
1475 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1479 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1480 res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1481 if ((res != GNUNET_OK) || (rd_count > 1))
1483 GNUNET_break_op (0);
1489 /* remove the whole name and all records */
1490 /* Database operation */
1491 res = GSN_database->remove_records (GSN_database->cls,
1494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing name `%s': %s\n",
1495 name_tmp, (GNUNET_OK == res) ? "OK" : "FAIL");
1497 if (GNUNET_OK != res)
1498 /* Could not remove entry from database */
1505 /* remove a single record */
1506 struct RemoveRecordContext rrc;
1510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_short_h2s(&pubkey_hash));
1512 /* Database operation */
1513 res = GSN_database->iterate_records (GSN_database->cls,
1517 handle_record_remove_it, &rrc);
1519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1520 name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1525 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1526 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1527 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1528 rrr_msg.gns_header.r_id = htonl (rid);
1529 rrr_msg.op_result = htonl (res);
1530 GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1532 GNUNET_CRYPTO_rsa_key_free (pkey);
1534 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1540 * Context for record remove operations passed from 'handle_zone_to_name' to
1541 * 'handle_zone_to_name_it' as closure
1543 struct ZoneToNameCtx
1548 struct GNUNET_NAMESTORE_Client *nc;
1558 * Zone to name iterator
1560 * @param cls struct ZoneToNameCtx *
1561 * @param zone_key the zone key
1562 * @param expire expiration date
1564 * @param rd_count number of records
1565 * @param rd record data
1566 * @param signature signature
1569 handle_zone_to_name_it (void *cls,
1570 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1571 struct GNUNET_TIME_Absolute expire,
1573 unsigned int rd_count,
1574 const struct GNUNET_NAMESTORE_RecordData *rd,
1575 const struct GNUNET_CRYPTO_RsaSignature *signature)
1577 struct ZoneToNameCtx *ztn_ctx = cls;
1578 struct ZoneToNameResponseMessage *ztnr_msg;
1579 int16_t res = GNUNET_SYSERR;
1580 uint16_t name_len = 0;
1581 uint16_t rd_ser_len = 0 ;
1582 int32_t contains_sig = 0;
1583 size_t msg_size = 0;
1585 char *rd_ser = NULL;
1590 if ((zone_key != NULL) && (name != NULL))
1593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found results: name is `%s', has %u records\n", name, rd_count);
1595 name_len = strlen (name) +1;
1599 /* no result found */
1600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no results\n");
1607 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1608 rd_ser = GNUNET_malloc (rd_ser_len);
1609 GNUNET_NAMESTORE_records_serialize(rd_count, rd, rd_ser_len, rd_ser);
1614 if (signature != NULL)
1615 contains_sig = GNUNET_YES;
1617 contains_sig = GNUNET_NO;
1621 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature);
1622 ztnr_msg = GNUNET_malloc (msg_size);
1624 name_tmp = (char *) &ztnr_msg[1];
1625 rd_tmp = &name_tmp[name_len];
1626 sig_tmp = &rd_tmp[rd_ser_len];
1628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_TO_NAME_RESPONSE");
1629 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1630 ztnr_msg->gns_header.header.size = htons (msg_size);
1631 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1632 ztnr_msg->res = htons (res);
1633 ztnr_msg->rd_len = htons (rd_ser_len);
1634 ztnr_msg->rd_count = htons (rd_count);
1635 ztnr_msg->name_len = htons (name_len);
1636 ztnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
1637 if (zone_key != NULL)
1638 ztnr_msg->zone_key = *zone_key;
1640 memset (&ztnr_msg->zone_key, '\0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1642 if ((name_len > 0) && (name != NULL))
1643 memcpy (name_tmp, name, name_len);
1645 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);
1646 if ((rd_ser_len > 0) && (rd_ser != NULL))
1647 memcpy (rd_tmp, rd_ser, rd_ser_len);
1648 if ((GNUNET_YES == contains_sig) && (signature != NULL))
1649 memcpy (sig_tmp, signature, contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature));
1651 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, (const struct GNUNET_MessageHeader *) ztnr_msg, GNUNET_NO);
1652 GNUNET_free (ztnr_msg);
1653 GNUNET_free_non_null (rd_ser);
1657 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1660 * @param client GNUNET_SERVER_Client sending the message
1661 * @param message message of type 'struct ZoneToNameMessage'
1664 handle_zone_to_name (void *cls,
1665 struct GNUNET_SERVER_Client *client,
1666 const struct GNUNET_MessageHeader *message)
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME");
1669 struct GNUNET_NAMESTORE_Client *nc;
1670 struct ZoneToNameMessage *ztn_msg;
1671 struct ZoneToNameCtx ztn_ctx;
1672 size_t msg_size = 0;
1675 if (ntohs (message->size) != sizeof (struct ZoneToNameMessage))
1677 GNUNET_break_op (0);
1678 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1682 nc = client_lookup(client);
1685 GNUNET_break_op (0);
1686 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1690 ztn_msg = (struct ZoneToNameMessage *) message;
1692 if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
1694 GNUNET_break_op (0);
1695 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1699 rid = ntohl (ztn_msg->gns_header.r_id);
1704 struct GNUNET_CRYPTO_ShortHashAsciiEncoded z_tmp;
1705 GNUNET_CRYPTO_short_hash_to_enc(&ztn_msg->zone, &z_tmp);
1706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up name for zone `%s' in zone `%s'\n",
1708 GNUNET_short_h2s (&ztn_msg->value_zone));
1710 GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx);
1712 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1717 * Copy record, data has to be free'd separetely
1719 * @param src source record
1720 * @param dest destination record
1723 copy_record (const struct GNUNET_NAMESTORE_RecordData *src, struct GNUNET_NAMESTORE_RecordData *dest)
1726 memcpy (dest, src, sizeof (struct GNUNET_NAMESTORE_RecordData));
1727 dest->data = GNUNET_malloc (src->data_size);
1728 memcpy ((void *) dest->data, src->data, src->data_size);
1733 * ZoneIterationProcResult
1735 * Context for record remove operations passed from
1736 * 'find_next_zone_iteration_result' to 'zone_iteraterate_proc' as closure
1738 struct ZoneIterationProcResult
1741 * The zone iteration handle
1743 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1746 * Iteration result: iteration done?
1748 int res_iteration_finished;
1751 * Iteration result: number of records included
1753 int records_included;
1756 * Iteration result: is a valid signature included?
1768 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1773 struct GNUNET_NAMESTORE_RecordData *rd;
1778 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1783 struct GNUNET_CRYPTO_RsaSignature signature;
1788 struct GNUNET_TIME_Absolute expire;
1793 * Process results for zone iteration from database
1795 * @param cls struct ZoneIterationProcResult *proc
1796 * @param zone_key the zone key
1797 * @param expire expiration time
1799 * @param rd_count number of records for this name
1800 * @param rd record data
1801 * @param signature block signature
1805 zone_iteraterate_proc (void *cls,
1806 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1807 struct GNUNET_TIME_Absolute expire,
1809 unsigned int rd_count,
1810 const struct GNUNET_NAMESTORE_RecordData *rd,
1811 const struct GNUNET_CRYPTO_RsaSignature *signature)
1813 struct ZoneIterationProcResult *proc = cls;
1814 struct GNUNET_NAMESTORE_RecordData *rd_filtered;
1815 struct GNUNET_CRYPTO_RsaSignature *new_signature;
1816 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1817 struct GNUNET_CRYPTO_ShortHashCode hash;
1818 struct GNUNET_HashCode long_hash;
1819 struct GNUNET_TIME_Absolute e;
1820 unsigned int rd_count_filtered = 0;
1824 proc->res_iteration_finished = GNUNET_NO;
1825 proc->records_included = 0;
1827 if ((zone_key == NULL) && (name == NULL))
1829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1830 proc->res_iteration_finished = GNUNET_YES;
1834 else if ((zone_key != NULL) && (name != NULL)) /* just a safety check */
1836 rd_filtered = GNUNET_malloc (rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for zone iteration: `%s'\n", name);
1838 for (c = 0; c < rd_count; c++)
1840 include = GNUNET_YES;
1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must have 0x%x \n",
1842 c, rd[c].flags, proc->zi->must_have_flags);
1843 /* Checking must have flags */
1844 if ((rd[c].flags & proc->zi->must_have_flags) == proc->zi->must_have_flags)
1847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1852 include = GNUNET_NO;
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: 0x%x must not have 0x%x\n",
1856 c, rd[c].flags, proc->zi->must_not_have_flags);
1857 if ((rd[c].flags & proc->zi->must_not_have_flags) != 0)
1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Not include \n", c);
1860 include = GNUNET_NO;
1865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %i has flags: Include \n", c);
1867 if (GNUNET_YES == include)
1869 copy_record (&rd[c], &rd_filtered[rd_count_filtered]);
1870 rd_count_filtered++;
1874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Included %i of %i records \n", rd_count_filtered, rd_count);
1876 proc->records_included = rd_count_filtered;
1877 if (0 == rd_count_filtered)
1879 GNUNET_free (rd_filtered);
1882 proc->rd = rd_filtered;
1883 proc->name = GNUNET_strdup(name);
1884 memcpy (&proc->zone_key, zone_key, sizeof (proc->zone_key));
1887 proc->has_signature = GNUNET_NO;
1888 GNUNET_CRYPTO_short_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &hash);
1889 GNUNET_CRYPTO_short_hash_double(&hash, &long_hash);
1890 proc->zone_hash = hash;
1892 if (GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
1894 cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash);
1895 e = get_block_expiration_time(rd_count_filtered, rd_filtered);
1897 new_signature = GNUNET_NAMESTORE_create_signature(cc->privkey, e, name, rd_filtered, rd_count_filtered);
1898 GNUNET_assert (signature != NULL);
1899 proc->signature = (*new_signature);
1900 GNUNET_free (new_signature);
1901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1902 name, GNUNET_short_h2s(&hash), rd_count_filtered, e.abs_value);
1903 proc->has_signature = GNUNET_YES;
1905 else if (rd_count_filtered == rd_count)
1907 proc->expire = expire;
1908 if (NULL != signature)
1910 proc->signature = (*signature);
1911 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1912 name, GNUNET_short_h2s(&hash), rd_count_filtered, expire.abs_value);
1913 proc->has_signature = GNUNET_YES;
1917 memset (&proc->signature, '\0', sizeof (proc->signature));
1918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No signature provided for `%s'\n", name);
1932 * Find next zone iteration result in database
1933 * @param proc the zone iteration processing to use
1936 find_next_zone_iteration_result (struct ZoneIterationProcResult *proc)
1939 struct GNUNET_CRYPTO_ShortHashCode *zone;
1941 if (GNUNET_YES == proc->zi->has_zone)
1942 zone = &proc->zi->zone;
1948 GSN_database->iterate_records (GSN_database->cls, zone , NULL, proc->zi->offset, &zone_iteraterate_proc, proc);
1951 while ((proc->records_included == 0) && (GNUNET_NO == proc->res_iteration_finished));
1956 * Send zone iteration result to client
1957 * @param proc the zone iteration processing result to send
1960 send_zone_iteration_result (struct ZoneIterationProcResult *proc)
1962 struct GNUNET_NAMESTORE_ZoneIteration *zi = proc->zi;
1964 if (GNUNET_YES == proc->res_iteration_finished)
1966 struct ZoneIterationResponseMessage zir_msg;
1967 if (zi->has_zone == GNUNET_YES)
1968 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for zone `%s'\n", GNUNET_short_h2s(&zi->zone));
1970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more results for all zones\n");
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "ZONE_ITERATION_RESPONSE");
1973 zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1974 zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1975 zir_msg.gns_header.r_id = htonl(zi->request_id);
1976 zir_msg.expire = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
1977 zir_msg.name_len = htons (0);
1978 zir_msg.reserved = htons (0);
1979 zir_msg.rd_count = htons (0);
1980 zir_msg.rd_len = htons (0);
1981 memset (&zir_msg.public_key, '\0', sizeof (zir_msg.public_key));
1982 memset (&zir_msg.signature, '\0', sizeof (zir_msg.signature));
1983 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing zone iterator\n");
1986 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1992 GNUNET_assert (proc->records_included > 0);
1994 struct ZoneIterationResponseMessage *zir_msg;
1995 if (zi->has_zone == GNUNET_YES)
1996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over zone `%s'\n",
1997 proc->name, GNUNET_short_h2s(&zi->zone));
1998 if (zi->has_zone == GNUNET_NO)
1999 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending name `%s' for iteration over all zones\n",
2007 name_len = strlen (proc->name) +1;
2009 rd_ser_len = GNUNET_NAMESTORE_records_get_size(proc->records_included, proc->rd);
2010 char rd_ser[rd_ser_len];
2011 GNUNET_NAMESTORE_records_serialize(proc->records_included, proc->rd, rd_ser_len, rd_ser);
2012 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
2013 zir_msg = GNUNET_malloc(msg_size);
2015 name_tmp = (char *) &zir_msg[1];
2016 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, "Sending `%s' message with size %u\n", "ZONE_ITERATION_RESPONSE", msg_size);
2032 GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) zir_msg, GNUNET_NO);
2033 GNUNET_free (zir_msg);
2039 * Clean up after zone iteration
2040 * @param proc the zone iteration processor
2043 clean_up_zone_iteration_result (struct ZoneIterationProcResult *proc)
2046 GNUNET_free_non_null (proc->name);
2047 for (c = 0; c < proc->records_included; c++)
2049 GNUNET_free ((void *) proc->rd[c].data);
2051 GNUNET_free_non_null (proc->rd);
2058 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
2061 * @param client GNUNET_SERVER_Client sending the message
2062 * @param message message of type 'struct ZoneIterationStartMessage'
2065 handle_iteration_start (void *cls,
2066 struct GNUNET_SERVER_Client *client,
2067 const struct GNUNET_MessageHeader *message)
2069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
2071 struct ZoneIterationStartMessage *zis_msg = (struct ZoneIterationStartMessage *) message;
2072 struct GNUNET_NAMESTORE_Client *nc;
2073 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2074 struct GNUNET_CRYPTO_ShortHashCode dummy;
2075 struct ZoneIterationProcResult proc;
2077 nc = client_lookup(client);
2080 GNUNET_break_op (0);
2081 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2085 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
2086 zi->request_id = ntohl (zis_msg->gns_header.r_id);
2089 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
2090 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
2092 memset (&dummy, '\0', sizeof (dummy));
2093 if (0 == memcmp (&dummy, &zis_msg->zone, sizeof (dummy)))
2095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
2096 zi->zone = zis_msg->zone;
2097 zi->has_zone = GNUNET_NO;
2101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
2102 zi->zone = zis_msg->zone;
2103 zi->has_zone = GNUNET_YES;
2106 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
2109 find_next_zone_iteration_result (&proc);
2110 if (GNUNET_YES == proc.res_iteration_finished)
2112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
2114 else if (proc.records_included != 0)
2116 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
2118 send_zone_iteration_result (&proc);
2119 clean_up_zone_iteration_result (&proc);
2121 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2126 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2129 * @param client GNUNET_SERVER_Client sending the message
2130 * @param message message of type 'struct ZoneIterationStopMessage'
2133 handle_iteration_stop (void *cls,
2134 struct GNUNET_SERVER_Client *client,
2135 const struct GNUNET_MessageHeader *message)
2137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
2139 struct GNUNET_NAMESTORE_Client *nc;
2140 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2141 struct ZoneIterationStopMessage *zis_msg;
2144 nc = client_lookup(client);
2147 GNUNET_break_op (0);
2148 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2152 zis_msg = (struct ZoneIterationStopMessage *) message;
2153 rid = ntohl (zis_msg->gns_header.r_id);
2154 for (zi = nc->op_head; zi != NULL; zi = zi->next)
2156 if (zi->request_id == rid)
2161 GNUNET_break_op (0);
2162 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2166 GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
2167 if (GNUNET_YES == zi->has_zone)
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_short_h2s (&zi->zone));
2170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration all zones\n");
2173 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2178 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2181 * @param client GNUNET_SERVER_Client sending the message
2182 * @param message message of type 'struct ZoneIterationNextMessage'
2185 handle_iteration_next (void *cls,
2186 struct GNUNET_SERVER_Client *client,
2187 const struct GNUNET_MessageHeader *message)
2189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2191 struct GNUNET_NAMESTORE_Client *nc;
2192 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2193 struct ZoneIterationNextMessage *zis_msg;
2196 nc = client_lookup(client);
2199 GNUNET_break_op (0);
2200 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2204 zis_msg = (struct ZoneIterationNextMessage *) message;
2205 rid = ntohl (zis_msg->gns_header.r_id);
2206 for (zi = nc->op_head; zi != NULL; zi = zi->next)
2208 if (zi->request_id == rid)
2213 GNUNET_break_op (0);
2214 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2218 struct ZoneIterationProcResult proc;
2221 find_next_zone_iteration_result (&proc);
2222 if (GNUNET_YES == proc.res_iteration_finished)
2224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration done\n");
2226 else if (proc.records_included != 0)
2228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration return %u records\n", proc.records_included);
2230 send_zone_iteration_result (&proc);
2231 clean_up_zone_iteration_result (&proc);
2233 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2238 * Load zone keys from directory by reading all .zkey files in this directory
2240 * @param cls int * 'counter' to store the number of files found
2241 * @param filename directory to scan
2242 * @return GNUNET_OK to continue
2245 zonekey_file_it (void *cls, const char *filename)
2247 struct GNUNET_HashCode long_hash;
2249 if ((filename != NULL) && (NULL != strstr(filename, ".zkey")))
2251 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2252 struct GNUNET_NAMESTORE_CryptoContainer *c;
2253 privkey = GNUNET_CRYPTO_rsa_key_create_from_file(filename);
2254 if (privkey == NULL)
2257 c = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
2258 c->pubkey = GNUNET_malloc(sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2259 c->privkey = privkey;
2260 GNUNET_CRYPTO_rsa_key_get_public(privkey, c->pubkey);
2261 GNUNET_CRYPTO_short_hash(c->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &c->zone);
2263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found zonefile for zone `%s'\n", GNUNET_short_h2s (&c->zone));
2264 GNUNET_CRYPTO_short_hash_double (&c->zone, &long_hash);
2265 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2273 * Process namestore requests.
2275 * @param cls closure
2276 * @param server the initialized server
2277 * @param cfg configuration to use
2280 run (void *cls, struct GNUNET_SERVER_Handle *server,
2281 const struct GNUNET_CONFIGURATION_Handle *cfg)
2285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
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},
2311 /* Load private keys from disk */
2313 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore", "zonefile_directory",
2314 &zonefile_directory))
2316 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No directory to load zonefiles specified in configuration\n"));
2317 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2321 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2323 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Creating directory `%s' for zone files failed!\n"), zonefile_directory);
2326 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created directory `%s' for zone files\n", zonefile_directory);
2332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scanning directory `%s' for zone files\n", zonefile_directory);
2333 zonekeys = GNUNET_CONTAINER_multihashmap_create (10);
2334 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u zone files\n", counter);
2337 /* Loading database plugin */
2339 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2343 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2344 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2345 GNUNET_free (database);
2346 if (GSN_database == NULL)
2348 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
2350 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2354 /* Configuring server handles */
2355 GNUNET_SERVER_add_handlers (server, handlers);
2356 snc = GNUNET_SERVER_notification_context_create (server, 16);
2357 GNUNET_SERVER_disconnect_notify (server,
2358 &client_disconnect_notification,
2361 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2368 * The main function for the template service.
2370 * @param argc number of arguments from the command line
2371 * @param argv command line arguments
2372 * @return 0 ok, 1 on error
2375 main (int argc, char *const *argv)
2377 return (GNUNET_OK ==
2378 GNUNET_SERVICE_run (argc, argv, "namestore",
2379 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2382 /* end of gnunet-service-namestore.c */