get rid of plain memcpy calls
[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   int record_offset;
554   size_t data_offset;
555
556   (*rdc_res) = 1 + rd2_length;
557   if (0 == 1 + rd2_length)
558   {
559     (*rd_res) = NULL;
560     return;
561   }
562   req = 0;
563   for (unsigned int c=0; c< 1; c++)
564     req += sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd[c].data_size;
565   for (unsigned int c=0; c< rd2_length; c++)
566     req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size;
567   (*rd_res) = GNUNET_malloc (req);
568   data = (char *) &(*rd_res)[1 + rd2_length];
569   data_offset = 0;
570   latest_expiration = 0;
571   for (unsigned int c=0; c< rd2_length; c++)
572   {
573     if (0 != (rd2[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
574     {
575       if ((GNUNET_TIME_absolute_get().abs_value_us + rd2[c].expiration_time) >
576         latest_expiration)
577           latest_expiration = rd2[c].expiration_time;
578     }
579     else if (rd2[c].expiration_time > latest_expiration)
580       latest_expiration = rd2[c].expiration_time;
581     (*rd_res)[c] = rd2[c];
582     (*rd_res)[c].data = (void *) &data[data_offset];
583     GNUNET_memcpy ((void *) (*rd_res)[c].data,
584                    rd2[c].data,
585                    rd2[c].data_size);
586     data_offset += (*rd_res)[c].data_size;
587   }
588   /* append nick */
589   record_offset = rd2_length;
590   (*rd_res)[record_offset] = *nick_rd;
591   (*rd_res)[record_offset].expiration_time = latest_expiration;
592   (*rd_res)[record_offset].data = (void *) &data[data_offset];
593   GNUNET_memcpy ((void *) (*rd_res)[record_offset].data,
594                  nick_rd->data,
595                  nick_rd->data_size);
596   data_offset += (*rd_res)[record_offset].data_size;
597   GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
598 }
599
600
601 /**
602  * Generate a `struct LookupNameResponseMessage` and send it to the
603  * given client using the given notification context.
604  *
605  * @param nc client to unicast to
606  * @param request_id request ID to use
607  * @param zone_key zone key of the zone
608  * @param name name
609  * @param rd_count number of records in @a rd
610  * @param rd array of records
611  */
612 static void
613 send_lookup_response (struct NamestoreClient *nc,
614                       uint32_t request_id,
615                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
616                       const char *name,
617                       unsigned int rd_count,
618                       const struct GNUNET_GNSRECORD_Data *rd)
619 {
620   struct GNUNET_MQ_Envelope *env;
621   struct RecordResultMessage *zir_msg;
622   struct GNUNET_GNSRECORD_Data *nick;
623   struct GNUNET_GNSRECORD_Data *res;
624   unsigned int res_count;
625   size_t name_len;
626   size_t rd_ser_len;
627   char *name_tmp;
628   char *rd_ser;
629
630   nick = get_nick_record (zone_key);
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   name_len = strlen (name) + 1;
650   rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
651   env = GNUNET_MQ_msg_extra (zir_msg,
652                              name_len + rd_ser_len,
653                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
654   zir_msg->gns_header.r_id = htonl (request_id);
655   zir_msg->name_len = htons (name_len);
656   zir_msg->rd_count = htons (res_count);
657   zir_msg->rd_len = htons (rd_ser_len);
658   zir_msg->private_key = *zone_key;
659   name_tmp = (char *) &zir_msg[1];
660   GNUNET_memcpy (name_tmp,
661                  name,
662                  name_len);
663   rd_ser = &name_tmp[name_len];
664   GNUNET_GNSRECORD_records_serialize (res_count,
665                                       res,
666                                       rd_ser_len,
667                                       rd_ser);
668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
669               "Sending RECORD_RESULT message with %u records\n",
670               res_count);
671   GNUNET_STATISTICS_update (statistics,
672                             "Record sets sent to clients",
673                             1,
674                             GNUNET_NO);
675   GNUNET_MQ_send (nc->mq,
676                   env);
677   if (rd != res)
678     GNUNET_free (res);
679 }
680
681
682 /**
683  * Send response to the store request to the client.
684  *
685  * @param client client to talk to
686  * @param res status of the operation
687  * @param rid client's request ID
688  */
689 static void
690 send_store_response (struct NamestoreClient *nc,
691                      int res,
692                      uint32_t rid)
693 {
694   struct GNUNET_MQ_Envelope *env;
695   struct RecordStoreResponseMessage *rcr_msg;
696
697   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
698               "Sending RECORD_STORE_RESPONSE message\n");
699   GNUNET_STATISTICS_update (statistics,
700                             "Store requests completed",
701                             1,
702                             GNUNET_NO);
703   env = GNUNET_MQ_msg (rcr_msg,
704                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
705   rcr_msg->gns_header.r_id = htonl (rid);
706   rcr_msg->op_result = htonl (res);
707   GNUNET_MQ_send (nc->mq,
708                   env);
709 }
710
711
712 /**
713  * Cache operation complete, clean up.
714  *
715  * @param cls the `struct CacheOperation`
716  * @param success success
717  * @param emsg error messages
718  */
719 static void
720 finish_cache_operation (void *cls,
721                         int32_t success,
722                         const char *emsg)
723 {
724   struct CacheOperation *cop = cls;
725
726   if (NULL != emsg)
727     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
728                 _("Failed to replicate block in namecache: %s\n"),
729                 emsg);
730   else
731     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
732                 "CACHE operation completed\n");
733   GNUNET_CONTAINER_DLL_remove (cop_head,
734                                cop_tail,
735                                cop);
736   if (NULL != cop->nc)
737     send_store_response (cop->nc,
738                          success,
739                          cop->rid);
740   GNUNET_free (cop);
741 }
742
743
744 /**
745  * We just touched the plaintext information about a name in our zone;
746  * refresh the corresponding (encrypted) block in the namecache.
747  *
748  * @param nc client responsible for the request, can be NULL
749  * @param rid request ID of the client
750  * @param zone_key private key of the zone
751  * @param name label for the records
752  * @param rd_count number of records
753  * @param rd records stored under the given @a name
754  */
755 static void
756 refresh_block (struct NamestoreClient *nc,
757                uint32_t rid,
758                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
759                const char *name,
760                unsigned int rd_count,
761                const struct GNUNET_GNSRECORD_Data *rd)
762 {
763   struct GNUNET_GNSRECORD_Block *block;
764   struct CacheOperation *cop;
765   struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
766   struct GNUNET_GNSRECORD_Data *nick;
767   struct GNUNET_GNSRECORD_Data *res;
768   unsigned int res_count;
769   struct GNUNET_TIME_Absolute exp_time;
770
771   nick = get_nick_record (zone_key);
772   res_count = rd_count;
773   res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
774   if (NULL != nick)
775   {
776     nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
777     merge_with_nick_records (nick,
778                              rd_count,rd,
779                              &res_count,
780                              &res);
781     GNUNET_free (nick);
782   }
783   if (0 == res_count)
784   {
785     send_store_response (nc,
786                          GNUNET_OK,
787                          rid);
788     return; /* no data, no need to update cache */
789   }
790   if (GNUNET_YES == disable_namecache)
791   {
792     GNUNET_STATISTICS_update (statistics,
793                               "Namecache updates skipped (NC disabled)",
794                               1,
795                               GNUNET_NO);
796     send_store_response (nc,
797                          GNUNET_OK,
798                          rid);
799     return;
800   }
801   exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count,
802                                                           res);
803   if (cache_keys)
804     block = GNUNET_GNSRECORD_block_create2 (zone_key,
805                                             exp_time,
806                                             name,
807                                             res,
808                                             res_count);
809   else
810     block = GNUNET_GNSRECORD_block_create (zone_key,
811                                            exp_time,
812                                            name,
813                                            res,
814                                            res_count);
815   GNUNET_assert (NULL != block);
816   GNUNET_CRYPTO_ecdsa_key_get_public (zone_key,
817                                       &pkey);
818   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
819               "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
820               name,
821               res_count,
822               GNUNET_STRINGS_absolute_time_to_string (exp_time),
823               GNUNET_GNSRECORD_z2s (&pkey));
824   GNUNET_STATISTICS_update (statistics,
825                             "Namecache updates pushed",
826                             1,
827                             GNUNET_NO);
828   cop = GNUNET_new (struct CacheOperation);
829   cop->nc = nc;
830   cop->rid = rid;
831   GNUNET_CONTAINER_DLL_insert (cop_head,
832                                cop_tail,
833                                cop);
834   cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
835                                           block,
836                                           &finish_cache_operation,
837                                           cop);
838   GNUNET_free (block);
839 }
840
841
842 /**
843  * Print a warning that one of our monitors is no longer reacting.
844  *
845  * @param cls a `struct ZoneMonitor` to warn about
846  */
847 static void
848 warn_monitor_slow (void *cls)
849 {
850   struct ZoneMonitor *zm = cls;
851
852   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
853               "No response from monitor since %s\n",
854               GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
855   zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
856                                                       &warn_monitor_slow,
857                                                       zm);
858 }
859
860
861 /**
862  * Continue processing the @a sa.
863  *
864  * @param sa store activity to process
865  */
866 static void
867 continue_store_activity (struct StoreActivity *sa)
868 {
869   const struct RecordStoreMessage *rp_msg = sa->rsm;
870
871   for (struct ZoneMonitor *zm = sa->zm_pos;
872        NULL != zm;
873        zm = sa->zm_pos)
874   {
875     if ( (0 != memcmp (&rp_msg->private_key,
876                        &zm->zone,
877                        sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
878          (0 != memcmp (&zm->zone,
879                        &zero,
880                        sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
881       sa->zm_pos = zm->next; /* not interesting to this monitor */
882     if (zm->limit == zm->iteration_cnt)
883     {
884       zm->sa_waiting = GNUNET_YES;
885       zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
886       if (NULL != zm->sa_wait_warning)
887         GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
888       zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
889                                                           &warn_monitor_slow,
890                                                           zm);
891       return; /* blocked on zone monitor */
892     }
893     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
894                 "Notifying monitor about changes under label `%s'\n",
895                 sa->conv_name);
896     zm->limit--;
897     send_lookup_response (zm->nc,
898                           0,
899                           &rp_msg->private_key,
900                           sa->conv_name,
901                           sa->rd_count,
902                           sa->rd);
903     sa->zm_pos = zm->next;
904   }
905   /* great, done with the monitors, unpack (again) for refresh_block operation */
906   {
907     size_t name_len;
908     size_t rd_ser_len;
909     uint32_t rid;
910     const char *name_tmp;
911     const char *rd_ser;
912     unsigned int rd_count;
913
914     rid = ntohl (rp_msg->gns_header.r_id);
915     name_len = ntohs (rp_msg->name_len);
916     rd_count = ntohs (rp_msg->rd_count);
917     rd_ser_len = ntohs (rp_msg->rd_len);
918     name_tmp = (const char *) &rp_msg[1];
919     rd_ser = &name_tmp[name_len];
920     {
921       struct GNUNET_GNSRECORD_Data rd[rd_count];
922
923       /* We did this before, must succeed again */
924       GNUNET_assert (GNUNET_OK ==
925                      GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
926                                                            rd_ser,
927                                                            rd_count,
928                                                            rd));
929       refresh_block (sa->nc,
930                      rid,
931                      &rp_msg->private_key,
932                      sa->conv_name,
933                      rd_count,
934                      rd);
935     }
936   }
937   GNUNET_SERVICE_client_continue (sa->nc->client);
938   free_store_activity (sa);
939 }
940
941
942 /**
943  * Called whenever a client is disconnected.
944  * Frees our resources associated with that client.
945  *
946  * @param cls closure
947  * @param client identification of the client
948  * @param app_ctx the `struct NamestoreClient` of @a client
949  */
950 static void
951 client_disconnect_cb (void *cls,
952                       struct GNUNET_SERVICE_Client *client,
953                       void *app_ctx)
954 {
955   struct NamestoreClient *nc = app_ctx;
956   struct ZoneIteration *no;
957   struct CacheOperation *cop;
958
959   (void) cls;
960   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
961               "Client %p disconnected\n",
962               client);
963   for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
964   {
965     struct StoreActivity *san;
966
967     if (nc != zm->nc)
968       continue;
969     GNUNET_CONTAINER_DLL_remove (monitor_head,
970                                  monitor_tail,
971                                  zm);
972     if (NULL != zm->task)
973     {
974       GNUNET_SCHEDULER_cancel (zm->task);
975       zm->task = NULL;
976     }
977     if (NULL != zm->sa_wait_warning)
978     {
979       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
980       zm->sa_wait_warning = NULL;
981     }
982     for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
983     {
984       san = sa->next;
985       if (zm == sa->zm_pos)
986       {
987         sa->zm_pos = zm->next;
988         /* this may free sa */
989         continue_store_activity (sa);
990       }
991     }
992     GNUNET_free (zm);
993     break;
994   }
995   for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
996   {
997     if (sa->nc == nc)
998     {
999       /* this may free sa */
1000       free_store_activity (sa);
1001       break; /* there can only be one per nc */
1002     }
1003   }
1004   while (NULL != (no = nc->op_head))
1005   {
1006     GNUNET_CONTAINER_DLL_remove (nc->op_head,
1007                                  nc->op_tail,
1008                                  no);
1009     GNUNET_free (no);
1010   }
1011   for (cop = cop_head; NULL != cop; cop = cop->next)
1012     if (nc == cop->nc)
1013       cop->nc = NULL;
1014   GNUNET_free (nc);
1015 }
1016
1017
1018 /**
1019  * Add a client to our list of active clients.
1020  *
1021  * @param cls NULL
1022  * @param client client to add
1023  * @param mq message queue for @a client
1024  * @return internal namestore client structure for this client
1025  */
1026 static void *
1027 client_connect_cb (void *cls,
1028                    struct GNUNET_SERVICE_Client *client,
1029                    struct GNUNET_MQ_Handle *mq)
1030 {
1031   struct NamestoreClient *nc;
1032
1033   (void) cls;
1034   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035               "Client %p connected\n",
1036               client);
1037   nc = GNUNET_new (struct NamestoreClient);
1038   nc->client = client;
1039   nc->mq = mq;
1040   return nc;
1041 }
1042
1043
1044 /**
1045  * Closure for #lookup_it().
1046  */
1047 struct RecordLookupContext
1048 {
1049
1050   /**
1051    * FIXME.
1052    */
1053   const char *label;
1054
1055   /**
1056    * FIXME.
1057    */
1058   char *res_rd;
1059
1060   /**
1061    * FIXME.
1062    */
1063   struct GNUNET_GNSRECORD_Data *nick;
1064
1065   /**
1066    * FIXME.
1067    */
1068   int found;
1069
1070   /**
1071    * FIXME.
1072    */
1073   unsigned int res_rd_count;
1074
1075   /**
1076    * FIXME.
1077    */
1078   size_t rd_ser_len;
1079 };
1080
1081
1082 /**
1083  * FIXME.
1084  * @param seq sequence number of the record
1085  */
1086 static void
1087 lookup_it (void *cls,
1088            uint64_t seq,
1089            const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
1090            const char *label,
1091            unsigned int rd_count,
1092            const struct GNUNET_GNSRECORD_Data *rd)
1093 {
1094   struct RecordLookupContext *rlc = cls;
1095   struct GNUNET_GNSRECORD_Data *rd_res;
1096   unsigned int rdc_res;
1097
1098   (void) private_key;
1099   (void) seq;
1100   if (0 == strcmp (label,
1101                    rlc->label))
1102   {
1103     rlc->found = GNUNET_YES;
1104     if (0 != rd_count)
1105     {
1106       if ( (NULL != rlc->nick) &&
1107            (0 != strcmp (label,
1108                          GNUNET_GNS_EMPTY_LABEL_AT)) )
1109       {
1110         /* Merge */
1111         rd_res = NULL;
1112         rdc_res = 0;
1113         rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
1114         merge_with_nick_records (rlc->nick,
1115                                  rd_count,
1116                                  rd,
1117                                  &rdc_res,
1118                                  &rd_res);
1119         rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
1120                                                              rd_res);
1121         rlc->res_rd_count = rdc_res;
1122         rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1123         GNUNET_GNSRECORD_records_serialize (rdc_res,
1124                                             rd_res,
1125                                             rlc->rd_ser_len,
1126                                             rlc->res_rd);
1127
1128         GNUNET_free  (rd_res);
1129         GNUNET_free  (rlc->nick);
1130         rlc->nick = NULL;
1131       }
1132       else
1133       {
1134         rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
1135                                                              rd);
1136         rlc->res_rd_count = rd_count;
1137         rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1138         GNUNET_GNSRECORD_records_serialize (rd_count,
1139                                             rd,
1140                                             rlc->rd_ser_len,
1141                                             rlc->res_rd);
1142       }
1143     }
1144     else
1145     {
1146       rlc->rd_ser_len = 0;
1147       rlc->res_rd_count = 0;
1148       rlc->res_rd = NULL;
1149     }
1150   }
1151 }
1152
1153
1154 /**
1155  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1156  *
1157  * @param cls client sending the message
1158  * @param ll_msg message of type `struct LabelLookupMessage`
1159  * @return #GNUNET_OK if @a ll_msg is well-formed
1160  */
1161 static int
1162 check_record_lookup (void *cls,
1163                      const struct LabelLookupMessage *ll_msg)
1164 {
1165   uint32_t name_len;
1166   size_t src_size;
1167   const char *name_tmp;
1168
1169   (void) cls;
1170   name_len = ntohl (ll_msg->label_len);
1171   src_size = ntohs (ll_msg->gns_header.header.size);
1172   if (name_len != src_size - sizeof (struct LabelLookupMessage))
1173   {
1174     GNUNET_break (0);
1175     return GNUNET_SYSERR;
1176   }
1177
1178   name_tmp = (const char *) &ll_msg[1];
1179   if ('\0' != name_tmp[name_len -1])
1180   {
1181     GNUNET_break (0);
1182     return GNUNET_SYSERR;
1183   }
1184   return GNUNET_OK;
1185 }
1186
1187
1188 /**
1189  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1190  *
1191  * @param cls client sending the message
1192  * @param ll_msg message of type `struct LabelLookupMessage`
1193  */
1194 static void
1195 handle_record_lookup (void *cls,
1196                       const struct LabelLookupMessage *ll_msg)
1197 {
1198   struct NamestoreClient *nc = cls;
1199   struct GNUNET_MQ_Envelope *env;
1200   struct LabelLookupResponseMessage *llr_msg;
1201   struct RecordLookupContext rlc;
1202   const char *name_tmp;
1203   char *res_name;
1204   char *conv_name;
1205   uint32_t name_len;
1206   int res;
1207
1208   name_len = ntohl (ll_msg->label_len);
1209   name_tmp = (const char *) &ll_msg[1];
1210   GNUNET_SERVICE_client_continue (nc->client);
1211   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1212               "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1213               name_tmp);
1214
1215   conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1216   if (NULL == conv_name)
1217   {
1218     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1219                 "Error converting name `%s'\n",
1220                 name_tmp);
1221     GNUNET_SERVICE_client_drop (nc->client);
1222     return;
1223   }
1224   rlc.label = conv_name;
1225   rlc.found = GNUNET_NO;
1226   rlc.res_rd_count = 0;
1227   rlc.res_rd = NULL;
1228   rlc.rd_ser_len = 0;
1229   rlc.nick = get_nick_record (&ll_msg->zone);
1230   res = GSN_database->lookup_records (GSN_database->cls,
1231                                       &ll_msg->zone,
1232                                       conv_name,
1233                                       &lookup_it,
1234                                       &rlc);
1235   GNUNET_free (conv_name);
1236   env = GNUNET_MQ_msg_extra (llr_msg,
1237                              name_len + rlc.rd_ser_len,
1238                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1239   llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1240   llr_msg->private_key = ll_msg->zone;
1241   llr_msg->name_len = htons (name_len);
1242   llr_msg->rd_count = htons (rlc.res_rd_count);
1243   llr_msg->rd_len = htons (rlc.rd_ser_len);
1244   res_name = (char *) &llr_msg[1];
1245   if  ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1246     llr_msg->found = ntohs (GNUNET_YES);
1247   else
1248     llr_msg->found = ntohs (GNUNET_NO);
1249   GNUNET_memcpy (&llr_msg[1],
1250                  name_tmp,
1251                  name_len);
1252   GNUNET_memcpy (&res_name[name_len],
1253                  rlc.res_rd,
1254                  rlc.rd_ser_len);
1255   GNUNET_MQ_send (nc->mq,
1256                   env);
1257   GNUNET_free_non_null (rlc.res_rd);
1258 }
1259
1260
1261 /**
1262  * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1263  *
1264  * @param cls client sending the message
1265  * @param rp_msg message of type `struct RecordStoreMessage`
1266  * @return #GNUNET_OK if @a rp_msg is well-formed
1267  */
1268 static int
1269 check_record_store (void *cls,
1270                     const struct RecordStoreMessage *rp_msg)
1271 {
1272   size_t name_len;
1273   size_t msg_size;
1274   size_t msg_size_exp;
1275   size_t rd_ser_len;
1276   const char *name_tmp;
1277
1278   (void) cls;
1279   name_len = ntohs (rp_msg->name_len);
1280   msg_size = ntohs (rp_msg->gns_header.header.size);
1281   rd_ser_len = ntohs (rp_msg->rd_len);
1282   msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
1283   if (msg_size != msg_size_exp)
1284   {
1285     GNUNET_break (0);
1286     return GNUNET_SYSERR;
1287   }
1288   if ( (0 == name_len) ||
1289        (name_len > MAX_NAME_LEN) )
1290   {
1291     GNUNET_break (0);
1292     return GNUNET_SYSERR;
1293   }
1294   name_tmp = (const char *) &rp_msg[1];
1295   if ('\0' != name_tmp[name_len -1])
1296   {
1297     GNUNET_break (0);
1298     return GNUNET_SYSERR;
1299   }
1300   return GNUNET_OK;
1301 }
1302
1303
1304 /**
1305  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1306  *
1307  * @param cls client sending the message
1308  * @param rp_msg message of type `struct RecordStoreMessage`
1309  */
1310 static void
1311 handle_record_store (void *cls,
1312                      const struct RecordStoreMessage *rp_msg)
1313 {
1314   struct NamestoreClient *nc = cls;
1315   size_t name_len;
1316   size_t rd_ser_len;
1317   uint32_t rid;
1318   const char *name_tmp;
1319   char *conv_name;
1320   const char *rd_ser;
1321   unsigned int rd_count;
1322   int res;
1323   struct StoreActivity *sa;
1324
1325   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1326               "Received NAMESTORE_RECORD_STORE message\n");
1327   rid = ntohl (rp_msg->gns_header.r_id);
1328   name_len = ntohs (rp_msg->name_len);
1329   rd_count = ntohs (rp_msg->rd_count);
1330   rd_ser_len = ntohs (rp_msg->rd_len);
1331   GNUNET_break (0 == ntohs (rp_msg->reserved));
1332   name_tmp = (const char *) &rp_msg[1];
1333   rd_ser = &name_tmp[name_len];
1334   {
1335     struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(rd_count)];
1336     struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL(rd_count)];
1337     unsigned int rd_clean_off;
1338
1339     if (GNUNET_OK !=
1340         GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
1341                                               rd_ser,
1342                                               rd_count,
1343                                               rd))
1344     {
1345       GNUNET_break (0);
1346       GNUNET_SERVICE_client_drop (nc->client);
1347       return;
1348     }
1349
1350     /* Extracting and converting private key */
1351     conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1352     if (NULL == conv_name)
1353     {
1354       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1355                   "Error converting name `%s'\n",
1356                   name_tmp);
1357       GNUNET_SERVICE_client_drop (nc->client);
1358       return;
1359     }
1360     GNUNET_STATISTICS_update (statistics,
1361                               "Well-formed store requests received",
1362                               1,
1363                               GNUNET_NO);
1364     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1365                 "Creating %u records for name `%s'\n",
1366                 (unsigned int) rd_count,
1367                 conv_name);
1368     if ( (0 == rd_count) &&
1369          (GNUNET_NO ==
1370           GSN_database->lookup_records (GSN_database->cls,
1371                                         &rp_msg->private_key,
1372                                         conv_name,
1373                                         NULL,
1374                                         0)) )
1375     {
1376       /* This name does not exist, so cannot be removed */
1377       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378                   "Name `%s' does not exist, no deletion required\n",
1379                   conv_name);
1380       res = GNUNET_NO;
1381     }
1382     else
1383     {
1384       /* remove "NICK" records, unless this is for the
1385          #GNUNET_GNS_EMPTY_LABEL_AT label */
1386       rd_clean_off = 0;
1387       for (unsigned int i=0;i<rd_count;i++)
1388       {
1389         rd_clean[rd_clean_off] = rd[i];
1390         if ( (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT,
1391                            conv_name)) ||
1392              (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type) )
1393           rd_clean_off++;
1394       }
1395       res = GSN_database->store_records (GSN_database->cls,
1396                                          &rp_msg->private_key,
1397                                          conv_name,
1398                                          rd_clean_off,
1399                                          rd_clean);
1400     }
1401
1402     if (GNUNET_OK != res)
1403     {
1404       /* store not successful, not need to tell monitors */
1405       send_store_response (nc,
1406                            res,
1407                            rid);
1408       GNUNET_SERVICE_client_continue (nc->client);
1409       GNUNET_free (conv_name);
1410       return;
1411     }
1412
1413     sa = GNUNET_malloc (sizeof (struct StoreActivity) +
1414                         ntohs (rp_msg->gns_header.header.size));
1415     GNUNET_CONTAINER_DLL_insert (sa_head,
1416                                  sa_tail,
1417                                  sa);
1418     sa->nc = nc;
1419     sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1420     GNUNET_memcpy (&sa[1],
1421                    rp_msg,
1422                    ntohs (rp_msg->gns_header.header.size));
1423     sa->zm_pos = monitor_head;
1424     sa->conv_name = conv_name;
1425     GNUNET_array_grow (sa->rd,
1426                        sa->rd_count,
1427                        rd_clean_off);
1428     GNUNET_memcpy (sa->rd,
1429                    rd_clean,
1430                    sizeof (struct GNUNET_GNSRECORD_Data) * rd_clean_off);
1431     continue_store_activity (sa);
1432   }
1433 }
1434
1435
1436 /**
1437  * Context for record remove operations passed from #handle_zone_to_name to
1438  * #handle_zone_to_name_it as closure
1439  */
1440 struct ZoneToNameCtx
1441 {
1442   /**
1443    * Namestore client
1444    */
1445   struct NamestoreClient *nc;
1446
1447   /**
1448    * Request id (to be used in the response to the client).
1449    */
1450   uint32_t rid;
1451
1452   /**
1453    * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error.  Note that
1454    * not finding a name for the zone still counts as a 'success' here,
1455    * as this field is about the success of executing the IPC protocol.
1456    */
1457   int success;
1458 };
1459
1460
1461 /**
1462  * Zone to name iterator
1463  *
1464  * @param cls struct ZoneToNameCtx *
1465  * @param seq sequence number of the record
1466  * @param zone_key the zone key
1467  * @param name name
1468  * @param rd_count number of records in @a rd
1469  * @param rd record data
1470  */
1471 static void
1472 handle_zone_to_name_it (void *cls,
1473                         uint64_t seq,
1474                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1475                         const char *name,
1476                         unsigned int rd_count,
1477                         const struct GNUNET_GNSRECORD_Data *rd)
1478 {
1479   struct ZoneToNameCtx *ztn_ctx = cls;
1480   struct GNUNET_MQ_Envelope *env;
1481   struct ZoneToNameResponseMessage *ztnr_msg;
1482   int16_t res;
1483   size_t name_len;
1484   size_t rd_ser_len;
1485   size_t msg_size;
1486   char *name_tmp;
1487   char *rd_tmp;
1488
1489   (void) seq;
1490   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1491               "Found result for zone-to-name lookup: `%s'\n",
1492               name);
1493   res = GNUNET_YES;
1494   name_len = (NULL == name) ? 0 : strlen (name) + 1;
1495   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1496   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1497   if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1498   {
1499     GNUNET_break (0);
1500     ztn_ctx->success = GNUNET_SYSERR;
1501     return;
1502   }
1503   env = GNUNET_MQ_msg_extra (ztnr_msg,
1504                              name_len + rd_ser_len,
1505                              GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1506   ztnr_msg->gns_header.header.size = htons (msg_size);
1507   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1508   ztnr_msg->res = htons (res);
1509   ztnr_msg->rd_len = htons (rd_ser_len);
1510   ztnr_msg->rd_count = htons (rd_count);
1511   ztnr_msg->name_len = htons (name_len);
1512   ztnr_msg->zone = *zone_key;
1513   name_tmp = (char *) &ztnr_msg[1];
1514   GNUNET_memcpy (name_tmp,
1515                  name,
1516                  name_len);
1517   rd_tmp = &name_tmp[name_len];
1518   GNUNET_GNSRECORD_records_serialize (rd_count,
1519                                       rd,
1520                                       rd_ser_len,
1521                                       rd_tmp);
1522   ztn_ctx->success = GNUNET_OK;
1523   GNUNET_MQ_send (ztn_ctx->nc->mq,
1524                   env);
1525 }
1526
1527
1528 /**
1529  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1530  *
1531  * @param cls client client sending the message
1532  * @param ztn_msg message of type 'struct ZoneToNameMessage'
1533  */
1534 static void
1535 handle_zone_to_name (void *cls,
1536                      const struct ZoneToNameMessage *ztn_msg)
1537 {
1538   struct NamestoreClient *nc = cls;
1539   struct ZoneToNameCtx ztn_ctx;
1540   struct GNUNET_MQ_Envelope *env;
1541   struct ZoneToNameResponseMessage *ztnr_msg;
1542
1543   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1544               "Received ZONE_TO_NAME message\n");
1545   ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1546   ztn_ctx.nc = nc;
1547   ztn_ctx.success = GNUNET_NO;
1548   if (GNUNET_SYSERR ==
1549       GSN_database->zone_to_name (GSN_database->cls,
1550                                   &ztn_msg->zone,
1551                                   &ztn_msg->value_zone,
1552                                   &handle_zone_to_name_it, &ztn_ctx))
1553   {
1554     /* internal error, hang up instead of signalling something
1555        that might be wrong */
1556     GNUNET_break (0);
1557     GNUNET_SERVICE_client_drop (nc->client);
1558     return;
1559   }
1560   if (GNUNET_NO == ztn_ctx.success)
1561   {
1562     /* no result found, send empty response */
1563     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1564                 "Found no result for zone-to-name lookup.\n");
1565     env = GNUNET_MQ_msg (ztnr_msg,
1566                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1567     ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1568     ztnr_msg->res = htons (GNUNET_NO);
1569     GNUNET_MQ_send (nc->mq,
1570                     env);
1571   }
1572   GNUNET_SERVICE_client_continue (nc->client);
1573 }
1574
1575
1576 /**
1577  * Context for record remove operations passed from
1578  * #run_zone_iteration_round to #zone_iterate_proc as closure
1579  */
1580 struct ZoneIterationProcResult
1581 {
1582   /**
1583    * The zone iteration handle
1584    */
1585   struct ZoneIteration *zi;
1586
1587   /**
1588    * Number of results left to be returned in this iteration.
1589    */
1590   uint64_t limit;
1591
1592 };
1593
1594
1595 /**
1596  * Process results for zone iteration from database
1597  *
1598  * @param cls struct ZoneIterationProcResult
1599  * @param seq sequence number of the record
1600  * @param zone_key the zone key
1601  * @param name name
1602  * @param rd_count number of records for this name
1603  * @param rd record data
1604  */
1605 static void
1606 zone_iterate_proc (void *cls,
1607                    uint64_t seq,
1608                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1609                    const char *name,
1610                    unsigned int rd_count,
1611                    const struct GNUNET_GNSRECORD_Data *rd)
1612 {
1613   struct ZoneIterationProcResult *proc = cls;
1614   int do_refresh_block;
1615
1616   if ( (NULL == zone_key) &&
1617        (NULL == name) )
1618   {
1619     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1620                 "Iteration done\n");
1621     return;
1622   }
1623   if ( (NULL == zone_key) ||
1624        (NULL == name) )
1625   {
1626     /* what is this!? should never happen */
1627     GNUNET_break (0);
1628     return;
1629   }
1630   if (0 == proc->limit)
1631   {
1632     /* what is this!? should never happen */
1633     GNUNET_break (0);
1634     return;
1635   }
1636   proc->limit--;
1637   proc->zi->seq = seq;
1638   send_lookup_response (proc->zi->nc,
1639                         proc->zi->request_id,
1640                         zone_key,
1641                         name,
1642                         rd_count,
1643                         rd);
1644   do_refresh_block = GNUNET_NO;
1645   for (unsigned int i=0;i<rd_count;i++)
1646     if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1647     {
1648       do_refresh_block = GNUNET_YES;
1649       break;
1650     }
1651   if (GNUNET_YES == do_refresh_block)
1652     refresh_block (NULL,
1653                    0,
1654                    zone_key,
1655                    name,
1656                    rd_count,
1657                    rd);
1658 }
1659
1660
1661 /**
1662  * Perform the next round of the zone iteration.
1663  *
1664  * @param zi zone iterator to process
1665  * @param limit number of results to return in one pass
1666  */
1667 static void
1668 run_zone_iteration_round (struct ZoneIteration *zi,
1669                           uint64_t limit)
1670 {
1671   struct ZoneIterationProcResult proc;
1672   struct GNUNET_MQ_Envelope *env;
1673   struct RecordResultMessage *rrm;
1674   struct GNUNET_TIME_Absolute start;
1675   struct GNUNET_TIME_Relative duration;
1676
1677   memset (&proc,
1678           0,
1679           sizeof (proc));
1680   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1681               "Asked to return up to %llu records at position %llu\n",
1682               (unsigned long long) limit,
1683               (unsigned long long) zi->seq);
1684   proc.zi = zi;
1685   proc.limit = limit;
1686   start = GNUNET_TIME_absolute_get ();
1687   GNUNET_break (GNUNET_SYSERR !=
1688                 GSN_database->iterate_records (GSN_database->cls,
1689                                                (0 == memcmp (&zi->zone,
1690                                                              &zero,
1691                                                              sizeof (zero)))
1692                                                ? NULL
1693                                                : &zi->zone,
1694                                                zi->seq,
1695                                                limit,
1696                                                &zone_iterate_proc,
1697                                                &proc));
1698   duration = GNUNET_TIME_absolute_get_duration (start);
1699   duration = GNUNET_TIME_relative_divide (duration,
1700                                           limit - proc.limit);
1701   GNUNET_STATISTICS_set (statistics,
1702                          "NAMESTORE iteration delay (μs/record)",
1703                          duration.rel_value_us,
1704                          GNUNET_NO);
1705   if (0 == proc.limit)
1706   {
1707     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1708                 "Returned %llu results, more results available\n",
1709                 (unsigned long long) limit);
1710     return; /* more results later after we get the
1711                #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message */
1712   }
1713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1714               "Completed iteration after %llu/%llu results\n",
1715               (unsigned long long) (limit - proc.limit),
1716               (unsigned long long) limit);
1717   /* send empty response to indicate end of list */
1718   env = GNUNET_MQ_msg (rrm,
1719                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
1720   rrm->gns_header.r_id = htonl (zi->request_id);
1721   GNUNET_MQ_send (zi->nc->mq,
1722                   env);
1723   GNUNET_CONTAINER_DLL_remove (zi->nc->op_head,
1724                                zi->nc->op_tail,
1725                                zi);
1726   GNUNET_free (zi);
1727 }
1728
1729
1730 /**
1731  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1732  *
1733  * @param cls the client sending the message
1734  * @param zis_msg message from the client
1735  */
1736 static void
1737 handle_iteration_start (void *cls,
1738                         const struct ZoneIterationStartMessage *zis_msg)
1739 {
1740   struct NamestoreClient *nc = cls;
1741   struct ZoneIteration *zi;
1742
1743   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1744               "Received ZONE_ITERATION_START message\n");
1745   zi = GNUNET_new (struct ZoneIteration);
1746   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1747   zi->offset = 0;
1748   zi->nc = nc;
1749   zi->zone = zis_msg->zone;
1750
1751   GNUNET_CONTAINER_DLL_insert (nc->op_head,
1752                                nc->op_tail,
1753                                zi);
1754   run_zone_iteration_round (zi,
1755                             1);
1756   GNUNET_SERVICE_client_continue (nc->client);
1757 }
1758
1759
1760 /**
1761  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1762  *
1763  * @param cls the client sending the message
1764  * @param zis_msg message from the client
1765  */
1766 static void
1767 handle_iteration_stop (void *cls,
1768                        const struct ZoneIterationStopMessage *zis_msg)
1769 {
1770   struct NamestoreClient *nc = cls;
1771   struct ZoneIteration *zi;
1772   uint32_t rid;
1773
1774   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1775               "Received ZONE_ITERATION_STOP message\n");
1776   rid = ntohl (zis_msg->gns_header.r_id);
1777   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1778     if (zi->request_id == rid)
1779       break;
1780   if (NULL == zi)
1781   {
1782     GNUNET_break (0);
1783     GNUNET_SERVICE_client_drop (nc->client);
1784     return;
1785   }
1786   GNUNET_CONTAINER_DLL_remove (nc->op_head,
1787                                nc->op_tail,
1788                                zi);
1789   GNUNET_free (zi);
1790   GNUNET_SERVICE_client_continue (nc->client);
1791 }
1792
1793
1794 /**
1795  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1796  *
1797  * @param cls the client sending the message
1798  * @param message message from the client
1799  */
1800 static void
1801 handle_iteration_next (void *cls,
1802                        const struct ZoneIterationNextMessage *zis_msg)
1803 {
1804   struct NamestoreClient *nc = cls;
1805   struct ZoneIteration *zi;
1806   uint32_t rid;
1807   uint64_t limit;
1808
1809   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1810               "Received ZONE_ITERATION_NEXT message\n");
1811   GNUNET_STATISTICS_update (statistics,
1812                             "Iteration NEXT messages received",
1813                             1,
1814                             GNUNET_NO);
1815   rid = ntohl (zis_msg->gns_header.r_id);
1816   limit = GNUNET_ntohll (zis_msg->limit);
1817   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1818     if (zi->request_id == rid)
1819       break;
1820   if (NULL == zi)
1821   {
1822     GNUNET_break (0);
1823     GNUNET_SERVICE_client_drop (nc->client);
1824     return;
1825   }
1826   run_zone_iteration_round (zi,
1827                             limit);
1828   GNUNET_SERVICE_client_continue (nc->client);
1829 }
1830
1831
1832 /**
1833  * Function called when the monitor is ready for more data, and we
1834  * should thus unblock PUT operations that were blocked on the
1835  * monitor not being ready.
1836  */
1837 static void
1838 monitor_unblock (struct ZoneMonitor *zm)
1839 {
1840   struct StoreActivity *sa = sa_head;
1841
1842   while ( (NULL != sa) &&
1843           (zm->limit > zm->iteration_cnt) )
1844   {
1845     struct StoreActivity *sn = sa->next;
1846
1847     if (sa->zm_pos == zm)
1848       continue_store_activity (sa);
1849     sa = sn;
1850   }
1851   if (zm->limit > zm->iteration_cnt)
1852   {
1853     zm->sa_waiting = GNUNET_NO;
1854     if (NULL != zm->sa_wait_warning)
1855     {
1856       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1857       zm->sa_wait_warning = NULL;
1858     }
1859   }
1860   else if (GNUNET_YES == zm->sa_waiting)
1861   {
1862     zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1863     if (NULL != zm->sa_wait_warning)
1864       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1865     zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1866                                                         &warn_monitor_slow,
1867                                                         zm);
1868   }
1869 }
1870
1871
1872 /**
1873  * Send 'sync' message to zone monitor, we're now in sync.
1874  *
1875  * @param zm monitor that is now in sync
1876  */
1877 static void
1878 monitor_sync (struct ZoneMonitor *zm)
1879 {
1880   struct GNUNET_MQ_Envelope *env;
1881   struct GNUNET_MessageHeader *sync;
1882
1883   env = GNUNET_MQ_msg (sync,
1884                        GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1885   GNUNET_MQ_send (zm->nc->mq,
1886                   env);
1887   /* mark iteration done */
1888   zm->in_first_iteration = GNUNET_NO;
1889   zm->iteration_cnt = 0;
1890   if ( (zm->limit > 0) &&
1891        (zm->sa_waiting) )
1892     monitor_unblock (zm);
1893 }
1894
1895
1896 /**
1897  * Obtain the next datum during the zone monitor's zone initial iteration.
1898  *
1899  * @param cls zone monitor that does its initial iteration
1900  */
1901 static void
1902 monitor_iteration_next (void *cls);
1903
1904
1905 /**
1906  * A #GNUNET_NAMESTORE_RecordIterator for monitors.
1907  *
1908  * @param cls a 'struct ZoneMonitor *' with information about the monitor
1909  * @param seq sequence number of the record
1910  * @param zone_key zone key of the zone
1911  * @param name name
1912  * @param rd_count number of records in @a rd
1913  * @param rd array of records
1914  */
1915 static void
1916 monitor_iterate_cb (void *cls,
1917                     uint64_t seq,
1918                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1919                     const char *name,
1920                     unsigned int rd_count,
1921                     const struct GNUNET_GNSRECORD_Data *rd)
1922 {
1923   struct ZoneMonitor *zm = cls;
1924
1925   zm->seq = seq;
1926   if (NULL == name)
1927   {
1928     /* finished with iteration */
1929     monitor_sync (zm);
1930     return;
1931   }
1932   GNUNET_STATISTICS_update (statistics,
1933                             "Monitor notifications sent",
1934                             1,
1935                             GNUNET_NO);
1936   zm->limit--;
1937   zm->iteration_cnt--;
1938   send_lookup_response (zm->nc,
1939                         0,
1940                         zone_key,
1941                         name,
1942                         rd_count,
1943                         rd);
1944   if ( (0 == zm->iteration_cnt) &&
1945        (0 != zm->limit) )
1946   {
1947     /* We are done with the current iteration batch, AND the
1948        client would right now accept more, so go again! */
1949     GNUNET_assert (NULL == zm->task);
1950     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1951                                          zm);
1952   }
1953 }
1954
1955
1956 /**
1957  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
1958  *
1959  * @param cls the client sending the message
1960  * @param zis_msg message from the client
1961  */
1962 static void
1963 handle_monitor_start (void *cls,
1964                       const struct ZoneMonitorStartMessage *zis_msg)
1965 {
1966   struct NamestoreClient *nc = cls;
1967   struct ZoneMonitor *zm;
1968
1969   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1970               "Received ZONE_MONITOR_START message\n");
1971   zm = GNUNET_new (struct ZoneMonitor);
1972   zm->nc = nc;
1973   zm->zone = zis_msg->zone;
1974   zm->limit = 1;
1975   zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
1976   GNUNET_CONTAINER_DLL_insert (monitor_head,
1977                                monitor_tail,
1978                                zm);
1979   GNUNET_SERVICE_client_mark_monitor (nc->client);
1980   GNUNET_SERVICE_client_continue (nc->client);
1981   GNUNET_notification_context_add (monitor_nc,
1982                                    nc->mq);
1983   if (zm->in_first_iteration)
1984     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
1985                                          zm);
1986   else
1987     monitor_sync (zm);
1988 }
1989
1990
1991 /**
1992  * Obtain the next datum during the zone monitor's zone initial iteration.
1993  *
1994  * @param cls zone monitor that does its initial iteration
1995  */
1996 static void
1997 monitor_iteration_next (void *cls)
1998 {
1999   struct ZoneMonitor *zm = cls;
2000   int ret;
2001
2002   zm->task = NULL;
2003   GNUNET_assert (0 == zm->iteration_cnt);
2004   if (zm->limit > 16)
2005     zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2006   else
2007     zm->iteration_cnt = zm->limit; /* use it all */
2008   ret = GSN_database->iterate_records (GSN_database->cls,
2009                                        (0 == memcmp (&zm->zone,
2010                                                      &zero,
2011                                                      sizeof (zero)))
2012                                        ? NULL
2013                                        : &zm->zone,
2014                                        zm->seq,
2015                                        zm->iteration_cnt,
2016                                        &monitor_iterate_cb,
2017                                        zm);
2018   if (GNUNET_SYSERR == ret)
2019   {
2020     GNUNET_SERVICE_client_drop (zm->nc->client);
2021     return;
2022   }
2023   if (GNUNET_NO == ret)
2024   {
2025     /* empty zone */
2026     monitor_sync (zm);
2027     return;
2028   }
2029 }
2030
2031
2032 /**
2033  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2034  *
2035  * @param cls the client sending the message
2036  * @param nm message from the client
2037  */
2038 static void
2039 handle_monitor_next (void *cls,
2040                      const struct ZoneMonitorNextMessage *nm)
2041 {
2042   struct NamestoreClient *nc = cls;
2043   struct ZoneMonitor *zm;
2044   uint64_t inc;
2045
2046   inc = GNUNET_ntohll (nm->limit);
2047   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2048               "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2049               (unsigned long long) inc);
2050   for (zm = monitor_head; NULL != zm; zm = zm->next)
2051     if (zm->nc == nc)
2052       break;
2053   if (NULL == zm)
2054   {
2055     GNUNET_break (0);
2056     GNUNET_SERVICE_client_drop (nc->client);
2057     return;
2058   }
2059   GNUNET_SERVICE_client_continue (nc->client);
2060   if (zm->limit + inc < zm->limit)
2061   {
2062     GNUNET_break (0);
2063     GNUNET_SERVICE_client_drop (nc->client);
2064     return;
2065   }
2066   zm->limit += inc;
2067   if ( (zm->in_first_iteration) &&
2068        (zm->limit == inc) )
2069   {
2070     /* We are still iterating, and the previous iteration must
2071        have stopped due to the client's limit, so continue it! */
2072     GNUNET_assert (NULL == zm->task);
2073     zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next,
2074                                          zm);
2075   }
2076   GNUNET_assert (zm->iteration_cnt <= zm->limit);
2077   if ( (zm->limit > zm->iteration_cnt) &&
2078        (zm->sa_waiting) )
2079   {
2080     monitor_unblock (zm);
2081   }
2082   else if (GNUNET_YES == zm->sa_waiting)
2083   {
2084     if (NULL != zm->sa_wait_warning)
2085       GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2086     zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2087     zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2088                                                         &warn_monitor_slow,
2089                                                         zm);
2090   }
2091 }
2092
2093
2094 /**
2095  * Process namestore requests.
2096  *
2097  * @param cls closure
2098  * @param cfg configuration to use
2099  * @param service the initialized service
2100  */
2101 static void
2102 run (void *cls,
2103      const struct GNUNET_CONFIGURATION_Handle *cfg,
2104      struct GNUNET_SERVICE_Handle *service)
2105 {
2106   char *database;
2107
2108   (void) cls;
2109   (void) service;
2110   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2111               "Starting namestore service\n");
2112   cache_keys = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2113                                                      "namestore",
2114                                                      "CACHE_KEYS");
2115   disable_namecache = GNUNET_CONFIGURATION_get_value_yesno (cfg,
2116                                                             "namecache",
2117                                                             "DISABLE");
2118   GSN_cfg = cfg;
2119   monitor_nc = GNUNET_notification_context_create (1);
2120   if (GNUNET_YES != disable_namecache)
2121   {
2122     namecache = GNUNET_NAMECACHE_connect (cfg);
2123     GNUNET_assert (NULL != namecache);
2124   }
2125   /* Loading database plugin */
2126   if (GNUNET_OK !=
2127       GNUNET_CONFIGURATION_get_value_string (cfg,
2128                                              "namestore",
2129                                              "database",
2130                                              &database))
2131     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2132                 "No database backend configured\n");
2133
2134   GNUNET_asprintf (&db_lib_name,
2135                    "libgnunet_plugin_namestore_%s",
2136                    database);
2137   GSN_database = GNUNET_PLUGIN_load (db_lib_name,
2138                                      (void *) GSN_cfg);
2139   GNUNET_free (database);
2140   statistics = GNUNET_STATISTICS_create ("namestore",
2141                                          cfg);
2142   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
2143                                  NULL);
2144   if (NULL == GSN_database)
2145   {
2146     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2147                 "Could not load database backend `%s'\n",
2148                 db_lib_name);
2149     GNUNET_SCHEDULER_shutdown ();
2150     return;
2151   }
2152 }
2153
2154
2155 /**
2156  * Define "main" method using service macro.
2157  */
2158 GNUNET_SERVICE_MAIN
2159 ("namestore",
2160  GNUNET_SERVICE_OPTION_NONE,
2161  &run,
2162  &client_connect_cb,
2163  &client_disconnect_cb,
2164  NULL,
2165  GNUNET_MQ_hd_var_size (record_store,
2166                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2167                         struct RecordStoreMessage,
2168                         NULL),
2169  GNUNET_MQ_hd_var_size (record_lookup,
2170                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2171                         struct LabelLookupMessage,
2172                         NULL),
2173  GNUNET_MQ_hd_fixed_size (zone_to_name,
2174                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2175                           struct ZoneToNameMessage,
2176                           NULL),
2177  GNUNET_MQ_hd_fixed_size (iteration_start,
2178                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2179                           struct ZoneIterationStartMessage,
2180                           NULL),
2181  GNUNET_MQ_hd_fixed_size (iteration_next,
2182                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2183                           struct ZoneIterationNextMessage,
2184                           NULL),
2185  GNUNET_MQ_hd_fixed_size (iteration_stop,
2186                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2187                           struct ZoneIterationStopMessage,
2188                           NULL),
2189  GNUNET_MQ_hd_fixed_size (monitor_start,
2190                           GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2191                           struct ZoneMonitorStartMessage,
2192                           NULL),
2193  GNUNET_MQ_hd_fixed_size (monitor_next,
2194                           GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2195                           struct ZoneMonitorNextMessage,
2196                           NULL),
2197  GNUNET_MQ_handler_end ());
2198
2199
2200 /* end of gnunet-service-namestore.c */