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