2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2018 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file namestore/gnunet-service-namestore.c
23 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs
25 * @author Christian Grothoff
28 * - run testcases, make sure everything works!
31 #include "gnunet_util_lib.h"
32 #include "gnunet_dnsparser_lib.h"
33 #include "gnunet_gns_service.h"
34 #include "gnunet_namecache_service.h"
35 #include "gnunet_namestore_service.h"
36 #include "gnunet_namestore_plugin.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_signatures.h"
39 #include "namestore.h"
41 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
44 * If a monitor takes more than 1 minute to process an event, print a warning.
46 #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
52 struct NamestoreClient;
56 * A namestore iteration operation.
61 * Next element in the DLL
63 struct ZoneIteration *next;
66 * Previous element in the DLL
68 struct ZoneIteration *prev;
71 * Namestore client which intiated this zone iteration
73 struct NamestoreClient *nc;
76 * The nick to add to the records
78 struct GNUNET_GNSRECORD_Data *nick;
81 * Key of the zone we are iterating over.
83 struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
86 * Last sequence number in the zone iteration used to address next
87 * result of the zone iteration in the store
90 * Updated in #zone_iterate_proc()
95 * The operation id fot the zone iteration in the response for the client
100 * Offset of the zone iteration used to address next result of the zone
101 * iteration in the store
103 * Initialy set to 0 in #handle_iteration_start
104 * Incremented with by every call to #handle_iteration_next
114 struct NamestoreClient
120 struct GNUNET_SERVICE_Client *client;
123 * Message queue for transmission to @e client
125 struct GNUNET_MQ_Handle *mq;
129 * Zone iteration operations in progress initiated by this client
131 struct ZoneIteration *op_head;
135 * Zone iteration operations in progress initiated by this client
137 struct ZoneIteration *op_tail;
142 * A namestore monitor.
147 * Next element in the DLL
149 struct ZoneMonitor *next;
152 * Previous element in the DLL
154 struct ZoneMonitor *prev;
157 * Namestore client which intiated this zone monitor
159 struct NamestoreClient *nc;
162 * Private key of the zone.
164 struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
167 * Task active during initial iteration.
169 struct GNUNET_SCHEDULER_Task *task;
172 * Task to warn about slow monitors.
174 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
177 * Since when are we blocked on this monitor?
179 struct GNUNET_TIME_Absolute sa_waiting_start;
182 * Last sequence number in the zone iteration used to address next
183 * result of the zone iteration in the store
186 * Updated in #monitor_iterate_cb()
191 * Current limit of how many more messages we are allowed
192 * to queue to this monitor.
197 * How many more requests may we receive from the iterator
198 * before it is at the limit we gave it? Will be below or
199 * equal to @e limit. The effective limit for monitor
200 * events is thus @e iteration_cnt - @e limit!
202 uint64_t iteration_cnt;
205 * Are we (still) in the initial iteration pass?
207 int in_first_iteration;
210 * Is there a store activity waiting for this monitor? We only raise the
211 * flag when it happens and search the DLL for the store activity when we
212 * had a limit increase. If we cannot find any waiting store activity at
213 * that time, we clear the flag again.
221 * Pending operation on the namecache.
223 struct CacheOperation
229 struct CacheOperation *prev;
234 struct CacheOperation *next;
237 * Handle to namecache queue.
239 struct GNUNET_NAMECACHE_QueueEntry *qe;
242 * Client to notify about the result.
244 struct NamestoreClient *nc;
247 * Client's request ID.
254 * Information for an ongoing #handle_record_store() operation.
255 * Needed as we may wait for monitors to be ready for the notification.
262 struct StoreActivity *next;
267 struct StoreActivity *prev;
270 * Which client triggered the store activity?
272 struct NamestoreClient *nc;
275 * Copy of the original store message (as data fields in @e rd will
278 const struct RecordStoreMessage *rsm;
281 * Array of record data to store (without NICK unless this is about
282 * #GNUNET_GNS_EMPTY_LABEL_AT). Length is in @e rd_count.
284 struct GNUNET_GNSRECORD_Data *rd;
287 * Next zone monitor that still needs to be notified about this PUT.
289 struct ZoneMonitor *zm_pos;
292 * Label nicely canonicalized (lower case).
297 * How many records do we try to store?
299 unsigned int rd_count;
305 * Public key of all zeros.
307 static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
310 * Configuration handle.
312 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
315 * Handle to the statistics service
317 static struct GNUNET_STATISTICS_Handle *statistics;
322 static struct GNUNET_NAMECACHE_Handle *namecache;
327 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
330 * Name of the database plugin
332 static char *db_lib_name;
337 static struct CacheOperation *cop_head;
342 static struct CacheOperation *cop_tail;
345 * First active zone monitor.
347 static struct ZoneMonitor *monitor_head;
350 * Last active zone monitor.
352 static struct ZoneMonitor *monitor_tail;
355 * Head of DLL of monitor-blocked store activities.
357 static struct StoreActivity *sa_head;
360 * Tail of DLL of monitor-blocked store activities.
362 static struct StoreActivity *sa_tail;
365 * Notification context shared by all monitors.
367 static struct GNUNET_NotificationContext *monitor_nc;
370 * Optimize block insertion by caching map of private keys to
371 * public keys in memory?
373 static int cache_keys;
376 * Use the namecache? Doing so creates additional cryptographic
377 * operations whenever we touch a record.
379 static int disable_namecache;
383 * Task run during shutdown.
388 cleanup_task (void *cls)
390 struct CacheOperation *cop;
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394 "Stopping namestore service\n");
395 while (NULL != (cop = cop_head))
397 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
398 "Aborting incomplete namecache operation\n");
399 GNUNET_NAMECACHE_cancel (cop->qe);
400 GNUNET_CONTAINER_DLL_remove (cop_head,
405 if (NULL != namecache)
407 GNUNET_NAMECACHE_disconnect (namecache);
410 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
412 GNUNET_free (db_lib_name);
414 if (NULL != monitor_nc)
416 GNUNET_notification_context_destroy (monitor_nc);
419 if (NULL != statistics)
421 GNUNET_STATISTICS_destroy (statistics,
429 * Release memory used by @a sa.
431 * @param sa activity to free
434 free_store_activity (struct StoreActivity *sa)
436 GNUNET_CONTAINER_DLL_remove (sa_head,
439 GNUNET_array_grow (sa->rd,
442 GNUNET_free (sa->conv_name);
448 * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
449 * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
450 * record, which (if found) is then copied to @a cls for future use.
452 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
453 * @param seq sequence number of the record
454 * @param private_key the private key of the zone (unused)
455 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
456 * @param rd_count number of records in @a rd
457 * @param rd records stored under @a label in the zone
460 lookup_nick_it (void *cls,
462 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
464 unsigned int rd_count,
465 const struct GNUNET_GNSRECORD_Data *rd)
467 struct GNUNET_GNSRECORD_Data **res = cls;
471 if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
476 for (unsigned int c = 0; c < rd_count; c++)
478 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
480 (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data));
481 (*res)->data = &(*res)[1];
482 GNUNET_memcpy ((void *) (*res)->data,
485 (*res)->data_size = rd[c].data_size;
486 (*res)->expiration_time = rd[c].expiration_time;
487 (*res)->flags = rd[c].flags;
488 (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
497 * Return the NICK record for the zone (if it exists).
499 * @param zone private key for the zone to look for nick
500 * @return NULL if no NICK record was found
502 static struct GNUNET_GNSRECORD_Data *
503 get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone)
505 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
506 struct GNUNET_GNSRECORD_Data *nick;
510 res = GSN_database->lookup_records (GSN_database->cls,
512 GNUNET_GNS_EMPTY_LABEL_AT,
515 if ( (GNUNET_OK != res) ||
518 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
520 "No nick name set for zone `%s'\n",
521 GNUNET_GNSRECORD_z2s (&pub));
529 * Merge the nick record @a nick_rd with the rest of the
530 * record set given in @a rd2. Store the result in @a rdc_res
531 * and @a rd_res. The @a nick_rd's expiration time is set to
532 * the maximum expiration time of all of the records in @a rd2.
534 * @param nick_rd the nick record to integrate
535 * @param rd2_length length of the @a rd2 array
536 * @param rd2 array of records
537 * @param rdc_res[out] length of the resulting @a rd_res array
538 * @param rd_res[out] set to an array of records,
539 * including @a nick_rd and @a rd2;
540 * all of the variable-size 'data' fields in @a rd2 are
541 * allocated in the same chunk of memory!
544 merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
545 unsigned int rd2_length,
546 const struct GNUNET_GNSRECORD_Data *rd2,
547 unsigned int *rdc_res,
548 struct GNUNET_GNSRECORD_Data **rd_res)
550 uint64_t latest_expiration;
555 (*rdc_res) = 1 + rd2_length;
556 if (0 == 1 + rd2_length)
562 req = sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
563 for (unsigned int c=0; c< rd2_length; c++)
564 req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size;
565 (*rd_res) = GNUNET_malloc (req);
566 data = (char *) &(*rd_res)[1 + rd2_length];
568 latest_expiration = 0;
569 for (unsigned int c=0; c< rd2_length; c++)
571 if (0 != (rd2[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
573 if ((GNUNET_TIME_absolute_get().abs_value_us + rd2[c].expiration_time) >
575 latest_expiration = rd2[c].expiration_time;
577 else if (rd2[c].expiration_time > latest_expiration)
578 latest_expiration = rd2[c].expiration_time;
579 (*rd_res)[c] = rd2[c];
580 (*rd_res)[c].data = (void *) &data[data_offset];
581 GNUNET_memcpy (&data[data_offset],
584 data_offset += (*rd_res)[c].data_size;
587 (*rd_res)[rd2_length] = *nick_rd;
588 (*rd_res)[rd2_length].expiration_time = latest_expiration;
589 (*rd_res)[rd2_length].data = (void *) &data[data_offset];
590 GNUNET_memcpy ((void *) (*rd_res)[rd2_length].data,
593 data_offset += (*rd_res)[rd2_length].data_size;
594 GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
599 * Generate a `struct LookupNameResponseMessage` and send it to the
600 * given client using the given notification context.
602 * @param nc client to unicast to
603 * @param request_id request ID to use
604 * @param zone_key zone key of the zone
606 * @param rd_count number of records in @a rd
607 * @param rd array of records
610 send_lookup_response (struct NamestoreClient *nc,
612 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
614 unsigned int rd_count,
615 const struct GNUNET_GNSRECORD_Data *rd)
617 struct GNUNET_MQ_Envelope *env;
618 struct RecordResultMessage *zir_msg;
619 struct GNUNET_GNSRECORD_Data *nick;
620 struct GNUNET_GNSRECORD_Data *res;
621 unsigned int res_count;
627 nick = get_nick_record (zone_key);
628 if ( (NULL != nick) &&
630 GNUNET_GNS_EMPTY_LABEL_AT)))
632 nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
633 merge_with_nick_records (nick,
642 res_count = rd_count;
643 res = (struct GNUNET_GNSRECORD_Data *) rd;
646 name_len = strlen (name) + 1;
647 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count,
649 env = GNUNET_MQ_msg_extra (zir_msg,
650 name_len + rd_ser_len,
651 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
652 zir_msg->gns_header.r_id = htonl (request_id);
653 zir_msg->name_len = htons (name_len);
654 zir_msg->rd_count = htons (res_count);
655 zir_msg->rd_len = htons (rd_ser_len);
656 zir_msg->private_key = *zone_key;
657 name_tmp = (char *) &zir_msg[1];
658 GNUNET_memcpy (name_tmp,
661 rd_ser = &name_tmp[name_len];
662 GNUNET_GNSRECORD_records_serialize (res_count,
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Sending RECORD_RESULT message with %u records\n",
669 GNUNET_STATISTICS_update (statistics,
670 "Record sets sent to clients",
673 GNUNET_MQ_send (nc->mq,
681 * Send response to the store request to the client.
683 * @param client client to talk to
684 * @param res status of the operation
685 * @param rid client's request ID
688 send_store_response (struct NamestoreClient *nc,
692 struct GNUNET_MQ_Envelope *env;
693 struct RecordStoreResponseMessage *rcr_msg;
695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
696 "Sending RECORD_STORE_RESPONSE message\n");
697 GNUNET_STATISTICS_update (statistics,
698 "Store requests completed",
701 env = GNUNET_MQ_msg (rcr_msg,
702 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
703 rcr_msg->gns_header.r_id = htonl (rid);
704 rcr_msg->op_result = htonl (res);
705 GNUNET_MQ_send (nc->mq,
711 * Cache operation complete, clean up.
713 * @param cls the `struct CacheOperation`
714 * @param success success
715 * @param emsg error messages
718 finish_cache_operation (void *cls,
722 struct CacheOperation *cop = cls;
725 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
726 _("Failed to replicate block in namecache: %s\n"),
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "CACHE operation completed\n");
731 GNUNET_CONTAINER_DLL_remove (cop_head,
735 send_store_response (cop->nc,
743 * We just touched the plaintext information about a name in our zone;
744 * refresh the corresponding (encrypted) block in the namecache.
746 * @param nc client responsible for the request, can be NULL
747 * @param rid request ID of the client
748 * @param zone_key private key of the zone
749 * @param name label for the records
750 * @param rd_count number of records
751 * @param rd records stored under the given @a name
754 refresh_block (struct NamestoreClient *nc,
756 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
758 unsigned int rd_count,
759 const struct GNUNET_GNSRECORD_Data *rd)
761 struct GNUNET_GNSRECORD_Block *block;
762 struct CacheOperation *cop;
763 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
764 struct GNUNET_GNSRECORD_Data *nick;
765 struct GNUNET_GNSRECORD_Data *res;
766 unsigned int res_count;
767 struct GNUNET_TIME_Absolute exp_time;
769 nick = get_nick_record (zone_key);
770 res_count = rd_count;
771 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
774 nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
775 merge_with_nick_records (nick,
783 send_store_response (nc,
786 return; /* no data, no need to update cache */
788 if (GNUNET_YES == disable_namecache)
790 GNUNET_STATISTICS_update (statistics,
791 "Namecache updates skipped (NC disabled)",
794 send_store_response (nc,
799 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count,
802 block = GNUNET_GNSRECORD_block_create2 (zone_key,
808 block = GNUNET_GNSRECORD_block_create (zone_key,
813 GNUNET_assert (NULL != block);
814 GNUNET_CRYPTO_ecdsa_key_get_public (zone_key,
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
820 GNUNET_STRINGS_absolute_time_to_string (exp_time),
821 GNUNET_GNSRECORD_z2s (&pkey));
822 GNUNET_STATISTICS_update (statistics,
823 "Namecache updates pushed",
826 cop = GNUNET_new (struct CacheOperation);
829 GNUNET_CONTAINER_DLL_insert (cop_head,
832 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
834 &finish_cache_operation,
841 * Print a warning that one of our monitors is no longer reacting.
843 * @param cls a `struct ZoneMonitor` to warn about
846 warn_monitor_slow (void *cls)
848 struct ZoneMonitor *zm = cls;
850 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
851 "No response from monitor since %s\n",
852 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
853 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
860 * Continue processing the @a sa.
862 * @param sa store activity to process
865 continue_store_activity (struct StoreActivity *sa)
867 const struct RecordStoreMessage *rp_msg = sa->rsm;
869 for (struct ZoneMonitor *zm = sa->zm_pos;
873 if ( (0 != memcmp (&rp_msg->private_key,
875 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
876 (0 != memcmp (&zm->zone,
878 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
879 sa->zm_pos = zm->next; /* not interesting to this monitor */
880 if (zm->limit == zm->iteration_cnt)
882 zm->sa_waiting = GNUNET_YES;
883 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
884 if (NULL != zm->sa_wait_warning)
885 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
886 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
889 return; /* blocked on zone monitor */
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "Notifying monitor about changes under label `%s'\n",
895 send_lookup_response (zm->nc,
897 &rp_msg->private_key,
901 sa->zm_pos = zm->next;
903 /* great, done with the monitors, unpack (again) for refresh_block operation */
908 const char *name_tmp;
910 unsigned int rd_count;
912 rid = ntohl (rp_msg->gns_header.r_id);
913 name_len = ntohs (rp_msg->name_len);
914 rd_count = ntohs (rp_msg->rd_count);
915 rd_ser_len = ntohs (rp_msg->rd_len);
916 name_tmp = (const char *) &rp_msg[1];
917 rd_ser = &name_tmp[name_len];
919 struct GNUNET_GNSRECORD_Data rd[rd_count];
921 /* We did this before, must succeed again */
922 GNUNET_assert (GNUNET_OK ==
923 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
927 refresh_block (sa->nc,
929 &rp_msg->private_key,
935 GNUNET_SERVICE_client_continue (sa->nc->client);
936 free_store_activity (sa);
941 * Called whenever a client is disconnected.
942 * Frees our resources associated with that client.
945 * @param client identification of the client
946 * @param app_ctx the `struct NamestoreClient` of @a client
949 client_disconnect_cb (void *cls,
950 struct GNUNET_SERVICE_Client *client,
953 struct NamestoreClient *nc = app_ctx;
954 struct ZoneIteration *no;
955 struct CacheOperation *cop;
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959 "Client %p disconnected\n",
961 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
963 struct StoreActivity *san;
967 GNUNET_CONTAINER_DLL_remove (monitor_head,
970 if (NULL != zm->task)
972 GNUNET_SCHEDULER_cancel (zm->task);
975 if (NULL != zm->sa_wait_warning)
977 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
978 zm->sa_wait_warning = NULL;
980 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
983 if (zm == sa->zm_pos)
985 sa->zm_pos = zm->next;
986 /* this may free sa */
987 continue_store_activity (sa);
993 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
997 /* this may free sa */
998 free_store_activity (sa);
999 break; /* there can only be one per nc */
1002 while (NULL != (no = nc->op_head))
1004 GNUNET_CONTAINER_DLL_remove (nc->op_head,
1009 for (cop = cop_head; NULL != cop; cop = cop->next)
1017 * Add a client to our list of active clients.
1020 * @param client client to add
1021 * @param mq message queue for @a client
1022 * @return internal namestore client structure for this client
1025 client_connect_cb (void *cls,
1026 struct GNUNET_SERVICE_Client *client,
1027 struct GNUNET_MQ_Handle *mq)
1029 struct NamestoreClient *nc;
1032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1033 "Client %p connected\n",
1035 nc = GNUNET_new (struct NamestoreClient);
1036 nc->client = client;
1043 * Closure for #lookup_it().
1045 struct RecordLookupContext
1061 struct GNUNET_GNSRECORD_Data *nick;
1071 unsigned int res_rd_count;
1082 * @param seq sequence number of the record
1085 lookup_it (void *cls,
1087 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
1089 unsigned int rd_count,
1090 const struct GNUNET_GNSRECORD_Data *rd)
1092 struct RecordLookupContext *rlc = cls;
1093 struct GNUNET_GNSRECORD_Data *rd_res;
1094 unsigned int rdc_res;
1098 if (0 == strcmp (label,
1101 rlc->found = GNUNET_YES;
1104 if ( (NULL != rlc->nick) &&
1105 (0 != strcmp (label,
1106 GNUNET_GNS_EMPTY_LABEL_AT)) )
1111 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
1112 merge_with_nick_records (rlc->nick,
1117 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
1119 rlc->res_rd_count = rdc_res;
1120 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1121 GNUNET_GNSRECORD_records_serialize (rdc_res,
1126 GNUNET_free (rd_res);
1127 GNUNET_free (rlc->nick);
1132 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1134 rlc->res_rd_count = rd_count;
1135 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1136 GNUNET_GNSRECORD_records_serialize (rd_count,
1144 rlc->rd_ser_len = 0;
1145 rlc->res_rd_count = 0;
1153 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1155 * @param cls client sending the message
1156 * @param ll_msg message of type `struct LabelLookupMessage`
1157 * @return #GNUNET_OK if @a ll_msg is well-formed
1160 check_record_lookup (void *cls,
1161 const struct LabelLookupMessage *ll_msg)
1165 const char *name_tmp;
1168 name_len = ntohl (ll_msg->label_len);
1169 src_size = ntohs (ll_msg->gns_header.header.size);
1170 if (name_len != src_size - sizeof (struct LabelLookupMessage))
1173 return GNUNET_SYSERR;
1176 name_tmp = (const char *) &ll_msg[1];
1177 if ('\0' != name_tmp[name_len -1])
1180 return GNUNET_SYSERR;
1187 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1189 * @param cls client sending the message
1190 * @param ll_msg message of type `struct LabelLookupMessage`
1193 handle_record_lookup (void *cls,
1194 const struct LabelLookupMessage *ll_msg)
1196 struct NamestoreClient *nc = cls;
1197 struct GNUNET_MQ_Envelope *env;
1198 struct LabelLookupResponseMessage *llr_msg;
1199 struct RecordLookupContext rlc;
1200 const char *name_tmp;
1206 name_len = ntohl (ll_msg->label_len);
1207 name_tmp = (const char *) &ll_msg[1];
1208 GNUNET_SERVICE_client_continue (nc->client);
1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1210 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1213 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1214 if (NULL == conv_name)
1216 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1217 "Error converting name `%s'\n",
1219 GNUNET_SERVICE_client_drop (nc->client);
1222 rlc.label = conv_name;
1223 rlc.found = GNUNET_NO;
1224 rlc.res_rd_count = 0;
1227 rlc.nick = get_nick_record (&ll_msg->zone);
1228 res = GSN_database->lookup_records (GSN_database->cls,
1233 GNUNET_free (conv_name);
1234 env = GNUNET_MQ_msg_extra (llr_msg,
1235 name_len + rlc.rd_ser_len,
1236 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1237 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1238 llr_msg->private_key = ll_msg->zone;
1239 llr_msg->name_len = htons (name_len);
1240 llr_msg->rd_count = htons (rlc.res_rd_count);
1241 llr_msg->rd_len = htons (rlc.rd_ser_len);
1242 res_name = (char *) &llr_msg[1];
1243 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1244 llr_msg->found = ntohs (GNUNET_YES);
1246 llr_msg->found = ntohs (GNUNET_NO);
1247 GNUNET_memcpy (&llr_msg[1],
1250 GNUNET_memcpy (&res_name[name_len],
1253 GNUNET_MQ_send (nc->mq,
1255 GNUNET_free_non_null (rlc.res_rd);
1260 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1262 * @param cls client sending the message
1263 * @param rp_msg message of type `struct RecordStoreMessage`
1264 * @return #GNUNET_OK if @a rp_msg is well-formed
1267 check_record_store (void *cls,
1268 const struct RecordStoreMessage *rp_msg)
1272 size_t msg_size_exp;
1274 const char *name_tmp;
1277 name_len = ntohs (rp_msg->name_len);
1278 msg_size = ntohs (rp_msg->gns_header.header.size);
1279 rd_ser_len = ntohs (rp_msg->rd_len);
1280 msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
1281 if (msg_size != msg_size_exp)
1284 return GNUNET_SYSERR;
1286 if ( (0 == name_len) ||
1287 (name_len > MAX_NAME_LEN) )
1290 return GNUNET_SYSERR;
1292 name_tmp = (const char *) &rp_msg[1];
1293 if ('\0' != name_tmp[name_len -1])
1296 return GNUNET_SYSERR;
1303 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1305 * @param cls client sending the message
1306 * @param rp_msg message of type `struct RecordStoreMessage`
1309 handle_record_store (void *cls,
1310 const struct RecordStoreMessage *rp_msg)
1312 struct NamestoreClient *nc = cls;
1316 const char *name_tmp;
1319 unsigned int rd_count;
1321 struct StoreActivity *sa;
1323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1324 "Received NAMESTORE_RECORD_STORE message\n");
1325 rid = ntohl (rp_msg->gns_header.r_id);
1326 name_len = ntohs (rp_msg->name_len);
1327 rd_count = ntohs (rp_msg->rd_count);
1328 rd_ser_len = ntohs (rp_msg->rd_len);
1329 GNUNET_break (0 == ntohs (rp_msg->reserved));
1330 name_tmp = (const char *) &rp_msg[1];
1331 rd_ser = &name_tmp[name_len];
1333 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1334 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1335 unsigned int rd_clean_off;
1338 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
1344 GNUNET_SERVICE_client_drop (nc->client);
1348 /* Extracting and converting private key */
1349 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1350 if (NULL == conv_name)
1352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1353 "Error converting name `%s'\n",
1355 GNUNET_SERVICE_client_drop (nc->client);
1358 GNUNET_STATISTICS_update (statistics,
1359 "Well-formed store requests received",
1362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1363 "Creating %u records for name `%s'\n",
1364 (unsigned int) rd_count,
1366 if ( (0 == rd_count) &&
1368 GSN_database->lookup_records (GSN_database->cls,
1369 &rp_msg->private_key,
1374 /* This name does not exist, so cannot be removed */
1375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1376 "Name `%s' does not exist, no deletion required\n",
1382 /* remove "NICK" records, unless this is for the
1383 #GNUNET_GNS_EMPTY_LABEL_AT label */
1385 for (unsigned int i=0;i<rd_count;i++)
1387 rd_clean[rd_clean_off] = rd[i];
1388 if ( (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT,
1390 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type) )
1393 res = GSN_database->store_records (GSN_database->cls,
1394 &rp_msg->private_key,
1400 if (GNUNET_OK != res)
1402 /* store not successful, not need to tell monitors */
1403 send_store_response (nc,
1406 GNUNET_SERVICE_client_continue (nc->client);
1407 GNUNET_free (conv_name);
1411 sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1412 ntohs (rp_msg->gns_header.header.size));
1413 GNUNET_CONTAINER_DLL_insert (sa_head,
1417 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1418 GNUNET_memcpy (&sa[1],
1420 ntohs (rp_msg->gns_header.header.size));
1421 sa->zm_pos = monitor_head;
1422 sa->conv_name = conv_name;
1423 GNUNET_array_grow (sa->rd,
1426 GNUNET_memcpy (sa->rd,
1428 sizeof (struct GNUNET_GNSRECORD_Data) * rd_clean_off);
1429 continue_store_activity (sa);
1435 * Context for record remove operations passed from #handle_zone_to_name to
1436 * #handle_zone_to_name_it as closure
1438 struct ZoneToNameCtx
1443 struct NamestoreClient *nc;
1446 * Request id (to be used in the response to the client).
1451 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1452 * not finding a name for the zone still counts as a 'success' here,
1453 * as this field is about the success of executing the IPC protocol.
1460 * Zone to name iterator
1462 * @param cls struct ZoneToNameCtx *
1463 * @param seq sequence number of the record
1464 * @param zone_key the zone key
1466 * @param rd_count number of records in @a rd
1467 * @param rd record data
1470 handle_zone_to_name_it (void *cls,
1472 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1474 unsigned int rd_count,
1475 const struct GNUNET_GNSRECORD_Data *rd)
1477 struct ZoneToNameCtx *ztn_ctx = cls;
1478 struct GNUNET_MQ_Envelope *env;
1479 struct ZoneToNameResponseMessage *ztnr_msg;
1488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1489 "Found result for zone-to-name lookup: `%s'\n",
1492 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1493 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1494 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1495 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1498 ztn_ctx->success = GNUNET_SYSERR;
1501 env = GNUNET_MQ_msg_extra (ztnr_msg,
1502 name_len + rd_ser_len,
1503 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1504 ztnr_msg->gns_header.header.size = htons (msg_size);
1505 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1506 ztnr_msg->res = htons (res);
1507 ztnr_msg->rd_len = htons (rd_ser_len);
1508 ztnr_msg->rd_count = htons (rd_count);
1509 ztnr_msg->name_len = htons (name_len);
1510 ztnr_msg->zone = *zone_key;
1511 name_tmp = (char *) &ztnr_msg[1];
1512 GNUNET_memcpy (name_tmp,
1515 rd_tmp = &name_tmp[name_len];
1516 GNUNET_GNSRECORD_records_serialize (rd_count,
1520 ztn_ctx->success = GNUNET_OK;
1521 GNUNET_MQ_send (ztn_ctx->nc->mq,
1527 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1529 * @param cls client client sending the message
1530 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1533 handle_zone_to_name (void *cls,
1534 const struct ZoneToNameMessage *ztn_msg)
1536 struct NamestoreClient *nc = cls;
1537 struct ZoneToNameCtx ztn_ctx;
1538 struct GNUNET_MQ_Envelope *env;
1539 struct ZoneToNameResponseMessage *ztnr_msg;
1541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1542 "Received ZONE_TO_NAME message\n");
1543 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1545 ztn_ctx.success = GNUNET_NO;
1546 if (GNUNET_SYSERR ==
1547 GSN_database->zone_to_name (GSN_database->cls,
1549 &ztn_msg->value_zone,
1550 &handle_zone_to_name_it, &ztn_ctx))
1552 /* internal error, hang up instead of signalling something
1553 that might be wrong */
1555 GNUNET_SERVICE_client_drop (nc->client);
1558 if (GNUNET_NO == ztn_ctx.success)
1560 /* no result found, send empty response */
1561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1562 "Found no result for zone-to-name lookup.\n");
1563 env = GNUNET_MQ_msg (ztnr_msg,
1564 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1565 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1566 ztnr_msg->res = htons (GNUNET_NO);
1567 GNUNET_MQ_send (nc->mq,
1570 GNUNET_SERVICE_client_continue (nc->client);
1575 * Context for record remove operations passed from
1576 * #run_zone_iteration_round to #zone_iterate_proc as closure
1578 struct ZoneIterationProcResult
1581 * The zone iteration handle
1583 struct ZoneIteration *zi;
1586 * Number of results left to be returned in this iteration.
1594 * Process results for zone iteration from database
1596 * @param cls struct ZoneIterationProcResult
1597 * @param seq sequence number of the record
1598 * @param zone_key the zone key
1600 * @param rd_count number of records for this name
1601 * @param rd record data
1604 zone_iterate_proc (void *cls,
1606 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1608 unsigned int rd_count,
1609 const struct GNUNET_GNSRECORD_Data *rd)
1611 struct ZoneIterationProcResult *proc = cls;
1612 int do_refresh_block;
1614 if ( (NULL == zone_key) &&
1617 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1618 "Iteration done\n");
1621 if ( (NULL == zone_key) ||
1624 /* what is this!? should never happen */
1628 if (0 == proc->limit)
1630 /* what is this!? should never happen */
1635 proc->zi->seq = seq;
1636 send_lookup_response (proc->zi->nc,
1637 proc->zi->request_id,
1642 do_refresh_block = GNUNET_NO;
1643 for (unsigned int i=0;i<rd_count;i++)
1644 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1646 do_refresh_block = GNUNET_YES;
1649 if (GNUNET_YES == do_refresh_block)
1650 refresh_block (NULL,
1660 * Perform the next round of the zone iteration.
1662 * @param zi zone iterator to process
1663 * @param limit number of results to return in one pass
1666 run_zone_iteration_round (struct ZoneIteration *zi,
1669 struct ZoneIterationProcResult proc;
1670 struct GNUNET_MQ_Envelope *env;
1671 struct RecordResultMessage *rrm;
1672 struct GNUNET_TIME_Absolute start;
1673 struct GNUNET_TIME_Relative duration;
1678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1679 "Asked to return up to %llu records at position %llu\n",
1680 (unsigned long long) limit,
1681 (unsigned long long) zi->seq);
1684 start = GNUNET_TIME_absolute_get ();
1685 GNUNET_break (GNUNET_SYSERR !=
1686 GSN_database->iterate_records (GSN_database->cls,
1687 (0 == memcmp (&zi->zone,
1696 duration = GNUNET_TIME_absolute_get_duration (start);
1697 duration = GNUNET_TIME_relative_divide (duration,
1698 limit - proc.limit);
1699 GNUNET_STATISTICS_set (statistics,
1700 "NAMESTORE iteration delay (μs/record)",
1701 duration.rel_value_us,
1703 if (0 == proc.limit)
1705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706 "Returned %llu results, more results available\n",
1707 (unsigned long long) limit);
1708 return; /* more results later after we get the
1709 #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message */
1711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712 "Completed iteration after %llu/%llu results\n",
1713 (unsigned long long) (limit - proc.limit),
1714 (unsigned long long) limit);
1715 /* send empty response to indicate end of list */
1716 env = GNUNET_MQ_msg (rrm,
1717 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
1718 rrm->gns_header.r_id = htonl (zi->request_id);
1719 GNUNET_MQ_send (zi->nc->mq,
1721 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head,
1729 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1731 * @param cls the client sending the message
1732 * @param zis_msg message from the client
1735 handle_iteration_start (void *cls,
1736 const struct ZoneIterationStartMessage *zis_msg)
1738 struct NamestoreClient *nc = cls;
1739 struct ZoneIteration *zi;
1741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1742 "Received ZONE_ITERATION_START message\n");
1743 zi = GNUNET_new (struct ZoneIteration);
1744 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1747 zi->zone = zis_msg->zone;
1749 GNUNET_CONTAINER_DLL_insert (nc->op_head,
1752 run_zone_iteration_round (zi,
1754 GNUNET_SERVICE_client_continue (nc->client);
1759 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1761 * @param cls the client sending the message
1762 * @param zis_msg message from the client
1765 handle_iteration_stop (void *cls,
1766 const struct ZoneIterationStopMessage *zis_msg)
1768 struct NamestoreClient *nc = cls;
1769 struct ZoneIteration *zi;
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1773 "Received ZONE_ITERATION_STOP message\n");
1774 rid = ntohl (zis_msg->gns_header.r_id);
1775 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1776 if (zi->request_id == rid)
1781 GNUNET_SERVICE_client_drop (nc->client);
1784 GNUNET_CONTAINER_DLL_remove (nc->op_head,
1788 GNUNET_SERVICE_client_continue (nc->client);
1793 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1795 * @param cls the client sending the message
1796 * @param message message from the client
1799 handle_iteration_next (void *cls,
1800 const struct ZoneIterationNextMessage *zis_msg)
1802 struct NamestoreClient *nc = cls;
1803 struct ZoneIteration *zi;
1807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1808 "Received ZONE_ITERATION_NEXT message\n");
1809 GNUNET_STATISTICS_update (statistics,
1810 "Iteration NEXT messages received",
1813 rid = ntohl (zis_msg->gns_header.r_id);
1814 limit = GNUNET_ntohll (zis_msg->limit);
1815 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1816 if (zi->request_id == rid)
1821 GNUNET_SERVICE_client_drop (nc->client);
1824 run_zone_iteration_round (zi,
1826 GNUNET_SERVICE_client_continue (nc->client);
1831 * Function called when the monitor is ready for more data, and we
1832 * should thus unblock PUT operations that were blocked on the
1833 * monitor not being ready.
1836 monitor_unblock (struct ZoneMonitor *zm)
1838 struct StoreActivity *sa = sa_head;
1840 while ( (NULL != sa) &&
1841 (zm->limit > zm->iteration_cnt) )
1843 struct StoreActivity *sn = sa->next;
1845 if (sa->zm_pos == zm)
1846 continue_store_activity (sa);
1849 if (zm->limit > zm->iteration_cnt)
1851 zm->sa_waiting = GNUNET_NO;
1852 if (NULL != zm->sa_wait_warning)
1854 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1855 zm->sa_wait_warning = NULL;
1858 else if (GNUNET_YES == zm->sa_waiting)
1860 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1861 if (NULL != zm->sa_wait_warning)
1862 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1863 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1871 * Send 'sync' message to zone monitor, we're now in sync.
1873 * @param zm monitor that is now in sync
1876 monitor_sync (struct ZoneMonitor *zm)
1878 struct GNUNET_MQ_Envelope *env;
1879 struct GNUNET_MessageHeader *sync;
1881 env = GNUNET_MQ_msg (sync,
1882 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1883 GNUNET_MQ_send (zm->nc->mq,
1885 /* mark iteration done */
1886 zm->in_first_iteration = GNUNET_NO;
1887 zm->iteration_cnt = 0;
1888 if ( (zm->limit > 0) &&
1890 monitor_unblock (zm);
1895 * Obtain the next datum during the zone monitor's zone initial iteration.
1897 * @param cls zone monitor that does its initial iteration
1900 monitor_iteration_next (void *cls);
1904 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
1906 * @param cls a 'struct ZoneMonitor *' with information about the monitor
1907 * @param seq sequence number of the record
1908 * @param zone_key zone key of the zone
1910 * @param rd_count number of records in @a rd
1911 * @param rd array of records
1914 monitor_iterate_cb (void *cls,
1916 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1918 unsigned int rd_count,
1919 const struct GNUNET_GNSRECORD_Data *rd)
1921 struct ZoneMonitor *zm = cls;
1926 /* finished with iteration */
1930 GNUNET_STATISTICS_update (statistics,
1931 "Monitor notifications sent",
1935 zm->iteration_cnt--;
1936 send_lookup_response (zm->nc,
1942 if ( (0 == zm->iteration_cnt) &&
1945 /* We are done with the current iteration batch, AND the
1946 client would right now accept more, so go again! */
1947 GNUNET_assert (NULL == zm->task);
1948 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1955 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
1957 * @param cls the client sending the message
1958 * @param zis_msg message from the client
1961 handle_monitor_start (void *cls,
1962 const struct ZoneMonitorStartMessage *zis_msg)
1964 struct NamestoreClient *nc = cls;
1965 struct ZoneMonitor *zm;
1967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1968 "Received ZONE_MONITOR_START message\n");
1969 zm = GNUNET_new (struct ZoneMonitor);
1971 zm->zone = zis_msg->zone;
1973 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
1974 GNUNET_CONTAINER_DLL_insert (monitor_head,
1977 GNUNET_SERVICE_client_mark_monitor (nc->client);
1978 GNUNET_SERVICE_client_continue (nc->client);
1979 GNUNET_notification_context_add (monitor_nc,
1981 if (zm->in_first_iteration)
1982 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1990 * Obtain the next datum during the zone monitor's zone initial iteration.
1992 * @param cls zone monitor that does its initial iteration
1995 monitor_iteration_next (void *cls)
1997 struct ZoneMonitor *zm = cls;
2001 GNUNET_assert (0 == zm->iteration_cnt);
2003 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2005 zm->iteration_cnt = zm->limit; /* use it all */
2006 ret = GSN_database->iterate_records (GSN_database->cls,
2007 (0 == memcmp (&zm->zone,
2014 &monitor_iterate_cb,
2016 if (GNUNET_SYSERR == ret)
2018 GNUNET_SERVICE_client_drop (zm->nc->client);
2021 if (GNUNET_NO == ret)
2031 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2033 * @param cls the client sending the message
2034 * @param nm message from the client
2037 handle_monitor_next (void *cls,
2038 const struct ZoneMonitorNextMessage *nm)
2040 struct NamestoreClient *nc = cls;
2041 struct ZoneMonitor *zm;
2044 inc = GNUNET_ntohll (nm->limit);
2045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2046 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2047 (unsigned long long) inc);
2048 for (zm = monitor_head; NULL != zm; zm = zm->next)
2054 GNUNET_SERVICE_client_drop (nc->client);
2057 GNUNET_SERVICE_client_continue (nc->client);
2058 if (zm->limit + inc < zm->limit)
2061 GNUNET_SERVICE_client_drop (nc->client);
2065 if ( (zm->in_first_iteration) &&
2066 (zm->limit == inc) )
2068 /* We are still iterating, and the previous iteration must
2069 have stopped due to the client's limit, so continue it! */
2070 GNUNET_assert (NULL == zm->task);
2071 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2074 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2075 if ( (zm->limit > zm->iteration_cnt) &&
2078 monitor_unblock (zm);
2080 else if (GNUNET_YES == zm->sa_waiting)
2082 if (NULL != zm->sa_wait_warning)
2083 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2084 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2085 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2093 * Process namestore requests.
2095 * @param cls closure
2096 * @param cfg configuration to use
2097 * @param service the initialized service
2101 const struct GNUNET_CONFIGURATION_Handle *cfg,
2102 struct GNUNET_SERVICE_Handle *service)
2108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2109 "Starting namestore service\n");
2110 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2113 disable_namecache = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2117 monitor_nc = GNUNET_notification_context_create (1);
2118 if (GNUNET_YES != disable_namecache)
2120 namecache = GNUNET_NAMECACHE_connect (cfg);
2121 GNUNET_assert (NULL != namecache);
2123 /* Loading database plugin */
2125 GNUNET_CONFIGURATION_get_value_string (cfg,
2129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2130 "No database backend configured\n");
2132 GNUNET_asprintf (&db_lib_name,
2133 "libgnunet_plugin_namestore_%s",
2135 GSN_database = GNUNET_PLUGIN_load (db_lib_name,
2137 GNUNET_free (database);
2138 statistics = GNUNET_STATISTICS_create ("namestore",
2140 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
2142 if (NULL == GSN_database)
2144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2145 "Could not load database backend `%s'\n",
2147 GNUNET_SCHEDULER_shutdown ();
2154 * Define "main" method using service macro.
2158 GNUNET_SERVICE_OPTION_NONE,
2161 &client_disconnect_cb,
2163 GNUNET_MQ_hd_var_size (record_store,
2164 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2165 struct RecordStoreMessage,
2167 GNUNET_MQ_hd_var_size (record_lookup,
2168 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2169 struct LabelLookupMessage,
2171 GNUNET_MQ_hd_fixed_size (zone_to_name,
2172 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2173 struct ZoneToNameMessage,
2175 GNUNET_MQ_hd_fixed_size (iteration_start,
2176 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2177 struct ZoneIterationStartMessage,
2179 GNUNET_MQ_hd_fixed_size (iteration_next,
2180 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2181 struct ZoneIterationNextMessage,
2183 GNUNET_MQ_hd_fixed_size (iteration_stop,
2184 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2185 struct ZoneIterationStopMessage,
2187 GNUNET_MQ_hd_fixed_size (monitor_start,
2188 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2189 struct ZoneMonitorStartMessage,
2191 GNUNET_MQ_hd_fixed_size (monitor_next,
2192 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2193 struct ZoneMonitorNextMessage,
2195 GNUNET_MQ_handler_end ());
2198 /* end of gnunet-service-namestore.c */