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