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