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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file namestore/gnunet-service-namestore.c
21 * @brief namestore for the GNUnet naming system
22 * @author Matthias Wachs
23 * @author Christian Grothoff
26 * - "get_nick_record" is a bottleneck, introduce a cache to
27 * avoid looking it up again and again (for the same few
28 * zones that the user will typically manage!)
29 * - run testcases, make sure everything works!
32 #include "gnunet_util_lib.h"
33 #include "gnunet_dnsparser_lib.h"
34 #include "gnunet_gns_service.h"
35 #include "gnunet_namecache_service.h"
36 #include "gnunet_namestore_service.h"
37 #include "gnunet_namestore_plugin.h"
38 #include "gnunet_statistics_service.h"
39 #include "gnunet_signatures.h"
40 #include "namestore.h"
42 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
45 * If a monitor takes more than 1 minute to process an event, print a warning.
47 #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
50 * Size of the cache used by #get_nick_record()
57 struct NamestoreClient;
61 * A namestore iteration operation.
66 * Next element in the DLL
68 struct ZoneIteration *next;
71 * Previous element in the DLL
73 struct ZoneIteration *prev;
76 * Namestore client which intiated this zone iteration
78 struct NamestoreClient *nc;
81 * The nick to add to the records
83 struct GNUNET_GNSRECORD_Data *nick;
86 * Key of the zone we are iterating over.
88 struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
91 * Last sequence number in the zone iteration used to address next
92 * result of the zone iteration in the store
95 * Updated in #zone_iterate_proc()
100 * The operation id fot the zone iteration in the response for the client
105 * Offset of the zone iteration used to address next result of the zone
106 * iteration in the store
108 * Initialy set to 0 in #handle_iteration_start
109 * Incremented with by every call to #handle_iteration_next
114 * Number of pending cache operations triggered by this zone iteration which we
115 * need to wait for before allowing the client to continue.
117 unsigned int cache_ops;
120 * Set to #GNUNET_YES if the last iteration exhausted the limit set by the
121 * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
122 * message and free the data structure once @e cache_ops is zero.
132 struct NamestoreClient
138 struct GNUNET_SERVICE_Client *client;
141 * Message queue for transmission to @e client
143 struct GNUNET_MQ_Handle *mq;
147 * Zone iteration operations in progress initiated by this client
149 struct ZoneIteration *op_head;
153 * Zone iteration operations in progress initiated by this client
155 struct ZoneIteration *op_tail;
160 * A namestore monitor.
165 * Next element in the DLL
167 struct ZoneMonitor *next;
170 * Previous element in the DLL
172 struct ZoneMonitor *prev;
175 * Namestore client which intiated this zone monitor
177 struct NamestoreClient *nc;
180 * Private key of the zone.
182 struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
185 * Task active during initial iteration.
187 struct GNUNET_SCHEDULER_Task *task;
190 * Task to warn about slow monitors.
192 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
195 * Since when are we blocked on this monitor?
197 struct GNUNET_TIME_Absolute sa_waiting_start;
200 * Last sequence number in the zone iteration used to address next
201 * result of the zone iteration in the store
204 * Updated in #monitor_iterate_cb()
209 * Current limit of how many more messages we are allowed
210 * to queue to this monitor.
215 * How many more requests may we receive from the iterator
216 * before it is at the limit we gave it? Will be below or
217 * equal to @e limit. The effective limit for monitor
218 * events is thus @e iteration_cnt - @e limit!
220 uint64_t iteration_cnt;
223 * Are we (still) in the initial iteration pass?
225 int in_first_iteration;
228 * Is there a store activity waiting for this monitor? We only raise the
229 * flag when it happens and search the DLL for the store activity when we
230 * had a limit increase. If we cannot find any waiting store activity at
231 * that time, we clear the flag again.
239 * Pending operation on the namecache.
241 struct CacheOperation
247 struct CacheOperation *prev;
252 struct CacheOperation *next;
255 * Handle to namecache queue.
257 struct GNUNET_NAMECACHE_QueueEntry *qe;
260 * Client to notify about the result, can be NULL.
262 struct NamestoreClient *nc;
265 * Zone iteration to call #zone_iteration_done_client_continue()
266 * for if applicable, can be NULL.
268 struct ZoneIteration *zi;
271 * Client's request ID.
278 * Information for an ongoing #handle_record_store() operation.
279 * Needed as we may wait for monitors to be ready for the notification.
286 struct StoreActivity *next;
291 struct StoreActivity *prev;
294 * Which client triggered the store activity?
296 struct NamestoreClient *nc;
299 * Copy of the original store message (as data fields in @e rd will
302 const struct RecordStoreMessage *rsm;
305 * Next zone monitor that still needs to be notified about this PUT.
307 struct ZoneMonitor *zm_pos;
310 * Label nicely canonicalized (lower case).
318 * Entry in list of cached nick resolutions.
323 * Zone the cache entry is for.
325 struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
328 * Cached record data.
330 struct GNUNET_GNSRECORD_Data *rd;
333 * Timestamp when this cache entry was used last.
335 struct GNUNET_TIME_Absolute last_used;
340 * We cache nick records to reduce DB load.
342 static struct NickCache nick_cache[NC_SIZE];
345 * Public key of all zeros.
347 static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
350 * Configuration handle.
352 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
355 * Handle to the statistics service
357 static struct GNUNET_STATISTICS_Handle *statistics;
362 static struct GNUNET_NAMECACHE_Handle *namecache;
367 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
370 * Name of the database plugin
372 static char *db_lib_name;
377 static struct CacheOperation *cop_head;
382 static struct CacheOperation *cop_tail;
385 * First active zone monitor.
387 static struct ZoneMonitor *monitor_head;
390 * Last active zone monitor.
392 static struct ZoneMonitor *monitor_tail;
395 * Head of DLL of monitor-blocked store activities.
397 static struct StoreActivity *sa_head;
400 * Tail of DLL of monitor-blocked store activities.
402 static struct StoreActivity *sa_tail;
405 * Notification context shared by all monitors.
407 static struct GNUNET_NotificationContext *monitor_nc;
410 * Optimize block insertion by caching map of private keys to
411 * public keys in memory?
413 static int cache_keys;
416 * Use the namecache? Doing so creates additional cryptographic
417 * operations whenever we touch a record.
419 static int disable_namecache;
423 * Task run during shutdown.
428 cleanup_task (void *cls)
430 struct CacheOperation *cop;
433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
434 "Stopping namestore service\n");
435 while (NULL != (cop = cop_head))
437 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
438 "Aborting incomplete namecache operation\n");
439 GNUNET_NAMECACHE_cancel (cop->qe);
440 GNUNET_CONTAINER_DLL_remove (cop_head,
445 if (NULL != namecache)
447 GNUNET_NAMECACHE_disconnect (namecache);
450 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
452 GNUNET_free (db_lib_name);
454 if (NULL != monitor_nc)
456 GNUNET_notification_context_destroy (monitor_nc);
459 if (NULL != statistics)
461 GNUNET_STATISTICS_destroy (statistics,
469 * Release memory used by @a sa.
471 * @param sa activity to free
474 free_store_activity (struct StoreActivity *sa)
476 GNUNET_CONTAINER_DLL_remove (sa_head,
479 GNUNET_free (sa->conv_name);
485 * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
486 * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
487 * record, which (if found) is then copied to @a cls for future use.
489 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
490 * @param seq sequence number of the record
491 * @param private_key the private key of the zone (unused)
492 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
493 * @param rd_count number of records in @a rd
494 * @param rd records stored under @a label in the zone
497 lookup_nick_it (void *cls,
499 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
501 unsigned int rd_count,
502 const struct GNUNET_GNSRECORD_Data *rd)
504 struct GNUNET_GNSRECORD_Data **res = cls;
508 if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
513 for (unsigned int c = 0; c < rd_count; c++)
515 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
517 (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data));
518 (*res)->data = &(*res)[1];
519 GNUNET_memcpy ((void *) (*res)->data,
522 (*res)->data_size = rd[c].data_size;
523 (*res)->expiration_time = rd[c].expiration_time;
524 (*res)->flags = rd[c].flags;
525 (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
534 * Add entry to the cache for @a zone and @a nick
536 * @param zone zone key to cache under
537 * @param nick nick entry to cache
540 cache_nick (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
541 const struct GNUNET_GNSRECORD_Data *nick)
543 struct NickCache *oldest;
546 for (unsigned int i=0;i<NC_SIZE;i++)
548 struct NickCache *pos = &nick_cache[i];
550 if ( (NULL == oldest) ||
551 (oldest->last_used.abs_value_us >
552 pos->last_used.abs_value_us) )
554 if (0 == memcmp (zone,
562 GNUNET_free_non_null (oldest->rd);
563 oldest->zone = *zone;
564 oldest->rd = GNUNET_malloc (sizeof (*nick) +
567 oldest->rd->data = &oldest->rd[1];
568 memcpy (&oldest->rd[1],
571 oldest->last_used = GNUNET_TIME_absolute_get ();
576 * Return the NICK record for the zone (if it exists).
578 * @param zone private key for the zone to look for nick
579 * @return NULL if no NICK record was found
581 static struct GNUNET_GNSRECORD_Data *
582 get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone)
584 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
585 struct GNUNET_GNSRECORD_Data *nick;
588 /* check cache first */
589 for (unsigned int i=0;i<NC_SIZE;i++)
591 struct NickCache *pos = &nick_cache[i];
592 if ( (NULL != pos->rd) &&
597 nick = GNUNET_malloc (sizeof (*nick) +
600 nick->data = &nick[1];
604 pos->last_used = GNUNET_TIME_absolute_get ();
610 res = GSN_database->lookup_records (GSN_database->cls,
612 GNUNET_GNS_EMPTY_LABEL_AT,
615 if ( (GNUNET_OK != res) ||
618 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
620 "No nick name set for zone `%s'\n",
621 GNUNET_GNSRECORD_z2s (&pub));
633 * Merge the nick record @a nick_rd with the rest of the
634 * record set given in @a rd2. Store the result in @a rdc_res
635 * and @a rd_res. The @a nick_rd's expiration time is set to
636 * the maximum expiration time of all of the records in @a rd2.
638 * @param nick_rd the nick record to integrate
639 * @param rd2_length length of the @a rd2 array
640 * @param rd2 array of records
641 * @param rdc_res[out] length of the resulting @a rd_res array
642 * @param rd_res[out] set to an array of records,
643 * including @a nick_rd and @a rd2;
644 * all of the variable-size 'data' fields in @a rd2 are
645 * allocated in the same chunk of memory!
648 merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
649 unsigned int rd2_length,
650 const struct GNUNET_GNSRECORD_Data *rd2,
651 unsigned int *rdc_res,
652 struct GNUNET_GNSRECORD_Data **rd_res)
654 uint64_t latest_expiration;
658 struct GNUNET_GNSRECORD_Data *target;
660 (*rdc_res) = 1 + rd2_length;
661 if (0 == 1 + rd2_length)
667 req = sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
668 for (unsigned int i=0; i<rd2_length; i++)
670 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
672 if (req + sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
678 req += sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size;
680 target = GNUNET_malloc (req);
682 data = (char *) &target[1 + rd2_length];
684 latest_expiration = 0;
685 for (unsigned int i=0;i<rd2_length;i++)
687 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
689 if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
691 if ((GNUNET_TIME_absolute_get().abs_value_us + orig->expiration_time) >
693 latest_expiration = orig->expiration_time;
695 else if (orig->expiration_time > latest_expiration)
696 latest_expiration = orig->expiration_time;
698 target[i].data = (void *) &data[data_offset];
699 GNUNET_memcpy (&data[data_offset],
702 data_offset += orig->data_size;
705 target[rd2_length] = *nick_rd;
706 target[rd2_length].expiration_time = latest_expiration;
707 target[rd2_length].data = (void *) &data[data_offset];
708 GNUNET_memcpy (&data[data_offset],
711 data_offset += nick_rd->data_size;
712 GNUNET_assert (req ==
713 (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
718 * Generate a `struct LookupNameResponseMessage` and send it to the
719 * given client using the given notification context.
721 * @param nc client to unicast to
722 * @param request_id request ID to use
723 * @param zone_key zone key of the zone
725 * @param rd_count number of records in @a rd
726 * @param rd array of records
729 send_lookup_response (struct NamestoreClient *nc,
731 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
733 unsigned int rd_count,
734 const struct GNUNET_GNSRECORD_Data *rd)
736 struct GNUNET_MQ_Envelope *env;
737 struct RecordResultMessage *zir_msg;
738 struct GNUNET_GNSRECORD_Data *nick;
739 struct GNUNET_GNSRECORD_Data *res;
740 unsigned int res_count;
746 nick = get_nick_record (zone_key);
748 GNUNET_GNSRECORD_records_get_size (rd_count,
751 if ( (NULL != nick) &&
753 GNUNET_GNS_EMPTY_LABEL_AT)))
755 nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
756 merge_with_nick_records (nick,
765 res_count = rd_count;
766 res = (struct GNUNET_GNSRECORD_Data *) rd;
770 GNUNET_GNSRECORD_records_get_size (res_count,
774 name_len = strlen (name) + 1;
775 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count,
780 GNUNET_SERVICE_client_drop (nc->client);
783 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof (*zir_msg))
786 GNUNET_SERVICE_client_drop (nc->client);
789 env = GNUNET_MQ_msg_extra (zir_msg,
790 name_len + rd_ser_len,
791 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
792 zir_msg->gns_header.r_id = htonl (request_id);
793 zir_msg->name_len = htons (name_len);
794 zir_msg->rd_count = htons (res_count);
795 zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
796 zir_msg->private_key = *zone_key;
797 name_tmp = (char *) &zir_msg[1];
798 GNUNET_memcpy (name_tmp,
801 rd_ser = &name_tmp[name_len];
802 GNUNET_assert (rd_ser_len ==
803 GNUNET_GNSRECORD_records_serialize (res_count,
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
808 "Sending RECORD_RESULT message with %u records\n",
810 GNUNET_STATISTICS_update (statistics,
811 "Record sets sent to clients",
814 GNUNET_MQ_send (nc->mq,
822 * Send response to the store request to the client.
824 * @param client client to talk to
825 * @param res status of the operation
826 * @param rid client's request ID
829 send_store_response (struct NamestoreClient *nc,
833 struct GNUNET_MQ_Envelope *env;
834 struct RecordStoreResponseMessage *rcr_msg;
836 GNUNET_assert (NULL != nc);
837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
838 "Sending RECORD_STORE_RESPONSE message\n");
839 GNUNET_STATISTICS_update (statistics,
840 "Store requests completed",
843 env = GNUNET_MQ_msg (rcr_msg,
844 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
845 rcr_msg->gns_header.r_id = htonl (rid);
846 rcr_msg->op_result = htonl (res);
847 GNUNET_MQ_send (nc->mq,
853 * Function called once we are done with the zone iteration and
854 * allow the zone iteration client to send us more messages.
856 * @param zi zone iteration we are processing
859 zone_iteration_done_client_continue (struct ZoneIteration *zi)
861 struct GNUNET_MQ_Envelope *env;
862 struct GNUNET_NAMESTORE_Header *em;
864 GNUNET_SERVICE_client_continue (zi->nc->client);
867 /* send empty response to indicate end of list */
868 env = GNUNET_MQ_msg (em,
869 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
870 em->r_id = htonl (zi->request_id);
871 GNUNET_MQ_send (zi->nc->mq,
874 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head,
882 * Cache operation complete, clean up.
884 * @param cls the `struct CacheOperation`
885 * @param success success
886 * @param emsg error messages
889 finish_cache_operation (void *cls,
893 struct CacheOperation *cop = cls;
894 struct ZoneIteration *zi;
897 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
898 _("Failed to replicate block in namecache: %s\n"),
901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
902 "CACHE operation completed\n");
903 GNUNET_CONTAINER_DLL_remove (cop_head,
907 send_store_response (cop->nc,
910 if (NULL != (zi = cop->zi))
913 if (0 == zi->cache_ops)
915 /* unchoke zone iteration, cache has caught up */
916 zone_iteration_done_client_continue (zi);
924 * We just touched the plaintext information about a name in our zone;
925 * refresh the corresponding (encrypted) block in the namecache.
927 * @param nc client responsible for the request, can be NULL
928 * @param zi zone iteration response for the request, can be NULL
929 * @param rid request ID of the client
930 * @param zone_key private key of the zone
931 * @param name label for the records
932 * @param rd_count number of records
933 * @param rd records stored under the given @a name
936 refresh_block (struct NamestoreClient *nc,
937 struct ZoneIteration *zi,
939 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
941 unsigned int rd_count,
942 const struct GNUNET_GNSRECORD_Data *rd)
944 struct GNUNET_GNSRECORD_Block *block;
945 struct CacheOperation *cop;
946 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
947 struct GNUNET_GNSRECORD_Data *nick;
948 struct GNUNET_GNSRECORD_Data *res;
949 unsigned int res_count;
950 struct GNUNET_TIME_Absolute exp_time;
952 nick = get_nick_record (zone_key);
953 res_count = rd_count;
954 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
957 nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
958 merge_with_nick_records (nick,
967 send_store_response (nc,
970 return; /* no data, no need to update cache */
972 if (GNUNET_YES == disable_namecache)
974 GNUNET_STATISTICS_update (statistics,
975 "Namecache updates skipped (NC disabled)",
979 send_store_response (nc,
984 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count,
987 block = GNUNET_GNSRECORD_block_create2 (zone_key,
993 block = GNUNET_GNSRECORD_block_create (zone_key,
998 GNUNET_assert (NULL != block);
999 GNUNET_CRYPTO_ecdsa_key_get_public (zone_key,
1001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1002 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
1005 GNUNET_STRINGS_absolute_time_to_string (exp_time),
1006 GNUNET_GNSRECORD_z2s (&pkey));
1007 GNUNET_STATISTICS_update (statistics,
1008 "Namecache updates pushed",
1011 cop = GNUNET_new (struct CacheOperation);
1017 GNUNET_CONTAINER_DLL_insert (cop_head,
1020 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
1022 &finish_cache_operation,
1024 GNUNET_free (block);
1029 * Print a warning that one of our monitors is no longer reacting.
1031 * @param cls a `struct ZoneMonitor` to warn about
1034 warn_monitor_slow (void *cls)
1036 struct ZoneMonitor *zm = cls;
1038 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1039 "No response from monitor since %s\n",
1040 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
1041 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1048 * Continue processing the @a sa.
1050 * @param sa store activity to process
1053 continue_store_activity (struct StoreActivity *sa)
1055 const struct RecordStoreMessage *rp_msg = sa->rsm;
1056 unsigned int rd_count;
1060 const char *name_tmp;
1063 rid = ntohl (rp_msg->gns_header.r_id);
1064 name_len = ntohs (rp_msg->name_len);
1065 rd_count = ntohs (rp_msg->rd_count);
1066 rd_ser_len = ntohs (rp_msg->rd_len);
1067 name_tmp = (const char *) &rp_msg[1];
1068 rd_ser = &name_tmp[name_len];
1070 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1072 /* We did this before, must succeed again */
1073 GNUNET_assert (GNUNET_OK ==
1074 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
1079 for (struct ZoneMonitor *zm = sa->zm_pos;
1083 if ( (0 != memcmp (&rp_msg->private_key,
1085 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
1086 (0 != memcmp (&zm->zone,
1088 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
1090 sa->zm_pos = zm->next; /* not interesting to this monitor */
1093 if (zm->limit == zm->iteration_cnt)
1095 zm->sa_waiting = GNUNET_YES;
1096 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1097 if (NULL != zm->sa_wait_warning)
1098 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1099 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1102 return; /* blocked on zone monitor */
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105 "Notifying monitor about changes under label `%s'\n",
1108 send_lookup_response (zm->nc,
1110 &rp_msg->private_key,
1114 sa->zm_pos = zm->next;
1116 /* great, done with the monitors, unpack (again) for refresh_block operation */
1117 refresh_block (sa->nc,
1120 &rp_msg->private_key,
1125 GNUNET_SERVICE_client_continue (sa->nc->client);
1126 free_store_activity (sa);
1131 * Called whenever a client is disconnected.
1132 * Frees our resources associated with that client.
1134 * @param cls closure
1135 * @param client identification of the client
1136 * @param app_ctx the `struct NamestoreClient` of @a client
1139 client_disconnect_cb (void *cls,
1140 struct GNUNET_SERVICE_Client *client,
1143 struct NamestoreClient *nc = app_ctx;
1144 struct ZoneIteration *no;
1145 struct CacheOperation *cop;
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1149 "Client %p disconnected\n",
1151 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1153 struct StoreActivity *san;
1157 GNUNET_CONTAINER_DLL_remove (monitor_head,
1160 if (NULL != zm->task)
1162 GNUNET_SCHEDULER_cancel (zm->task);
1165 if (NULL != zm->sa_wait_warning)
1167 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1168 zm->sa_wait_warning = NULL;
1170 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1173 if (zm == sa->zm_pos)
1175 sa->zm_pos = zm->next;
1176 /* this may free sa */
1177 continue_store_activity (sa);
1183 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1187 /* this may free sa */
1188 free_store_activity (sa);
1189 break; /* there can only be one per nc */
1192 while (NULL != (no = nc->op_head))
1194 GNUNET_CONTAINER_DLL_remove (nc->op_head,
1199 for (cop = cop_head; NULL != cop; cop = cop->next)
1207 * Add a client to our list of active clients.
1210 * @param client client to add
1211 * @param mq message queue for @a client
1212 * @return internal namestore client structure for this client
1215 client_connect_cb (void *cls,
1216 struct GNUNET_SERVICE_Client *client,
1217 struct GNUNET_MQ_Handle *mq)
1219 struct NamestoreClient *nc;
1222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1223 "Client %p connected\n",
1225 nc = GNUNET_new (struct NamestoreClient);
1226 nc->client = client;
1233 * Closure for #lookup_it().
1235 struct RecordLookupContext
1251 struct GNUNET_GNSRECORD_Data *nick;
1261 unsigned int res_rd_count;
1273 * @param seq sequence number of the record
1276 lookup_it (void *cls,
1278 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
1280 unsigned int rd_count,
1281 const struct GNUNET_GNSRECORD_Data *rd)
1283 struct RecordLookupContext *rlc = cls;
1287 if (0 != strcmp (label,
1290 rlc->found = GNUNET_YES;
1293 rlc->rd_ser_len = 0;
1294 rlc->res_rd_count = 0;
1298 if ( (NULL != rlc->nick) &&
1299 (0 != strcmp (label,
1300 GNUNET_GNS_EMPTY_LABEL_AT)) )
1303 struct GNUNET_GNSRECORD_Data *rd_res;
1304 unsigned int rdc_res;
1308 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
1309 merge_with_nick_records (rlc->nick,
1314 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
1316 if (rlc->rd_ser_len < 0)
1319 GNUNET_free (rd_res);
1320 rlc->found = GNUNET_NO;
1321 rlc->rd_ser_len = 0;
1324 rlc->res_rd_count = rdc_res;
1325 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1326 if (rlc->rd_ser_len !=
1327 GNUNET_GNSRECORD_records_serialize (rdc_res,
1333 GNUNET_free (rlc->res_rd);
1335 rlc->res_rd_count = 0;
1336 rlc->rd_ser_len = 0;
1337 GNUNET_free (rd_res);
1338 rlc->found = GNUNET_NO;
1341 GNUNET_free (rd_res);
1342 GNUNET_free (rlc->nick);
1347 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1349 if (rlc->rd_ser_len < 0)
1352 rlc->found = GNUNET_NO;
1353 rlc->rd_ser_len = 0;
1356 rlc->res_rd_count = rd_count;
1357 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1358 if (rlc->rd_ser_len !=
1359 GNUNET_GNSRECORD_records_serialize (rd_count,
1365 GNUNET_free (rlc->res_rd);
1367 rlc->res_rd_count = 0;
1368 rlc->rd_ser_len = 0;
1369 rlc->found = GNUNET_NO;
1377 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1379 * @param cls client sending the message
1380 * @param ll_msg message of type `struct LabelLookupMessage`
1381 * @return #GNUNET_OK if @a ll_msg is well-formed
1384 check_record_lookup (void *cls,
1385 const struct LabelLookupMessage *ll_msg)
1391 name_len = ntohl (ll_msg->label_len);
1392 src_size = ntohs (ll_msg->gns_header.header.size);
1393 if (name_len != src_size - sizeof (struct LabelLookupMessage))
1396 return GNUNET_SYSERR;
1398 GNUNET_MQ_check_zero_termination (ll_msg);
1404 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1406 * @param cls client sending the message
1407 * @param ll_msg message of type `struct LabelLookupMessage`
1410 handle_record_lookup (void *cls,
1411 const struct LabelLookupMessage *ll_msg)
1413 struct NamestoreClient *nc = cls;
1414 struct GNUNET_MQ_Envelope *env;
1415 struct LabelLookupResponseMessage *llr_msg;
1416 struct RecordLookupContext rlc;
1417 const char *name_tmp;
1423 name_len = ntohl (ll_msg->label_len);
1424 name_tmp = (const char *) &ll_msg[1];
1425 GNUNET_SERVICE_client_continue (nc->client);
1426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1427 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1430 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1431 if (NULL == conv_name)
1433 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1434 "Error converting name `%s'\n",
1436 GNUNET_SERVICE_client_drop (nc->client);
1439 rlc.label = conv_name;
1440 rlc.found = GNUNET_NO;
1441 rlc.res_rd_count = 0;
1444 rlc.nick = get_nick_record (&ll_msg->zone);
1445 res = GSN_database->lookup_records (GSN_database->cls,
1450 GNUNET_free (conv_name);
1451 env = GNUNET_MQ_msg_extra (llr_msg,
1452 name_len + rlc.rd_ser_len,
1453 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1454 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1455 llr_msg->private_key = ll_msg->zone;
1456 llr_msg->name_len = htons (name_len);
1457 llr_msg->rd_count = htons (rlc.res_rd_count);
1458 llr_msg->rd_len = htons (rlc.rd_ser_len);
1459 res_name = (char *) &llr_msg[1];
1460 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1461 llr_msg->found = ntohs (GNUNET_YES);
1463 llr_msg->found = ntohs (GNUNET_NO);
1464 GNUNET_memcpy (&llr_msg[1],
1467 GNUNET_memcpy (&res_name[name_len],
1470 GNUNET_MQ_send (nc->mq,
1472 GNUNET_free_non_null (rlc.res_rd);
1477 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1479 * @param cls client sending the message
1480 * @param rp_msg message of type `struct RecordStoreMessage`
1481 * @return #GNUNET_OK if @a rp_msg is well-formed
1484 check_record_store (void *cls,
1485 const struct RecordStoreMessage *rp_msg)
1489 size_t msg_size_exp;
1491 const char *name_tmp;
1494 name_len = ntohs (rp_msg->name_len);
1495 msg_size = ntohs (rp_msg->gns_header.header.size);
1496 rd_ser_len = ntohs (rp_msg->rd_len);
1497 msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
1498 if (msg_size != msg_size_exp)
1501 return GNUNET_SYSERR;
1503 if ( (0 == name_len) ||
1504 (name_len > MAX_NAME_LEN) )
1507 return GNUNET_SYSERR;
1509 name_tmp = (const char *) &rp_msg[1];
1510 if ('\0' != name_tmp[name_len -1])
1513 return GNUNET_SYSERR;
1520 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1522 * @param cls client sending the message
1523 * @param rp_msg message of type `struct RecordStoreMessage`
1526 handle_record_store (void *cls,
1527 const struct RecordStoreMessage *rp_msg)
1529 struct NamestoreClient *nc = cls;
1533 const char *name_tmp;
1536 unsigned int rd_count;
1538 struct StoreActivity *sa;
1540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1541 "Received NAMESTORE_RECORD_STORE message\n");
1542 rid = ntohl (rp_msg->gns_header.r_id);
1543 name_len = ntohs (rp_msg->name_len);
1544 rd_count = ntohs (rp_msg->rd_count);
1545 rd_ser_len = ntohs (rp_msg->rd_len);
1546 GNUNET_break (0 == ntohs (rp_msg->reserved));
1547 name_tmp = (const char *) &rp_msg[1];
1548 rd_ser = &name_tmp[name_len];
1550 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1553 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
1559 GNUNET_SERVICE_client_drop (nc->client);
1563 /* Extracting and converting private key */
1564 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1565 if (NULL == conv_name)
1567 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1568 "Error converting name `%s'\n",
1570 GNUNET_SERVICE_client_drop (nc->client);
1573 GNUNET_STATISTICS_update (statistics,
1574 "Well-formed store requests received",
1577 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1578 "Creating %u records for name `%s'\n",
1579 (unsigned int) rd_count,
1581 if ( (0 == rd_count) &&
1583 GSN_database->lookup_records (GSN_database->cls,
1584 &rp_msg->private_key,
1589 /* This name does not exist, so cannot be removed */
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1591 "Name `%s' does not exist, no deletion required\n",
1597 /* remove "NICK" records, unless this is for the
1598 #GNUNET_GNS_EMPTY_LABEL_AT label */
1599 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1600 unsigned int rd_clean_off;
1603 for (unsigned int i=0;i<rd_count;i++)
1605 rd_clean[rd_clean_off] = rd[i];
1606 if ( (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT,
1608 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type) )
1611 if ( (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT,
1613 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) )
1614 cache_nick (&rp_msg->private_key,
1617 res = GSN_database->store_records (GSN_database->cls,
1618 &rp_msg->private_key,
1624 if (GNUNET_OK != res)
1626 /* store not successful, not need to tell monitors */
1627 send_store_response (nc,
1630 GNUNET_SERVICE_client_continue (nc->client);
1631 GNUNET_free (conv_name);
1635 sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1636 ntohs (rp_msg->gns_header.header.size));
1637 GNUNET_CONTAINER_DLL_insert (sa_head,
1641 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1642 GNUNET_memcpy (&sa[1],
1644 ntohs (rp_msg->gns_header.header.size));
1645 sa->zm_pos = monitor_head;
1646 sa->conv_name = conv_name;
1647 continue_store_activity (sa);
1653 * Context for record remove operations passed from #handle_zone_to_name to
1654 * #handle_zone_to_name_it as closure
1656 struct ZoneToNameCtx
1661 struct NamestoreClient *nc;
1664 * Request id (to be used in the response to the client).
1669 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1670 * not finding a name for the zone still counts as a 'success' here,
1671 * as this field is about the success of executing the IPC protocol.
1678 * Zone to name iterator
1680 * @param cls struct ZoneToNameCtx *
1681 * @param seq sequence number of the record
1682 * @param zone_key the zone key
1684 * @param rd_count number of records in @a rd
1685 * @param rd record data
1688 handle_zone_to_name_it (void *cls,
1690 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1692 unsigned int rd_count,
1693 const struct GNUNET_GNSRECORD_Data *rd)
1695 struct ZoneToNameCtx *ztn_ctx = cls;
1696 struct GNUNET_MQ_Envelope *env;
1697 struct ZoneToNameResponseMessage *ztnr_msg;
1706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1707 "Found result for zone-to-name lookup: `%s'\n",
1710 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1711 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1716 ztn_ctx->success = GNUNET_SYSERR;
1719 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1720 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1723 ztn_ctx->success = GNUNET_SYSERR;
1726 env = GNUNET_MQ_msg_extra (ztnr_msg,
1727 name_len + rd_ser_len,
1728 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1729 ztnr_msg->gns_header.header.size = htons (msg_size);
1730 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1731 ztnr_msg->res = htons (res);
1732 ztnr_msg->rd_len = htons (rd_ser_len);
1733 ztnr_msg->rd_count = htons (rd_count);
1734 ztnr_msg->name_len = htons (name_len);
1735 ztnr_msg->zone = *zone_key;
1736 name_tmp = (char *) &ztnr_msg[1];
1737 GNUNET_memcpy (name_tmp,
1740 rd_tmp = &name_tmp[name_len];
1741 GNUNET_assert (rd_ser_len ==
1742 GNUNET_GNSRECORD_records_serialize (rd_count,
1746 ztn_ctx->success = GNUNET_OK;
1747 GNUNET_MQ_send (ztn_ctx->nc->mq,
1753 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1755 * @param cls client client sending the message
1756 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1759 handle_zone_to_name (void *cls,
1760 const struct ZoneToNameMessage *ztn_msg)
1762 struct NamestoreClient *nc = cls;
1763 struct ZoneToNameCtx ztn_ctx;
1764 struct GNUNET_MQ_Envelope *env;
1765 struct ZoneToNameResponseMessage *ztnr_msg;
1767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1768 "Received ZONE_TO_NAME message\n");
1769 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1771 ztn_ctx.success = GNUNET_NO;
1772 if (GNUNET_SYSERR ==
1773 GSN_database->zone_to_name (GSN_database->cls,
1775 &ztn_msg->value_zone,
1776 &handle_zone_to_name_it, &ztn_ctx))
1778 /* internal error, hang up instead of signalling something
1779 that might be wrong */
1781 GNUNET_SERVICE_client_drop (nc->client);
1784 if (GNUNET_NO == ztn_ctx.success)
1786 /* no result found, send empty response */
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1788 "Found no result for zone-to-name lookup.\n");
1789 env = GNUNET_MQ_msg (ztnr_msg,
1790 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1791 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1792 ztnr_msg->res = htons (GNUNET_NO);
1793 GNUNET_MQ_send (nc->mq,
1796 GNUNET_SERVICE_client_continue (nc->client);
1801 * Context for record remove operations passed from
1802 * #run_zone_iteration_round to #zone_iterate_proc as closure
1804 struct ZoneIterationProcResult
1807 * The zone iteration handle
1809 struct ZoneIteration *zi;
1812 * Number of results left to be returned in this iteration.
1820 * Process results for zone iteration from database
1822 * @param cls struct ZoneIterationProcResult
1823 * @param seq sequence number of the record
1824 * @param zone_key the zone key
1826 * @param rd_count number of records for this name
1827 * @param rd record data
1830 zone_iterate_proc (void *cls,
1832 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1834 unsigned int rd_count,
1835 const struct GNUNET_GNSRECORD_Data *rd)
1837 struct ZoneIterationProcResult *proc = cls;
1838 int do_refresh_block;
1840 if ( (NULL == zone_key) &&
1843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1844 "Iteration done\n");
1847 if ( (NULL == zone_key) ||
1850 /* what is this!? should never happen */
1854 if (0 == proc->limit)
1856 /* what is this!? should never happen */
1861 proc->zi->seq = seq;
1862 send_lookup_response (proc->zi->nc,
1863 proc->zi->request_id,
1870 do_refresh_block = GNUNET_NO;
1871 for (unsigned int i=0;i<rd_count;i++)
1872 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1874 do_refresh_block = GNUNET_YES;
1877 if (GNUNET_YES == do_refresh_block)
1878 refresh_block (NULL,
1889 * Perform the next round of the zone iteration.
1891 * @param zi zone iterator to process
1892 * @param limit number of results to return in one pass
1895 run_zone_iteration_round (struct ZoneIteration *zi,
1898 struct ZoneIterationProcResult proc;
1899 struct GNUNET_TIME_Absolute start;
1900 struct GNUNET_TIME_Relative duration;
1905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1906 "Asked to return up to %llu records at position %llu\n",
1907 (unsigned long long) limit,
1908 (unsigned long long) zi->seq);
1911 start = GNUNET_TIME_absolute_get ();
1912 GNUNET_break (GNUNET_SYSERR !=
1913 GSN_database->iterate_records (GSN_database->cls,
1914 (0 == memcmp (&zi->zone,
1923 duration = GNUNET_TIME_absolute_get_duration (start);
1924 duration = GNUNET_TIME_relative_divide (duration,
1925 limit - proc.limit);
1926 GNUNET_STATISTICS_set (statistics,
1927 "NAMESTORE iteration delay (μs/record)",
1928 duration.rel_value_us,
1930 if (0 == proc.limit)
1931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1932 "Returned %llu results, more results available\n",
1933 (unsigned long long) limit);
1934 zi->send_end = (0 != proc.limit);
1935 if (0 == zi->cache_ops)
1936 zone_iteration_done_client_continue (zi);
1941 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1943 * @param cls the client sending the message
1944 * @param zis_msg message from the client
1947 handle_iteration_start (void *cls,
1948 const struct ZoneIterationStartMessage *zis_msg)
1950 struct NamestoreClient *nc = cls;
1951 struct ZoneIteration *zi;
1953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1954 "Received ZONE_ITERATION_START message\n");
1955 zi = GNUNET_new (struct ZoneIteration);
1956 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1959 zi->zone = zis_msg->zone;
1961 GNUNET_CONTAINER_DLL_insert (nc->op_head,
1964 run_zone_iteration_round (zi,
1970 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1972 * @param cls the client sending the message
1973 * @param zis_msg message from the client
1976 handle_iteration_stop (void *cls,
1977 const struct ZoneIterationStopMessage *zis_msg)
1979 struct NamestoreClient *nc = cls;
1980 struct ZoneIteration *zi;
1983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1984 "Received ZONE_ITERATION_STOP message\n");
1985 rid = ntohl (zis_msg->gns_header.r_id);
1986 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1987 if (zi->request_id == rid)
1992 GNUNET_SERVICE_client_drop (nc->client);
1995 GNUNET_CONTAINER_DLL_remove (nc->op_head,
1999 GNUNET_SERVICE_client_continue (nc->client);
2004 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
2006 * @param cls the client sending the message
2007 * @param message message from the client
2010 handle_iteration_next (void *cls,
2011 const struct ZoneIterationNextMessage *zis_msg)
2013 struct NamestoreClient *nc = cls;
2014 struct ZoneIteration *zi;
2018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2019 "Received ZONE_ITERATION_NEXT message\n");
2020 GNUNET_STATISTICS_update (statistics,
2021 "Iteration NEXT messages received",
2024 rid = ntohl (zis_msg->gns_header.r_id);
2025 limit = GNUNET_ntohll (zis_msg->limit);
2026 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2027 if (zi->request_id == rid)
2032 GNUNET_SERVICE_client_drop (nc->client);
2035 run_zone_iteration_round (zi,
2041 * Function called when the monitor is ready for more data, and we
2042 * should thus unblock PUT operations that were blocked on the
2043 * monitor not being ready.
2046 monitor_unblock (struct ZoneMonitor *zm)
2048 struct StoreActivity *sa = sa_head;
2050 while ( (NULL != sa) &&
2051 (zm->limit > zm->iteration_cnt) )
2053 struct StoreActivity *sn = sa->next;
2055 if (sa->zm_pos == zm)
2056 continue_store_activity (sa);
2059 if (zm->limit > zm->iteration_cnt)
2061 zm->sa_waiting = GNUNET_NO;
2062 if (NULL != zm->sa_wait_warning)
2064 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2065 zm->sa_wait_warning = NULL;
2068 else if (GNUNET_YES == zm->sa_waiting)
2070 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2071 if (NULL != zm->sa_wait_warning)
2072 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2073 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2081 * Send 'sync' message to zone monitor, we're now in sync.
2083 * @param zm monitor that is now in sync
2086 monitor_sync (struct ZoneMonitor *zm)
2088 struct GNUNET_MQ_Envelope *env;
2089 struct GNUNET_MessageHeader *sync;
2091 env = GNUNET_MQ_msg (sync,
2092 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
2093 GNUNET_MQ_send (zm->nc->mq,
2095 /* mark iteration done */
2096 zm->in_first_iteration = GNUNET_NO;
2097 zm->iteration_cnt = 0;
2098 if ( (zm->limit > 0) &&
2100 monitor_unblock (zm);
2105 * Obtain the next datum during the zone monitor's zone initial iteration.
2107 * @param cls zone monitor that does its initial iteration
2110 monitor_iteration_next (void *cls);
2114 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2116 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2117 * @param seq sequence number of the record
2118 * @param zone_key zone key of the zone
2120 * @param rd_count number of records in @a rd
2121 * @param rd array of records
2124 monitor_iterate_cb (void *cls,
2126 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
2128 unsigned int rd_count,
2129 const struct GNUNET_GNSRECORD_Data *rd)
2131 struct ZoneMonitor *zm = cls;
2134 GNUNET_assert (NULL != name);
2135 GNUNET_STATISTICS_update (statistics,
2136 "Monitor notifications sent",
2140 zm->iteration_cnt--;
2141 send_lookup_response (zm->nc,
2147 if ( (0 == zm->iteration_cnt) &&
2150 /* We are done with the current iteration batch, AND the
2151 client would right now accept more, so go again! */
2152 GNUNET_assert (NULL == zm->task);
2153 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2160 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2162 * @param cls the client sending the message
2163 * @param zis_msg message from the client
2166 handle_monitor_start (void *cls,
2167 const struct ZoneMonitorStartMessage *zis_msg)
2169 struct NamestoreClient *nc = cls;
2170 struct ZoneMonitor *zm;
2172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2173 "Received ZONE_MONITOR_START message\n");
2174 zm = GNUNET_new (struct ZoneMonitor);
2176 zm->zone = zis_msg->zone;
2178 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2179 GNUNET_CONTAINER_DLL_insert (monitor_head,
2182 GNUNET_SERVICE_client_mark_monitor (nc->client);
2183 GNUNET_SERVICE_client_continue (nc->client);
2184 GNUNET_notification_context_add (monitor_nc,
2186 if (zm->in_first_iteration)
2187 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2195 * Obtain the next datum during the zone monitor's zone initial iteration.
2197 * @param cls zone monitor that does its initial iteration
2200 monitor_iteration_next (void *cls)
2202 struct ZoneMonitor *zm = cls;
2206 GNUNET_assert (0 == zm->iteration_cnt);
2208 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2210 zm->iteration_cnt = zm->limit; /* use it all */
2211 ret = GSN_database->iterate_records (GSN_database->cls,
2212 (0 == memcmp (&zm->zone,
2219 &monitor_iterate_cb,
2221 if (GNUNET_SYSERR == ret)
2223 GNUNET_SERVICE_client_drop (zm->nc->client);
2226 if (GNUNET_NO == ret)
2236 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2238 * @param cls the client sending the message
2239 * @param nm message from the client
2242 handle_monitor_next (void *cls,
2243 const struct ZoneMonitorNextMessage *nm)
2245 struct NamestoreClient *nc = cls;
2246 struct ZoneMonitor *zm;
2249 inc = GNUNET_ntohll (nm->limit);
2250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2251 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2252 (unsigned long long) inc);
2253 for (zm = monitor_head; NULL != zm; zm = zm->next)
2259 GNUNET_SERVICE_client_drop (nc->client);
2262 GNUNET_SERVICE_client_continue (nc->client);
2263 if (zm->limit + inc < zm->limit)
2266 GNUNET_SERVICE_client_drop (nc->client);
2270 if ( (zm->in_first_iteration) &&
2271 (zm->limit == inc) )
2273 /* We are still iterating, and the previous iteration must
2274 have stopped due to the client's limit, so continue it! */
2275 GNUNET_assert (NULL == zm->task);
2276 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2279 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2280 if ( (zm->limit > zm->iteration_cnt) &&
2283 monitor_unblock (zm);
2285 else if (GNUNET_YES == zm->sa_waiting)
2287 if (NULL != zm->sa_wait_warning)
2288 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2289 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2290 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2298 * Process namestore requests.
2300 * @param cls closure
2301 * @param cfg configuration to use
2302 * @param service the initialized service
2306 const struct GNUNET_CONFIGURATION_Handle *cfg,
2307 struct GNUNET_SERVICE_Handle *service)
2313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2314 "Starting namestore service\n");
2315 cache_keys = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2318 disable_namecache = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2322 monitor_nc = GNUNET_notification_context_create (1);
2323 if (GNUNET_YES != disable_namecache)
2325 namecache = GNUNET_NAMECACHE_connect (cfg);
2326 GNUNET_assert (NULL != namecache);
2328 /* Loading database plugin */
2330 GNUNET_CONFIGURATION_get_value_string (cfg,
2334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2335 "No database backend configured\n");
2337 GNUNET_asprintf (&db_lib_name,
2338 "libgnunet_plugin_namestore_%s",
2340 GSN_database = GNUNET_PLUGIN_load (db_lib_name,
2342 GNUNET_free (database);
2343 statistics = GNUNET_STATISTICS_create ("namestore",
2345 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
2347 if (NULL == GSN_database)
2349 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2350 "Could not load database backend `%s'\n",
2352 GNUNET_SCHEDULER_shutdown ();
2359 * Define "main" method using service macro.
2363 GNUNET_SERVICE_OPTION_NONE,
2366 &client_disconnect_cb,
2368 GNUNET_MQ_hd_var_size (record_store,
2369 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2370 struct RecordStoreMessage,
2372 GNUNET_MQ_hd_var_size (record_lookup,
2373 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2374 struct LabelLookupMessage,
2376 GNUNET_MQ_hd_fixed_size (zone_to_name,
2377 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2378 struct ZoneToNameMessage,
2380 GNUNET_MQ_hd_fixed_size (iteration_start,
2381 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2382 struct ZoneIterationStartMessage,
2384 GNUNET_MQ_hd_fixed_size (iteration_next,
2385 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2386 struct ZoneIterationNextMessage,
2388 GNUNET_MQ_hd_fixed_size (iteration_stop,
2389 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2390 struct ZoneIterationStopMessage,
2392 GNUNET_MQ_hd_fixed_size (monitor_start,
2393 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2394 struct ZoneMonitorStartMessage,
2396 GNUNET_MQ_hd_fixed_size (monitor_next,
2397 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2398 struct ZoneMonitorNextMessage,
2400 GNUNET_MQ_handler_end ());
2403 /* end of gnunet-service-namestore.c */