finish (?) libgnunetatstransport for now
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2014, 2018 GNUnet e.V.
4
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.
9
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.
14
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/>.
17 */
18
19 /**
20  * @file namestore/gnunet-service-namestore.c
21  * @brief namestore for the GNUnet naming system
22  * @author Matthias Wachs
23  * @author Christian Grothoff
24  *
25  * TODO:
26  * - run testcases, make sure everything works!
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_dnsparser_lib.h"
31 #include "gnunet_gns_service.h"
32 #include "gnunet_namecache_service.h"
33 #include "gnunet_namestore_service.h"
34 #include "gnunet_namestore_plugin.h"
35 #include "gnunet_statistics_service.h"
36 #include "gnunet_signatures.h"
37 #include "namestore.h"
38
39 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
40
41 /**
42  * If a monitor takes more than 1 minute to process an event, print a warning.
43  */
44 #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
45
46
47 /**
48  * A namestore client
49  */
50 struct NamestoreClient;
51
52
53 /**
54  * A namestore iteration operation.
55  */
56 struct ZoneIteration
57 {
58   /**
59    * Next element in the DLL
60    */
61   struct ZoneIteration *next;
62
63   /**
64    * Previous element in the DLL
65    */
66   struct ZoneIteration *prev;
67
68   /**
69    * Namestore client which intiated this zone iteration
70    */
71   struct NamestoreClient *nc;
72
73   /**
74    * The nick to add to the records
75    */
76   struct GNUNET_GNSRECORD_Data *nick;
77
78   /**
79    * Key of the zone we are iterating over.
80    */
81   struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
82
83   /**
84    * Last sequence number in the zone iteration used to address next
85    * result of the zone iteration in the store
86    *
87    * Initialy set to 0.
88    * Updated in #zone_iterate_proc()
89    */
90   uint64_t seq;
91
92   /**
93    * The operation id fot the zone iteration in the response for the client
94    */
95   uint32_t request_id;
96
97   /**
98    * Offset of the zone iteration used to address next result of the zone
99    * iteration in the store
100    *
101    * Initialy set to 0 in #handle_iteration_start
102    * Incremented with by every call to #handle_iteration_next
103    */
104   uint32_t offset;
105
106 };
107
108
109 /**
110  * A namestore client
111  */
112 struct NamestoreClient
113 {
114
115   /**
116    * The client
117    */
118   struct GNUNET_SERVICE_Client *client;
119
120   /**
121    * Message queue for transmission to @e client
122    */
123   struct GNUNET_MQ_Handle *mq;
124
125   /**
126    * Head of the DLL of
127    * Zone iteration operations in progress initiated by this client
128    */
129   struct ZoneIteration *op_head;
130
131   /**
132    * Tail of the DLL of
133    * Zone iteration operations in progress initiated by this client
134    */
135   struct ZoneIteration *op_tail;
136 };
137
138
139 /**
140  * A namestore monitor.
141  */
142 struct ZoneMonitor
143 {
144   /**
145    * Next element in the DLL
146    */
147   struct ZoneMonitor *next;
148
149   /**
150    * Previous element in the DLL
151    */
152   struct ZoneMonitor *prev;
153
154   /**
155    * Namestore client which intiated this zone monitor
156    */
157   struct NamestoreClient *nc;
158
159   /**
160    * Private key of the zone.
161    */
162   struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
163
164   /**
165    * Task active during initial iteration.
166    */
167   struct GNUNET_SCHEDULER_Task *task;
168
169   /**
170    * Task to warn about slow monitors.
171    */
172   struct GNUNET_SCHEDULER_Task *sa_wait_warning;
173
174   /**
175    * Since when are we blocked on this monitor?
176    */
177   struct GNUNET_TIME_Absolute sa_waiting_start;
178
179   /**
180    * Last sequence number in the zone iteration used to address next
181    * result of the zone iteration in the store
182    *
183    * Initialy set to 0.
184    * Updated in #monitor_iterate_cb()
185    */
186   uint64_t seq;
187
188   /**
189    * Current limit of how many more messages we are allowed
190    * to queue to this monitor.
191    */
192   uint64_t limit;
193
194   /**
195    * How many more requests may we receive from the iterator
196    * before it is at the limit we gave it?  Will be below or
197    * equal to @e limit.  The effective limit for monitor
198    * events is thus @e iteration_cnt - @e limit!
199    */
200   uint64_t iteration_cnt;
201
202   /**
203    * Are we (still) in the initial iteration pass?
204    */
205   int in_first_iteration;
206
207   /**
208    * Is there a store activity waiting for this monitor?  We only raise the
209    * flag when it happens and search the DLL for the store activity when we
210    * had a limit increase.  If we cannot find any waiting store activity at
211    * that time, we clear the flag again.
212    */
213   int sa_waiting;
214
215 };
216
217
218 /**
219  * Pending operation on the namecache.
220  */
221 struct CacheOperation
222 {
223
224   /**
225    * Kept in a DLL.
226    */
227   struct CacheOperation *prev;
228
229   /**
230    * Kept in a DLL.
231    */
232   struct CacheOperation *next;
233
234   /**
235    * Handle to namecache queue.
236    */
237   struct GNUNET_NAMECACHE_QueueEntry *qe;
238
239   /**
240    * Client to notify about the result.
241    */
242   struct NamestoreClient *nc;
243
244   /**
245    * Client's request ID.
246    */
247   uint32_t rid;
248 };
249
250
251 /**
252  * Information for an ongoing #handle_record_store() operation.
253  * Needed as we may wait for monitors to be ready for the notification.
254  */
255 struct StoreActivity
256 {
257   /**
258    * Kept in a DLL.
259    */
260   struct StoreActivity *next;
261
262   /**
263    * Kept in a DLL.
264    */
265   struct StoreActivity *prev;
266
267   /**
268    * Which client triggered the store activity?
269    */
270   struct NamestoreClient *nc;
271
272   /**
273    * Copy of the original store message (as data fields in @e rd will
274    * point into it!).
275    */
276   const struct RecordStoreMessage *rsm;
277
278   /**
279    * Next zone monitor that still needs to be notified about this PUT.
280    */
281   struct ZoneMonitor *zm_pos;
282
283   /**
284    * Label nicely canonicalized (lower case).
285    */
286   char *conv_name;
287
288 };
289
290
291 /**
292  * Public key of all zeros.
293  */
294 static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
295
296 /**
297  * Configuration handle.
298  */
299 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
300
301 /**
302  * Handle to the statistics service
303  */
304 static struct GNUNET_STATISTICS_Handle *statistics;
305
306 /**
307  * Namecache handle.
308  */
309 static struct GNUNET_NAMECACHE_Handle *namecache;
310
311 /**
312  * Database handle
313  */
314 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
315
316 /**
317  * Name of the database plugin
318  */
319 static char *db_lib_name;
320
321 /**
322  * Head of cop DLL.
323  */
324 static struct CacheOperation *cop_head;
325
326 /**
327  * Tail of cop DLL.
328  */
329 static struct CacheOperation *cop_tail;
330
331 /**
332  * First active zone monitor.
333  */
334 static struct ZoneMonitor *monitor_head;
335
336 /**
337  * Last active zone monitor.
338  */
339 static struct ZoneMonitor *monitor_tail;
340
341 /**
342  * Head of DLL of monitor-blocked store activities.
343  */
344 static struct StoreActivity *sa_head;
345
346 /**
347  * Tail of DLL of monitor-blocked store activities.
348  */
349 static struct StoreActivity *sa_tail;
350
351 /**
352  * Notification context shared by all monitors.
353  */
354 static struct GNUNET_NotificationContext *monitor_nc;
355
356 /**
357  * Optimize block insertion by caching map of private keys to
358  * public keys in memory?
359  */
360 static int cache_keys;
361
362 /**
363  * Use the namecache? Doing so creates additional cryptographic
364  * operations whenever we touch a record.
365  */
366 static int disable_namecache;
367
368
369 /**
370  * Task run during shutdown.
371  *
372  * @param cls unused
373  */
374 static void
375 cleanup_task (void *cls)
376 {
377   struct CacheOperation *cop;
378
379   (void) cls;
380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
381               "Stopping namestore service\n");
382   while (NULL != (cop = cop_head))
383   {
384     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
385                 "Aborting incomplete namecache operation\n");
386     GNUNET_NAMECACHE_cancel (cop->qe);
387     GNUNET_CONTAINER_DLL_remove (cop_head,
388                                  cop_tail,
389                                  cop);
390     GNUNET_free (cop);
391   }
392   if (NULL != namecache)
393   {
394     GNUNET_NAMECACHE_disconnect (namecache);
395     namecache = NULL;
396   }
397   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
398                                               GSN_database));
399   GNUNET_free (db_lib_name);
400   db_lib_name = NULL;
401   if (NULL != monitor_nc)
402   {
403     GNUNET_notification_context_destroy (monitor_nc);
404     monitor_nc = NULL;
405   }
406   if (NULL != statistics)
407   {
408     GNUNET_STATISTICS_destroy (statistics,
409                                GNUNET_NO);
410     statistics = NULL;
411   }
412 }
413
414
415 /**
416  * Release memory used by @a sa.
417  *
418  * @param sa activity to free
419  */
420 static void
421 free_store_activity (struct StoreActivity *sa)
422 {
423   GNUNET_CONTAINER_DLL_remove (sa_head,
424                                sa_tail,
425                                sa);
426   GNUNET_free (sa->conv_name);
427   GNUNET_free (sa);
428 }
429
430
431 /**
432  * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
433  * label in the zone.  Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
434  * record, which (if found) is then copied to @a cls for future use.
435  *
436  * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
437  * @param seq sequence number of the record
438  * @param private_key the private key of the zone (unused)
439  * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
440  * @param rd_count number of records in @a rd
441  * @param rd records stored under @a label in the zone
442  */
443 static void
444 lookup_nick_it (void *cls,
445                 uint64_t seq,
446                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
447                 const char *label,
448                 unsigned int rd_count,
449                 const struct GNUNET_GNSRECORD_Data *rd)
450 {
451   struct GNUNET_GNSRECORD_Data **res = cls;
452
453   (void) private_key;
454   (void) seq;
455   if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
456   {
457     GNUNET_break (0);
458     return;
459   }
460   for (unsigned int c = 0; c < rd_count; c++)
461   {
462     if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
463     {
464       (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data));
465       (*res)->data = &(*res)[1];
466       GNUNET_memcpy ((void *) (*res)->data,
467                      rd[c].data,
468                      rd[c].data_size);
469       (*res)->data_size = rd[c].data_size;
470       (*res)->expiration_time = rd[c].expiration_time;
471       (*res)->flags = rd[c].flags;
472       (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
473       return;
474     }
475   }
476   (*res) = NULL;
477 }
478
479
480 /**
481  * Return the NICK record for the zone (if it exists).
482  *
483  * @param zone private key for the zone to look for nick
484  * @return NULL if no NICK record was found
485  */
486 static struct GNUNET_GNSRECORD_Data *
487 get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone)
488 {
489   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
490   struct GNUNET_GNSRECORD_Data *nick;
491   int res;
492
493   nick = NULL;
494   res = GSN_database->lookup_records (GSN_database->cls,
495                                       zone,
496                                       GNUNET_GNS_EMPTY_LABEL_AT,
497                                       &lookup_nick_it,
498                                       &nick);
499   if ( (GNUNET_OK != res) ||
500        (NULL == nick) )
501   {
502     GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
503     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
504                 "No nick name set for zone `%s'\n",
505                 GNUNET_GNSRECORD_z2s (&pub));
506     return NULL;
507   }
508   return nick;
509 }
510
511
512 /**
513  * Merge the nick record @a nick_rd with the rest of the
514  * record set given in @a rd2.  Store the result in @a rdc_res
515  * and @a rd_res.  The @a nick_rd's expiration time is set to
516  * the maximum expiration time of all of the records in @a rd2.
517  *
518  * @param nick_rd the nick record to integrate
519  * @param rd2_length length of the @a rd2 array
520  * @param rd2 array of records
521  * @param rdc_res[out] length of the resulting @a rd_res array
522  * @param rd_res[out] set to an array of records,
523  *                    including @a nick_rd and @a rd2;
524  *           all of the variable-size 'data' fields in @a rd2 are
525  *           allocated in the same chunk of memory!
526  */
527 static void
528 merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
529                          unsigned int rd2_length,
530                          const struct GNUNET_GNSRECORD_Data *rd2,
531                          unsigned int *rdc_res,
532                          struct GNUNET_GNSRECORD_Data **rd_res)
533 {
534   uint64_t latest_expiration;
535   size_t req;
536   char *data;
537   size_t data_offset;
538   struct GNUNET_GNSRECORD_Data *target;
539
540   (*rdc_res) = 1 + rd2_length;
541   if (0 == 1 + rd2_length)
542   {
543     GNUNET_break (0);
544     (*rd_res) = NULL;
545     return;
546   }
547   req = sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
548   for (unsigned int i=0; i<rd2_length; i++)
549   {
550     const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
551
552     if (req + sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
553     {
554       GNUNET_break (0);
555       (*rd_res) = NULL;
556       return;
557     }
558     req += sizeof (struct GNUNET_GNSRECORD_Data) + orig->data_size;
559   }
560   target = GNUNET_malloc (req);
561   (*rd_res) = target;
562   data = (char *) &target[1 + rd2_length];
563   data_offset = 0;
564   latest_expiration = 0;
565   for (unsigned int i=0;i<rd2_length;i++)
566   {
567     const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
568
569     if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
570     {
571       if ((GNUNET_TIME_absolute_get().abs_value_us + orig->expiration_time) >
572           latest_expiration)
573         latest_expiration = orig->expiration_time;
574     }
575     else if (orig->expiration_time > latest_expiration)
576       latest_expiration = orig->expiration_time;
577     target[i] = *orig;
578     target[i].data = (void *) &data[data_offset];
579     GNUNET_memcpy (&data[data_offset],
580                    orig->data,
581                    orig->data_size);
582     data_offset += orig->data_size;
583   }
584   /* append nick */
585   target[rd2_length] = *nick_rd;
586   target[rd2_length].expiration_time = latest_expiration;
587   target[rd2_length].data = (void *) &data[data_offset];
588   GNUNET_memcpy (&data[data_offset],
589                  nick_rd->data,
590                  nick_rd->data_size);
591   data_offset += nick_rd->data_size;
592   GNUNET_assert (req ==
593                  (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
594 }
595
596
597 /**
598  * Generate a `struct LookupNameResponseMessage` and send it to the
599  * given client using the given notification context.
600  *
601  * @param nc client to unicast to
602  * @param request_id request ID to use
603  * @param zone_key zone key of the zone
604  * @param name name
605  * @param rd_count number of records in @a rd
606  * @param rd array of records
607  */
608 static void
609 send_lookup_response (struct NamestoreClient *nc,
610                       uint32_t request_id,
611                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
612                       const char *name,
613                       unsigned int rd_count,
614                       const struct GNUNET_GNSRECORD_Data *rd)
615 {
616   struct GNUNET_MQ_Envelope *env;
617   struct RecordResultMessage *zir_msg;
618   struct GNUNET_GNSRECORD_Data *nick;
619   struct GNUNET_GNSRECORD_Data *res;
620   unsigned int res_count;
621   size_t name_len;
622   ssize_t rd_ser_len;
623   char *name_tmp;
624   char *rd_ser;
625
626   nick = get_nick_record (zone_key);
627   GNUNET_assert (-1 !=
628                  GNUNET_GNSRECORD_records_get_size (rd_count,
629                                                     rd));
630
631   if ( (NULL != nick) &&
632        (0 != strcmp (name,
633                      GNUNET_GNS_EMPTY_LABEL_AT)))
634   {
635     nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
636     merge_with_nick_records (nick,
637                              rd_count,
638                              rd,
639                              &res_count,
640                              &res);
641     GNUNET_free (nick);
642   }
643   else
644   {
645     res_count = rd_count;
646     res = (struct GNUNET_GNSRECORD_Data *) rd;
647   }
648
649   GNUNET_assert (-1 !=
650                  GNUNET_GNSRECORD_records_get_size (res_count,
651                                                     res));
652
653
654   name_len = strlen (name) + 1;
655   rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count,
656                                                   res);
657   if (rd_ser_len < 0)
658   {
659     GNUNET_break (0);
660     GNUNET_SERVICE_client_drop (nc->client);
661     return;
662   }
663   if (rd_ser_len >= UINT16_MAX - name_len - sizeof (*zir_msg))
664   {
665     GNUNET_break (0);
666     GNUNET_SERVICE_client_drop (nc->client);
667     return;
668   }
669   env = GNUNET_MQ_msg_extra (zir_msg,
670                              name_len + rd_ser_len,
671                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
672   zir_msg->gns_header.r_id = htonl (request_id);
673   zir_msg->name_len = htons (name_len);
674   zir_msg->rd_count = htons (res_count);
675   zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
676   zir_msg->private_key = *zone_key;
677   name_tmp = (char *) &zir_msg[1];
678   GNUNET_memcpy (name_tmp,
679                  name,
680                  name_len);
681   rd_ser = &name_tmp[name_len];
682   GNUNET_assert (rd_ser_len ==
683                  GNUNET_GNSRECORD_records_serialize (res_count,
684                                                      res,
685                                                      rd_ser_len,
686                                                      rd_ser));
687   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
688               "Sending RECORD_RESULT message with %u records\n",
689               res_count);
690   GNUNET_STATISTICS_update (statistics,
691                             "Record sets sent to clients",
692                             1,
693                             GNUNET_NO);
694   GNUNET_MQ_send (nc->mq,
695                   env);
696   if (rd != res)
697     GNUNET_free (res);
698 }
699
700
701 /**
702  * Send response to the store request to the client.
703  *
704  * @param client client to talk to
705  * @param res status of the operation
706  * @param rid client's request ID
707  */
708 static void
709 send_store_response (struct NamestoreClient *nc,
710                      int res,
711                      uint32_t rid)
712 {
713   struct GNUNET_MQ_Envelope *env;
714   struct RecordStoreResponseMessage *rcr_msg;
715
716   GNUNET_assert (NULL != nc);
717   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718               "Sending RECORD_STORE_RESPONSE message\n");
719   GNUNET_STATISTICS_update (statistics,
720                             "Store requests completed",
721                             1,
722                             GNUNET_NO);
723   env = GNUNET_MQ_msg (rcr_msg,
724                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
725   rcr_msg->gns_header.r_id = htonl (rid);
726   rcr_msg->op_result = htonl (res);
727   GNUNET_MQ_send (nc->mq,
728                   env);
729 }
730
731
732 /**
733  * Cache operation complete, clean up.
734  *
735  * @param cls the `struct CacheOperation`
736  * @param success success
737  * @param emsg error messages
738  */
739 static void
740 finish_cache_operation (void *cls,
741                         int32_t success,
742                         const char *emsg)
743 {
744   struct CacheOperation *cop = cls;
745
746   if (NULL != emsg)
747     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
748                 _("Failed to replicate block in namecache: %s\n"),
749                 emsg);
750   else
751     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
752                 "CACHE operation completed\n");
753   GNUNET_CONTAINER_DLL_remove (cop_head,
754                                cop_tail,
755                                cop);
756   if (NULL != cop->nc)
757     send_store_response (cop->nc,
758                          success,
759                          cop->rid);
760   GNUNET_free (cop);
761 }
762
763
764 /**
765  * We just touched the plaintext information about a name in our zone;
766  * refresh the corresponding (encrypted) block in the namecache.
767  *
768  * @param nc client responsible for the request, can be NULL
769  * @param rid request ID of the client
770  * @param zone_key private key of the zone
771  * @param name label for the records
772  * @param rd_count number of records
773  * @param rd records stored under the given @a name
774  */
775 static void
776 refresh_block (struct NamestoreClient *nc,
777                uint32_t rid,
778                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
779                const char *name,
780                unsigned int rd_count,
781                const struct GNUNET_GNSRECORD_Data *rd)
782 {
783   struct GNUNET_GNSRECORD_Block *block;
784   struct CacheOperation *cop;
785   struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
786   struct GNUNET_GNSRECORD_Data *nick;
787   struct GNUNET_GNSRECORD_Data *res;
788   unsigned int res_count;
789   struct GNUNET_TIME_Absolute exp_time;
790
791   nick = get_nick_record (zone_key);
792   res_count = rd_count;
793   res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
794   if (NULL != nick)
795   {
796     nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
797     merge_with_nick_records (nick,
798                              rd_count,rd,
799                              &res_count,
800                              &res);
801     GNUNET_free (nick);
802   }
803   if (0 == res_count)
804   {
805     if (NULL != nc)
806       send_store_response (nc,
807                            GNUNET_OK,
808                            rid);
809     return; /* no data, no need to update cache */
810   }
811   if (GNUNET_YES == disable_namecache)
812   {
813     GNUNET_STATISTICS_update (statistics,
814                               "Namecache updates skipped (NC disabled)",
815                               1,
816                               GNUNET_NO);
817     if (NULL != nc)
818       send_store_response (nc,
819                            GNUNET_OK,
820                            rid);
821     return;
822   }
823   exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count,
824                                                           res);
825   if (cache_keys)
826     block = GNUNET_GNSRECORD_block_create2 (zone_key,
827                                             exp_time,
828                                             name,
829                                             res,
830                                             res_count);
831   else
832     block = GNUNET_GNSRECORD_block_create (zone_key,
833                                            exp_time,
834                                            name,
835                                            res,
836                                            res_count);
837   GNUNET_assert (NULL != block);
838   GNUNET_CRYPTO_ecdsa_key_get_public (zone_key,
839                                       &pkey);
840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841               "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
842               name,
843               res_count,
844               GNUNET_STRINGS_absolute_time_to_string (exp_time),
845               GNUNET_GNSRECORD_z2s (&pkey));
846   GNUNET_STATISTICS_update (statistics,
847                             "Namecache updates pushed",
848                             1,
849                             GNUNET_NO);
850   cop = GNUNET_new (struct CacheOperation);
851   cop->nc = nc;
852   cop->rid = rid;
853   GNUNET_CONTAINER_DLL_insert (cop_head,
854                                cop_tail,
855                                cop);
856   cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
857                                           block,
858                                           &finish_cache_operation,
859                                           cop);
860   GNUNET_free (block);
861 }
862
863
864 /**
865  * Print a warning that one of our monitors is no longer reacting.
866  *
867  * @param cls a `struct ZoneMonitor` to warn about
868  */
869 static void
870 warn_monitor_slow (void *cls)
871 {
872   struct ZoneMonitor *zm = cls;
873
874   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
875               "No response from monitor since %s\n",
876               GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
877   zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
878                                                       &warn_monitor_slow,
879                                                       zm);
880 }
881
882
883 /**
884  * Continue processing the @a sa.
885  *
886  * @param sa store activity to process
887  */
888 static void
889 continue_store_activity (struct StoreActivity *sa)
890 {
891   const struct RecordStoreMessage *rp_msg = sa->rsm;
892   unsigned int rd_count;
893   size_t name_len;
894   size_t rd_ser_len;
895   uint32_t rid;
896   const char *name_tmp;
897   const char *rd_ser;
898
899   rid = ntohl (rp_msg->gns_header.r_id);
900   name_len = ntohs (rp_msg->name_len);
901   rd_count = ntohs (rp_msg->rd_count);
902   rd_ser_len = ntohs (rp_msg->rd_len);
903   name_tmp = (const char *) &rp_msg[1];
904   rd_ser = &name_tmp[name_len];
905   {
906     struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
907
908     /* We did this before, must succeed again */
909     GNUNET_assert (GNUNET_OK ==
910                    GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
911                                                          rd_ser,
912                                                          rd_count,
913                                                          rd));
914
915     for (struct ZoneMonitor *zm = sa->zm_pos;
916          NULL != zm;
917          zm = sa->zm_pos)
918     {
919       if ( (0 != memcmp (&rp_msg->private_key,
920                          &zm->zone,
921                          sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
922            (0 != memcmp (&zm->zone,
923                          &zero,
924                          sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
925         {
926           sa->zm_pos = zm->next; /* not interesting to this monitor */
927           continue;
928         }
929       if (zm->limit == zm->iteration_cnt)
930       {
931         zm->sa_waiting = GNUNET_YES;
932         zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
933         if (NULL != zm->sa_wait_warning)
934           GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
935         zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
936                                                             &warn_monitor_slow,
937                                                             zm);
938         return; /* blocked on zone monitor */
939       }
940       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
941                   "Notifying monitor about changes under label `%s'\n",
942                   sa->conv_name);
943       zm->limit--;
944       send_lookup_response (zm->nc,
945                             0,
946                             &rp_msg->private_key,
947                             sa->conv_name,
948                             rd_count,
949                             rd);
950       sa->zm_pos = zm->next;
951     }
952     /* great, done with the monitors, unpack (again) for refresh_block operation */
953     refresh_block (sa->nc,
954                    rid,
955                    &rp_msg->private_key,
956                    sa->conv_name,
957                    rd_count,
958                    rd);
959   }
960   GNUNET_SERVICE_client_continue (sa->nc->client);
961   free_store_activity (sa);
962 }
963
964
965 /**
966  * Called whenever a client is disconnected.
967  * Frees our resources associated with that client.
968  *
969  * @param cls closure
970  * @param client identification of the client
971  * @param app_ctx the `struct NamestoreClient` of @a client
972  */
973 static void
974 client_disconnect_cb (void *cls,
975                       struct GNUNET_SERVICE_Client *client,
976                       void *app_ctx)
977 {
978   struct NamestoreClient *nc = app_ctx;
979   struct ZoneIteration *no;
980   struct CacheOperation *cop;
981
982   (void) cls;
983   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984               "Client %p disconnected\n",
985               client);
986   for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
987   {
988     struct StoreActivity *san;
989
990     if (nc != zm->nc)
991       continue;
992     GNUNET_CONTAINER_DLL_remove (monitor_head,
993                                  monitor_tail,
994                                  zm);
995     if (NULL != zm->task)
996     {
997       GNUNET_SCHEDULER_cancel (zm->task);
998       zm->task = NULL;
999     }
1000     if (NULL != zm->sa_wait_warning)
1001     {
1002       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1003       zm->sa_wait_warning = NULL;
1004     }
1005     for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1006     {
1007       san = sa->next;
1008       if (zm == sa->zm_pos)
1009       {
1010         sa->zm_pos = zm->next;
1011         /* this may free sa */
1012         continue_store_activity (sa);
1013       }
1014     }
1015     GNUNET_free (zm);
1016     break;
1017   }
1018   for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1019   {
1020     if (sa->nc == nc)
1021     {
1022       /* this may free sa */
1023       free_store_activity (sa);
1024       break; /* there can only be one per nc */
1025     }
1026   }
1027   while (NULL != (no = nc->op_head))
1028   {
1029     GNUNET_CONTAINER_DLL_remove (nc->op_head,
1030                                  nc->op_tail,
1031                                  no);
1032     GNUNET_free (no);
1033   }
1034   for (cop = cop_head; NULL != cop; cop = cop->next)
1035     if (nc == cop->nc)
1036       cop->nc = NULL;
1037   GNUNET_free (nc);
1038 }
1039
1040
1041 /**
1042  * Add a client to our list of active clients.
1043  *
1044  * @param cls NULL
1045  * @param client client to add
1046  * @param mq message queue for @a client
1047  * @return internal namestore client structure for this client
1048  */
1049 static void *
1050 client_connect_cb (void *cls,
1051                    struct GNUNET_SERVICE_Client *client,
1052                    struct GNUNET_MQ_Handle *mq)
1053 {
1054   struct NamestoreClient *nc;
1055
1056   (void) cls;
1057   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1058               "Client %p connected\n",
1059               client);
1060   nc = GNUNET_new (struct NamestoreClient);
1061   nc->client = client;
1062   nc->mq = mq;
1063   return nc;
1064 }
1065
1066
1067 /**
1068  * Closure for #lookup_it().
1069  */
1070 struct RecordLookupContext
1071 {
1072
1073   /**
1074    * FIXME.
1075    */
1076   const char *label;
1077
1078   /**
1079    * FIXME.
1080    */
1081   char *res_rd;
1082
1083   /**
1084    * FIXME.
1085    */
1086   struct GNUNET_GNSRECORD_Data *nick;
1087
1088   /**
1089    * FIXME.
1090    */
1091   int found;
1092
1093   /**
1094    * FIXME.
1095    */
1096   unsigned int res_rd_count;
1097
1098   /**
1099    * FIXME.
1100    */
1101   ssize_t rd_ser_len;
1102 };
1103
1104
1105 /**
1106  * FIXME.
1107  *
1108  * @param seq sequence number of the record
1109  */
1110 static void
1111 lookup_it (void *cls,
1112            uint64_t seq,
1113            const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
1114            const char *label,
1115            unsigned int rd_count,
1116            const struct GNUNET_GNSRECORD_Data *rd)
1117 {
1118   struct RecordLookupContext *rlc = cls;
1119
1120   (void) private_key;
1121   (void) seq;
1122   if (0 != strcmp (label,
1123                    rlc->label))
1124     return;
1125   rlc->found = GNUNET_YES;
1126   if (0 == rd_count)
1127   {
1128     rlc->rd_ser_len = 0;
1129     rlc->res_rd_count = 0;
1130     rlc->res_rd = NULL;
1131     return;
1132   }
1133   if ( (NULL != rlc->nick) &&
1134        (0 != strcmp (label,
1135                      GNUNET_GNS_EMPTY_LABEL_AT)) )
1136   {
1137     /* Merge */
1138     struct GNUNET_GNSRECORD_Data *rd_res;
1139     unsigned int rdc_res;
1140
1141     rd_res = NULL;
1142     rdc_res = 0;
1143     rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
1144     merge_with_nick_records (rlc->nick,
1145                              rd_count,
1146                              rd,
1147                              &rdc_res,
1148                              &rd_res);
1149     rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
1150                                                          rd_res);
1151     if (rlc->rd_ser_len < 0)
1152     {
1153       GNUNET_break (0);
1154       GNUNET_free  (rd_res);
1155       rlc->found = GNUNET_NO;
1156       rlc->rd_ser_len = 0;
1157       return;
1158     }
1159     rlc->res_rd_count = rdc_res;
1160     rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1161     if (rlc->rd_ser_len !=
1162         GNUNET_GNSRECORD_records_serialize (rdc_res,
1163                                             rd_res,
1164                                             rlc->rd_ser_len,
1165                                             rlc->res_rd))
1166     {
1167       GNUNET_break (0);
1168       GNUNET_free  (rlc->res_rd);
1169       rlc->res_rd = NULL;
1170       rlc->res_rd_count = 0;
1171       rlc->rd_ser_len = 0;
1172       GNUNET_free  (rd_res);
1173       rlc->found = GNUNET_NO;
1174       return;
1175     }
1176     GNUNET_free (rd_res);
1177     GNUNET_free (rlc->nick);
1178     rlc->nick = NULL;
1179   }
1180   else
1181   {
1182     rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1183                                                          rd);
1184     if (rlc->rd_ser_len < 0)
1185     {
1186       GNUNET_break (0);
1187       rlc->found = GNUNET_NO;
1188       rlc->rd_ser_len = 0;
1189       return;
1190     }
1191     rlc->res_rd_count = rd_count;
1192     rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1193     if (rlc->rd_ser_len !=
1194         GNUNET_GNSRECORD_records_serialize (rd_count,
1195                                             rd,
1196                                             rlc->rd_ser_len,
1197                                             rlc->res_rd))
1198     {
1199       GNUNET_break (0);
1200       GNUNET_free  (rlc->res_rd);
1201       rlc->res_rd = NULL;
1202       rlc->res_rd_count = 0;
1203       rlc->rd_ser_len = 0;
1204       rlc->found = GNUNET_NO;
1205       return;
1206     }
1207   }
1208 }
1209
1210
1211 /**
1212  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1213  *
1214  * @param cls client sending the message
1215  * @param ll_msg message of type `struct LabelLookupMessage`
1216  * @return #GNUNET_OK if @a ll_msg is well-formed
1217  */
1218 static int
1219 check_record_lookup (void *cls,
1220                      const struct LabelLookupMessage *ll_msg)
1221 {
1222   uint32_t name_len;
1223   size_t src_size;
1224
1225   (void) cls;
1226   name_len = ntohl (ll_msg->label_len);
1227   src_size = ntohs (ll_msg->gns_header.header.size);
1228   if (name_len != src_size - sizeof (struct LabelLookupMessage))
1229   {
1230     GNUNET_break (0);
1231     return GNUNET_SYSERR;
1232   }
1233   GNUNET_MQ_check_zero_termination (ll_msg);
1234   return GNUNET_OK;
1235 }
1236
1237
1238 /**
1239  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1240  *
1241  * @param cls client sending the message
1242  * @param ll_msg message of type `struct LabelLookupMessage`
1243  */
1244 static void
1245 handle_record_lookup (void *cls,
1246                       const struct LabelLookupMessage *ll_msg)
1247 {
1248   struct NamestoreClient *nc = cls;
1249   struct GNUNET_MQ_Envelope *env;
1250   struct LabelLookupResponseMessage *llr_msg;
1251   struct RecordLookupContext rlc;
1252   const char *name_tmp;
1253   char *res_name;
1254   char *conv_name;
1255   uint32_t name_len;
1256   int res;
1257
1258   name_len = ntohl (ll_msg->label_len);
1259   name_tmp = (const char *) &ll_msg[1];
1260   GNUNET_SERVICE_client_continue (nc->client);
1261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262               "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1263               name_tmp);
1264
1265   conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1266   if (NULL == conv_name)
1267   {
1268     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1269                 "Error converting name `%s'\n",
1270                 name_tmp);
1271     GNUNET_SERVICE_client_drop (nc->client);
1272     return;
1273   }
1274   rlc.label = conv_name;
1275   rlc.found = GNUNET_NO;
1276   rlc.res_rd_count = 0;
1277   rlc.res_rd = NULL;
1278   rlc.rd_ser_len = 0;
1279   rlc.nick = get_nick_record (&ll_msg->zone);
1280   res = GSN_database->lookup_records (GSN_database->cls,
1281                                       &ll_msg->zone,
1282                                       conv_name,
1283                                       &lookup_it,
1284                                       &rlc);
1285   GNUNET_free (conv_name);
1286   env = GNUNET_MQ_msg_extra (llr_msg,
1287                              name_len + rlc.rd_ser_len,
1288                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1289   llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1290   llr_msg->private_key = ll_msg->zone;
1291   llr_msg->name_len = htons (name_len);
1292   llr_msg->rd_count = htons (rlc.res_rd_count);
1293   llr_msg->rd_len = htons (rlc.rd_ser_len);
1294   res_name = (char *) &llr_msg[1];
1295   if  ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1296     llr_msg->found = ntohs (GNUNET_YES);
1297   else
1298     llr_msg->found = ntohs (GNUNET_NO);
1299   GNUNET_memcpy (&llr_msg[1],
1300                  name_tmp,
1301                  name_len);
1302   GNUNET_memcpy (&res_name[name_len],
1303                  rlc.res_rd,
1304                  rlc.rd_ser_len);
1305   GNUNET_MQ_send (nc->mq,
1306                   env);
1307   GNUNET_free_non_null (rlc.res_rd);
1308 }
1309
1310
1311 /**
1312  * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1313  *
1314  * @param cls client sending the message
1315  * @param rp_msg message of type `struct RecordStoreMessage`
1316  * @return #GNUNET_OK if @a rp_msg is well-formed
1317  */
1318 static int
1319 check_record_store (void *cls,
1320                     const struct RecordStoreMessage *rp_msg)
1321 {
1322   size_t name_len;
1323   size_t msg_size;
1324   size_t msg_size_exp;
1325   size_t rd_ser_len;
1326   const char *name_tmp;
1327
1328   (void) cls;
1329   name_len = ntohs (rp_msg->name_len);
1330   msg_size = ntohs (rp_msg->gns_header.header.size);
1331   rd_ser_len = ntohs (rp_msg->rd_len);
1332   msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
1333   if (msg_size != msg_size_exp)
1334   {
1335     GNUNET_break (0);
1336     return GNUNET_SYSERR;
1337   }
1338   if ( (0 == name_len) ||
1339        (name_len > MAX_NAME_LEN) )
1340   {
1341     GNUNET_break (0);
1342     return GNUNET_SYSERR;
1343   }
1344   name_tmp = (const char *) &rp_msg[1];
1345   if ('\0' != name_tmp[name_len -1])
1346   {
1347     GNUNET_break (0);
1348     return GNUNET_SYSERR;
1349   }
1350   return GNUNET_OK;
1351 }
1352
1353
1354 /**
1355  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1356  *
1357  * @param cls client sending the message
1358  * @param rp_msg message of type `struct RecordStoreMessage`
1359  */
1360 static void
1361 handle_record_store (void *cls,
1362                      const struct RecordStoreMessage *rp_msg)
1363 {
1364   struct NamestoreClient *nc = cls;
1365   size_t name_len;
1366   size_t rd_ser_len;
1367   uint32_t rid;
1368   const char *name_tmp;
1369   char *conv_name;
1370   const char *rd_ser;
1371   unsigned int rd_count;
1372   int res;
1373   struct StoreActivity *sa;
1374
1375   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1376               "Received NAMESTORE_RECORD_STORE message\n");
1377   rid = ntohl (rp_msg->gns_header.r_id);
1378   name_len = ntohs (rp_msg->name_len);
1379   rd_count = ntohs (rp_msg->rd_count);
1380   rd_ser_len = ntohs (rp_msg->rd_len);
1381   GNUNET_break (0 == ntohs (rp_msg->reserved));
1382   name_tmp = (const char *) &rp_msg[1];
1383   rd_ser = &name_tmp[name_len];
1384   {
1385     struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1386
1387     if (GNUNET_OK !=
1388         GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
1389                                               rd_ser,
1390                                               rd_count,
1391                                               rd))
1392     {
1393       GNUNET_break (0);
1394       GNUNET_SERVICE_client_drop (nc->client);
1395       return;
1396     }
1397
1398     /* Extracting and converting private key */
1399     conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1400     if (NULL == conv_name)
1401     {
1402       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1403                   "Error converting name `%s'\n",
1404                   name_tmp);
1405       GNUNET_SERVICE_client_drop (nc->client);
1406       return;
1407     }
1408     GNUNET_STATISTICS_update (statistics,
1409                               "Well-formed store requests received",
1410                               1,
1411                               GNUNET_NO);
1412     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413                 "Creating %u records for name `%s'\n",
1414                 (unsigned int) rd_count,
1415                 conv_name);
1416     if ( (0 == rd_count) &&
1417          (GNUNET_NO ==
1418           GSN_database->lookup_records (GSN_database->cls,
1419                                         &rp_msg->private_key,
1420                                         conv_name,
1421                                         NULL,
1422                                         0)) )
1423     {
1424       /* This name does not exist, so cannot be removed */
1425       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1426                   "Name `%s' does not exist, no deletion required\n",
1427                   conv_name);
1428       res = GNUNET_NO;
1429     }
1430     else
1431     {
1432       /* remove "NICK" records, unless this is for the
1433          #GNUNET_GNS_EMPTY_LABEL_AT label */
1434       struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1435       unsigned int rd_clean_off;
1436
1437       rd_clean_off = 0;
1438       for (unsigned int i=0;i<rd_count;i++)
1439       {
1440         rd_clean[rd_clean_off] = rd[i];
1441         if ( (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT,
1442                            conv_name)) ||
1443              (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type) )
1444           rd_clean_off++;
1445       }
1446       res = GSN_database->store_records (GSN_database->cls,
1447                                          &rp_msg->private_key,
1448                                          conv_name,
1449                                          rd_clean_off,
1450                                          rd_clean);
1451     }
1452
1453     if (GNUNET_OK != res)
1454     {
1455       /* store not successful, not need to tell monitors */
1456       send_store_response (nc,
1457                            res,
1458                            rid);
1459       GNUNET_SERVICE_client_continue (nc->client);
1460       GNUNET_free (conv_name);
1461       return;
1462     }
1463
1464     sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1465                         ntohs (rp_msg->gns_header.header.size));
1466     GNUNET_CONTAINER_DLL_insert (sa_head,
1467                                  sa_tail,
1468                                  sa);
1469     sa->nc = nc;
1470     sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1471     GNUNET_memcpy (&sa[1],
1472                    rp_msg,
1473                    ntohs (rp_msg->gns_header.header.size));
1474     sa->zm_pos = monitor_head;
1475     sa->conv_name = conv_name;
1476     continue_store_activity (sa);
1477   }
1478 }
1479
1480
1481 /**
1482  * Context for record remove operations passed from #handle_zone_to_name to
1483  * #handle_zone_to_name_it as closure
1484  */
1485 struct ZoneToNameCtx
1486 {
1487   /**
1488    * Namestore client
1489    */
1490   struct NamestoreClient *nc;
1491
1492   /**
1493    * Request id (to be used in the response to the client).
1494    */
1495   uint32_t rid;
1496
1497   /**
1498    * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error.  Note that
1499    * not finding a name for the zone still counts as a 'success' here,
1500    * as this field is about the success of executing the IPC protocol.
1501    */
1502   int success;
1503 };
1504
1505
1506 /**
1507  * Zone to name iterator
1508  *
1509  * @param cls struct ZoneToNameCtx *
1510  * @param seq sequence number of the record
1511  * @param zone_key the zone key
1512  * @param name name
1513  * @param rd_count number of records in @a rd
1514  * @param rd record data
1515  */
1516 static void
1517 handle_zone_to_name_it (void *cls,
1518                         uint64_t seq,
1519                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1520                         const char *name,
1521                         unsigned int rd_count,
1522                         const struct GNUNET_GNSRECORD_Data *rd)
1523 {
1524   struct ZoneToNameCtx *ztn_ctx = cls;
1525   struct GNUNET_MQ_Envelope *env;
1526   struct ZoneToNameResponseMessage *ztnr_msg;
1527   int16_t res;
1528   size_t name_len;
1529   ssize_t rd_ser_len;
1530   size_t msg_size;
1531   char *name_tmp;
1532   char *rd_tmp;
1533
1534   (void) seq;
1535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536               "Found result for zone-to-name lookup: `%s'\n",
1537               name);
1538   res = GNUNET_YES;
1539   name_len = (NULL == name) ? 0 : strlen (name) + 1;
1540   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1541                                                   rd);
1542   if (rd_ser_len < 0)
1543   {
1544     GNUNET_break (0);
1545     ztn_ctx->success = GNUNET_SYSERR;
1546     return;
1547   }
1548   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1549   if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1550   {
1551     GNUNET_break (0);
1552     ztn_ctx->success = GNUNET_SYSERR;
1553     return;
1554   }
1555   env = GNUNET_MQ_msg_extra (ztnr_msg,
1556                              name_len + rd_ser_len,
1557                              GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1558   ztnr_msg->gns_header.header.size = htons (msg_size);
1559   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1560   ztnr_msg->res = htons (res);
1561   ztnr_msg->rd_len = htons (rd_ser_len);
1562   ztnr_msg->rd_count = htons (rd_count);
1563   ztnr_msg->name_len = htons (name_len);
1564   ztnr_msg->zone = *zone_key;
1565   name_tmp = (char *) &ztnr_msg[1];
1566   GNUNET_memcpy (name_tmp,
1567                  name,
1568                  name_len);
1569   rd_tmp = &name_tmp[name_len];
1570   GNUNET_assert (rd_ser_len ==
1571                  GNUNET_GNSRECORD_records_serialize (rd_count,
1572                                                      rd,
1573                                                      rd_ser_len,
1574                                                      rd_tmp));
1575   ztn_ctx->success = GNUNET_OK;
1576   GNUNET_MQ_send (ztn_ctx->nc->mq,
1577                   env);
1578 }
1579
1580
1581 /**
1582  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1583  *
1584  * @param cls client client sending the message
1585  * @param ztn_msg message of type 'struct ZoneToNameMessage'
1586  */
1587 static void
1588 handle_zone_to_name (void *cls,
1589                      const struct ZoneToNameMessage *ztn_msg)
1590 {
1591   struct NamestoreClient *nc = cls;
1592   struct ZoneToNameCtx ztn_ctx;
1593   struct GNUNET_MQ_Envelope *env;
1594   struct ZoneToNameResponseMessage *ztnr_msg;
1595
1596   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1597               "Received ZONE_TO_NAME message\n");
1598   ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1599   ztn_ctx.nc = nc;
1600   ztn_ctx.success = GNUNET_NO;
1601   if (GNUNET_SYSERR ==
1602       GSN_database->zone_to_name (GSN_database->cls,
1603                                   &ztn_msg->zone,
1604                                   &ztn_msg->value_zone,
1605                                   &handle_zone_to_name_it, &ztn_ctx))
1606   {
1607     /* internal error, hang up instead of signalling something
1608        that might be wrong */
1609     GNUNET_break (0);
1610     GNUNET_SERVICE_client_drop (nc->client);
1611     return;
1612   }
1613   if (GNUNET_NO == ztn_ctx.success)
1614   {
1615     /* no result found, send empty response */
1616     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1617                 "Found no result for zone-to-name lookup.\n");
1618     env = GNUNET_MQ_msg (ztnr_msg,
1619                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1620     ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1621     ztnr_msg->res = htons (GNUNET_NO);
1622     GNUNET_MQ_send (nc->mq,
1623                     env);
1624   }
1625   GNUNET_SERVICE_client_continue (nc->client);
1626 }
1627
1628
1629 /**
1630  * Context for record remove operations passed from
1631  * #run_zone_iteration_round to #zone_iterate_proc as closure
1632  */
1633 struct ZoneIterationProcResult
1634 {
1635   /**
1636    * The zone iteration handle
1637    */
1638   struct ZoneIteration *zi;
1639
1640   /**
1641    * Number of results left to be returned in this iteration.
1642    */
1643   uint64_t limit;
1644
1645 };
1646
1647
1648 /**
1649  * Process results for zone iteration from database
1650  *
1651  * @param cls struct ZoneIterationProcResult
1652  * @param seq sequence number of the record
1653  * @param zone_key the zone key
1654  * @param name name
1655  * @param rd_count number of records for this name
1656  * @param rd record data
1657  */
1658 static void
1659 zone_iterate_proc (void *cls,
1660                    uint64_t seq,
1661                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1662                    const char *name,
1663                    unsigned int rd_count,
1664                    const struct GNUNET_GNSRECORD_Data *rd)
1665 {
1666   struct ZoneIterationProcResult *proc = cls;
1667   int do_refresh_block;
1668
1669   if ( (NULL == zone_key) &&
1670        (NULL == name) )
1671   {
1672     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1673                 "Iteration done\n");
1674     return;
1675   }
1676   if ( (NULL == zone_key) ||
1677        (NULL == name) )
1678   {
1679     /* what is this!? should never happen */
1680     GNUNET_break (0);
1681     return;
1682   }
1683   if (0 == proc->limit)
1684   {
1685     /* what is this!? should never happen */
1686     GNUNET_break (0);
1687     return;
1688   }
1689   proc->limit--;
1690   proc->zi->seq = seq;
1691   send_lookup_response (proc->zi->nc,
1692                         proc->zi->request_id,
1693                         zone_key,
1694                         name,
1695                         rd_count,
1696                         rd);
1697
1698
1699   do_refresh_block = GNUNET_NO;
1700   for (unsigned int i=0;i<rd_count;i++)
1701     if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1702     {
1703       do_refresh_block = GNUNET_YES;
1704       break;
1705     }
1706   if (GNUNET_YES == do_refresh_block)
1707     refresh_block (NULL,
1708                    0,
1709                    zone_key,
1710                    name,
1711                    rd_count,
1712                    rd);
1713 }
1714
1715
1716 /**
1717  * Perform the next round of the zone iteration.
1718  *
1719  * @param zi zone iterator to process
1720  * @param limit number of results to return in one pass
1721  */
1722 static void
1723 run_zone_iteration_round (struct ZoneIteration *zi,
1724                           uint64_t limit)
1725 {
1726   struct ZoneIterationProcResult proc;
1727   struct GNUNET_MQ_Envelope *env;
1728   struct GNUNET_NAMESTORE_Header *em;
1729   struct GNUNET_TIME_Absolute start;
1730   struct GNUNET_TIME_Relative duration;
1731
1732   memset (&proc,
1733           0,
1734           sizeof (proc));
1735   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1736               "Asked to return up to %llu records at position %llu\n",
1737               (unsigned long long) limit,
1738               (unsigned long long) zi->seq);
1739   proc.zi = zi;
1740   proc.limit = limit;
1741   start = GNUNET_TIME_absolute_get ();
1742   GNUNET_break (GNUNET_SYSERR !=
1743                 GSN_database->iterate_records (GSN_database->cls,
1744                                                (0 == memcmp (&zi->zone,
1745                                                              &zero,
1746                                                              sizeof (zero)))
1747                                                ? NULL
1748                                                : &zi->zone,
1749                                                zi->seq,
1750                                                limit,
1751                                                &zone_iterate_proc,
1752                                                &proc));
1753   duration = GNUNET_TIME_absolute_get_duration (start);
1754   duration = GNUNET_TIME_relative_divide (duration,
1755                                           limit - proc.limit);
1756   GNUNET_STATISTICS_set (statistics,
1757                          "NAMESTORE iteration delay (μs/record)",
1758                          duration.rel_value_us,
1759                          GNUNET_NO);
1760   if (0 == proc.limit)
1761   {
1762     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1763                 "Returned %llu results, more results available\n",
1764                 (unsigned long long) limit);
1765     return; /* more results later after we get the
1766                #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message */
1767   }
1768   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1769               "Completed iteration after %llu/%llu results\n",
1770               (unsigned long long) (limit - proc.limit),
1771               (unsigned long long) limit);
1772   /* send empty response to indicate end of list */
1773   env = GNUNET_MQ_msg (em,
1774                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
1775   em->r_id = htonl (zi->request_id);
1776   GNUNET_MQ_send (zi->nc->mq,
1777                   env);
1778   GNUNET_CONTAINER_DLL_remove (zi->nc->op_head,
1779                                zi->nc->op_tail,
1780                                zi);
1781   GNUNET_free (zi);
1782 }
1783
1784
1785 /**
1786  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1787  *
1788  * @param cls the client sending the message
1789  * @param zis_msg message from the client
1790  */
1791 static void
1792 handle_iteration_start (void *cls,
1793                         const struct ZoneIterationStartMessage *zis_msg)
1794 {
1795   struct NamestoreClient *nc = cls;
1796   struct ZoneIteration *zi;
1797
1798   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1799               "Received ZONE_ITERATION_START message\n");
1800   zi = GNUNET_new (struct ZoneIteration);
1801   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1802   zi->offset = 0;
1803   zi->nc = nc;
1804   zi->zone = zis_msg->zone;
1805
1806   GNUNET_CONTAINER_DLL_insert (nc->op_head,
1807                                nc->op_tail,
1808                                zi);
1809   run_zone_iteration_round (zi,
1810                             1);
1811   GNUNET_SERVICE_client_continue (nc->client);
1812 }
1813
1814
1815 /**
1816  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1817  *
1818  * @param cls the client sending the message
1819  * @param zis_msg message from the client
1820  */
1821 static void
1822 handle_iteration_stop (void *cls,
1823                        const struct ZoneIterationStopMessage *zis_msg)
1824 {
1825   struct NamestoreClient *nc = cls;
1826   struct ZoneIteration *zi;
1827   uint32_t rid;
1828
1829   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1830               "Received ZONE_ITERATION_STOP message\n");
1831   rid = ntohl (zis_msg->gns_header.r_id);
1832   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1833     if (zi->request_id == rid)
1834       break;
1835   if (NULL == zi)
1836   {
1837     GNUNET_break (0);
1838     GNUNET_SERVICE_client_drop (nc->client);
1839     return;
1840   }
1841   GNUNET_CONTAINER_DLL_remove (nc->op_head,
1842                                nc->op_tail,
1843                                zi);
1844   GNUNET_free (zi);
1845   GNUNET_SERVICE_client_continue (nc->client);
1846 }
1847
1848
1849 /**
1850  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1851  *
1852  * @param cls the client sending the message
1853  * @param message message from the client
1854  */
1855 static void
1856 handle_iteration_next (void *cls,
1857                        const struct ZoneIterationNextMessage *zis_msg)
1858 {
1859   struct NamestoreClient *nc = cls;
1860   struct ZoneIteration *zi;
1861   uint32_t rid;
1862   uint64_t limit;
1863
1864   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1865               "Received ZONE_ITERATION_NEXT message\n");
1866   GNUNET_STATISTICS_update (statistics,
1867                             "Iteration NEXT messages received",
1868                             1,
1869                             GNUNET_NO);
1870   rid = ntohl (zis_msg->gns_header.r_id);
1871   limit = GNUNET_ntohll (zis_msg->limit);
1872   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1873     if (zi->request_id == rid)
1874       break;
1875   if (NULL == zi)
1876   {
1877     GNUNET_break (0);
1878     GNUNET_SERVICE_client_drop (nc->client);
1879     return;
1880   }
1881   run_zone_iteration_round (zi,
1882                             limit);
1883   GNUNET_SERVICE_client_continue (nc->client);
1884 }
1885
1886
1887 /**
1888  * Function called when the monitor is ready for more data, and we
1889  * should thus unblock PUT operations that were blocked on the
1890  * monitor not being ready.
1891  */
1892 static void
1893 monitor_unblock (struct ZoneMonitor *zm)
1894 {
1895   struct StoreActivity *sa = sa_head;
1896
1897   while ( (NULL != sa) &&
1898           (zm->limit > zm->iteration_cnt) )
1899   {
1900     struct StoreActivity *sn = sa->next;
1901
1902     if (sa->zm_pos == zm)
1903       continue_store_activity (sa);
1904     sa = sn;
1905   }
1906   if (zm->limit > zm->iteration_cnt)
1907   {
1908     zm->sa_waiting = GNUNET_NO;
1909     if (NULL != zm->sa_wait_warning)
1910     {
1911       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1912       zm->sa_wait_warning = NULL;
1913     }
1914   }
1915   else if (GNUNET_YES == zm->sa_waiting)
1916   {
1917     zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1918     if (NULL != zm->sa_wait_warning)
1919       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1920     zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1921                                                         &warn_monitor_slow,
1922                                                         zm);
1923   }
1924 }
1925
1926
1927 /**
1928  * Send 'sync' message to zone monitor, we're now in sync.
1929  *
1930  * @param zm monitor that is now in sync
1931  */
1932 static void
1933 monitor_sync (struct ZoneMonitor *zm)
1934 {
1935   struct GNUNET_MQ_Envelope *env;
1936   struct GNUNET_MessageHeader *sync;
1937
1938   env = GNUNET_MQ_msg (sync,
1939                        GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1940   GNUNET_MQ_send (zm->nc->mq,
1941                   env);
1942   /* mark iteration done */
1943   zm->in_first_iteration = GNUNET_NO;
1944   zm->iteration_cnt = 0;
1945   if ( (zm->limit > 0) &&
1946        (zm->sa_waiting) )
1947     monitor_unblock (zm);
1948 }
1949
1950
1951 /**
1952  * Obtain the next datum during the zone monitor's zone initial iteration.
1953  *
1954  * @param cls zone monitor that does its initial iteration
1955  */
1956 static void
1957 monitor_iteration_next (void *cls);
1958
1959
1960 /**
1961  * A #GNUNET_NAMESTORE_RecordIterator for monitors.
1962  *
1963  * @param cls a 'struct ZoneMonitor *' with information about the monitor
1964  * @param seq sequence number of the record
1965  * @param zone_key zone key of the zone
1966  * @param name name
1967  * @param rd_count number of records in @a rd
1968  * @param rd array of records
1969  */
1970 static void
1971 monitor_iterate_cb (void *cls,
1972                     uint64_t seq,
1973                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1974                     const char *name,
1975                     unsigned int rd_count,
1976                     const struct GNUNET_GNSRECORD_Data *rd)
1977 {
1978   struct ZoneMonitor *zm = cls;
1979
1980   zm->seq = seq;
1981   GNUNET_assert (NULL != name);
1982   GNUNET_STATISTICS_update (statistics,
1983                             "Monitor notifications sent",
1984                             1,
1985                             GNUNET_NO);
1986   zm->limit--;
1987   zm->iteration_cnt--;
1988   send_lookup_response (zm->nc,
1989                         0,
1990                         zone_key,
1991                         name,
1992                         rd_count,
1993                         rd);
1994   if ( (0 == zm->iteration_cnt) &&
1995        (0 != zm->limit) )
1996   {
1997     /* We are done with the current iteration batch, AND the
1998        client would right now accept more, so go again! */
1999     GNUNET_assert (NULL == zm->task);
2000     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2001                                          zm);
2002   }
2003 }
2004
2005
2006 /**
2007  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2008  *
2009  * @param cls the client sending the message
2010  * @param zis_msg message from the client
2011  */
2012 static void
2013 handle_monitor_start (void *cls,
2014                       const struct ZoneMonitorStartMessage *zis_msg)
2015 {
2016   struct NamestoreClient *nc = cls;
2017   struct ZoneMonitor *zm;
2018
2019   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2020               "Received ZONE_MONITOR_START message\n");
2021   zm = GNUNET_new (struct ZoneMonitor);
2022   zm->nc = nc;
2023   zm->zone = zis_msg->zone;
2024   zm->limit = 1;
2025   zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2026   GNUNET_CONTAINER_DLL_insert (monitor_head,
2027                                monitor_tail,
2028                                zm);
2029   GNUNET_SERVICE_client_mark_monitor (nc->client);
2030   GNUNET_SERVICE_client_continue (nc->client);
2031   GNUNET_notification_context_add (monitor_nc,
2032                                    nc->mq);
2033   if (zm->in_first_iteration)
2034     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2035                                          zm);
2036   else
2037     monitor_sync (zm);
2038 }
2039
2040
2041 /**
2042  * Obtain the next datum during the zone monitor's zone initial iteration.
2043  *
2044  * @param cls zone monitor that does its initial iteration
2045  */
2046 static void
2047 monitor_iteration_next (void *cls)
2048 {
2049   struct ZoneMonitor *zm = cls;
2050   int ret;
2051
2052   zm->task = NULL;
2053   GNUNET_assert (0 == zm->iteration_cnt);
2054   if (zm->limit > 16)
2055     zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2056   else
2057     zm->iteration_cnt = zm->limit; /* use it all */
2058   ret = GSN_database->iterate_records (GSN_database->cls,
2059                                        (0 == memcmp (&zm->zone,
2060                                                      &zero,
2061                                                      sizeof (zero)))
2062                                        ? NULL
2063                                        : &zm->zone,
2064                                        zm->seq,
2065                                        zm->iteration_cnt,
2066                                        &monitor_iterate_cb,
2067                                        zm);
2068   if (GNUNET_SYSERR == ret)
2069   {
2070     GNUNET_SERVICE_client_drop (zm->nc->client);
2071     return;
2072   }
2073   if (GNUNET_NO == ret)
2074   {
2075     /* empty zone */
2076     monitor_sync (zm);
2077     return;
2078   }
2079 }
2080
2081
2082 /**
2083  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2084  *
2085  * @param cls the client sending the message
2086  * @param nm message from the client
2087  */
2088 static void
2089 handle_monitor_next (void *cls,
2090                      const struct ZoneMonitorNextMessage *nm)
2091 {
2092   struct NamestoreClient *nc = cls;
2093   struct ZoneMonitor *zm;
2094   uint64_t inc;
2095
2096   inc = GNUNET_ntohll (nm->limit);
2097   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2098               "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2099               (unsigned long long) inc);
2100   for (zm = monitor_head; NULL != zm; zm = zm->next)
2101     if (zm->nc == nc)
2102       break;
2103   if (NULL == zm)
2104   {
2105     GNUNET_break (0);
2106     GNUNET_SERVICE_client_drop (nc->client);
2107     return;
2108   }
2109   GNUNET_SERVICE_client_continue (nc->client);
2110   if (zm->limit + inc < zm->limit)
2111   {
2112     GNUNET_break (0);
2113     GNUNET_SERVICE_client_drop (nc->client);
2114     return;
2115   }
2116   zm->limit += inc;
2117   if ( (zm->in_first_iteration) &&
2118        (zm->limit == inc) )
2119   {
2120     /* We are still iterating, and the previous iteration must
2121        have stopped due to the client's limit, so continue it! */
2122     GNUNET_assert (NULL == zm->task);
2123     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2124                                          zm);
2125   }
2126   GNUNET_assert (zm->iteration_cnt <= zm->limit);
2127   if ( (zm->limit > zm->iteration_cnt) &&
2128        (zm->sa_waiting) )
2129   {
2130     monitor_unblock (zm);
2131   }
2132   else if (GNUNET_YES == zm->sa_waiting)
2133   {
2134     if (NULL != zm->sa_wait_warning)
2135       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2136     zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2137     zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2138                                                         &warn_monitor_slow,
2139                                                         zm);
2140   }
2141 }
2142
2143
2144 /**
2145  * Process namestore requests.
2146  *
2147  * @param cls closure
2148  * @param cfg configuration to use
2149  * @param service the initialized service
2150  */
2151 static void
2152 run (void *cls,
2153      const struct GNUNET_CONFIGURATION_Handle *cfg,
2154      struct GNUNET_SERVICE_Handle *service)
2155 {
2156   char *database;
2157
2158   (void) cls;
2159   (void) service;
2160   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2161               "Starting namestore service\n");
2162   cache_keys = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2163                                                      "namestore",
2164                                                      "CACHE_KEYS");
2165   disable_namecache = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2166                                                             "namecache",
2167                                                             "DISABLE");
2168   GSN_cfg = cfg;
2169   monitor_nc = GNUNET_notification_context_create (1);
2170   if (GNUNET_YES != disable_namecache)
2171   {
2172     namecache = GNUNET_NAMECACHE_connect (cfg);
2173     GNUNET_assert (NULL != namecache);
2174   }
2175   /* Loading database plugin */
2176   if (GNUNET_OK !=
2177       GNUNET_CONFIGURATION_get_value_string (cfg,
2178                                              "namestore",
2179                                              "database",
2180                                              &database))
2181     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2182                 "No database backend configured\n");
2183
2184   GNUNET_asprintf (&db_lib_name,
2185                    "libgnunet_plugin_namestore_%s",
2186                    database);
2187   GSN_database = GNUNET_PLUGIN_load (db_lib_name,
2188                                      (void *) GSN_cfg);
2189   GNUNET_free (database);
2190   statistics = GNUNET_STATISTICS_create ("namestore",
2191                                          cfg);
2192   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
2193                                  NULL);
2194   if (NULL == GSN_database)
2195   {
2196     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2197                 "Could not load database backend `%s'\n",
2198                 db_lib_name);
2199     GNUNET_SCHEDULER_shutdown ();
2200     return;
2201   }
2202 }
2203
2204
2205 /**
2206  * Define "main" method using service macro.
2207  */
2208 GNUNET_SERVICE_MAIN
2209 ("namestore",
2210  GNUNET_SERVICE_OPTION_NONE,
2211  &run,
2212  &client_connect_cb,
2213  &client_disconnect_cb,
2214  NULL,
2215  GNUNET_MQ_hd_var_size (record_store,
2216                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2217                         struct RecordStoreMessage,
2218                         NULL),
2219  GNUNET_MQ_hd_var_size (record_lookup,
2220                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2221                         struct LabelLookupMessage,
2222                         NULL),
2223  GNUNET_MQ_hd_fixed_size (zone_to_name,
2224                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2225                           struct ZoneToNameMessage,
2226                           NULL),
2227  GNUNET_MQ_hd_fixed_size (iteration_start,
2228                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2229                           struct ZoneIterationStartMessage,
2230                           NULL),
2231  GNUNET_MQ_hd_fixed_size (iteration_next,
2232                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2233                           struct ZoneIterationNextMessage,
2234                           NULL),
2235  GNUNET_MQ_hd_fixed_size (iteration_stop,
2236                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2237                           struct ZoneIterationStopMessage,
2238                           NULL),
2239  GNUNET_MQ_hd_fixed_size (monitor_start,
2240                           GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2241                           struct ZoneMonitorStartMessage,
2242                           NULL),
2243  GNUNET_MQ_hd_fixed_size (monitor_next,
2244                           GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2245                           struct ZoneMonitorNextMessage,
2246                           NULL),
2247  GNUNET_MQ_handler_end ());
2248
2249
2250 /* end of gnunet-service-namestore.c */