avoid specifying useless DEFAULT values
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2014 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 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsparser_lib.h"
30 #include "gnunet_gns_service.h"
31 #include "gnunet_namecache_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_namestore_plugin.h"
34 #include "gnunet_signatures.h"
35 #include "namestore.h"
36
37 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
38
39
40 /**
41  * A namestore client
42  */
43 struct NamestoreClient;
44
45
46 /**
47  * A namestore iteration operation.
48  */
49 struct ZoneIteration
50 {
51   /**
52    * Next element in the DLL
53    */
54   struct ZoneIteration *next;
55
56   /**
57    * Previous element in the DLL
58    */
59   struct ZoneIteration *prev;
60
61   /**
62    * Namestore client which intiated this zone iteration
63    */
64   struct NamestoreClient *nc;
65
66   /**
67    * The nick to add to the records
68    */
69   struct GNUNET_GNSRECORD_Data *nick;
70
71   /**
72    * Key of the zone we are iterating over.
73    */
74   struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
75
76   /**
77    * The operation id fot the zone iteration in the response for the client
78    */
79   uint32_t request_id;
80
81   /**
82    * Offset of the zone iteration used to address next result of the zone
83    * iteration in the store
84    *
85    * Initialy set to 0 in handle_iteration_start
86    * Incremented with by every call to handle_iteration_next
87    */
88   uint32_t offset;
89
90 };
91
92
93 /**
94  * A namestore client
95  */
96 struct NamestoreClient
97 {
98
99   /**
100    * The client
101    */
102   struct GNUNET_SERVICE_Client *client;
103
104   /**
105    * Message queue for transmission to @e client
106    */
107   struct GNUNET_MQ_Handle *mq;
108
109   /**
110    * Head of the DLL of
111    * Zone iteration operations in progress initiated by this client
112    */
113   struct ZoneIteration *op_head;
114
115   /**
116    * Tail of the DLL of
117    * Zone iteration operations in progress initiated by this client
118    */
119   struct ZoneIteration *op_tail;
120 };
121
122
123 /**
124  * A namestore monitor.
125  */
126 struct ZoneMonitor
127 {
128   /**
129    * Next element in the DLL
130    */
131   struct ZoneMonitor *next;
132
133   /**
134    * Previous element in the DLL
135    */
136   struct ZoneMonitor *prev;
137
138   /**
139    * Namestore client which intiated this zone monitor
140    */
141   struct NamestoreClient *nc;
142
143   /**
144    * Private key of the zone.
145    */
146   struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
147
148   /**
149    * Task active during initial iteration.
150    */
151   struct GNUNET_SCHEDULER_Task *task;
152
153   /**
154    * Offset of the zone iteration used to address next result of the zone
155    * iteration in the store
156    *
157    * Initialy set to 0.
158    * Incremented with by every call to #handle_iteration_next
159    */
160   uint32_t offset;
161
162 };
163
164
165 /**
166  * Pending operation on the namecache.
167  */
168 struct CacheOperation
169 {
170
171   /**
172    * Kept in a DLL.
173    */
174   struct CacheOperation *prev;
175
176   /**
177    * Kept in a DLL.
178    */
179   struct CacheOperation *next;
180
181   /**
182    * Handle to namecache queue.
183    */
184   struct GNUNET_NAMECACHE_QueueEntry *qe;
185
186   /**
187    * Client to notify about the result.
188    */
189   struct NamestoreClient *nc;
190
191   /**
192    * Client's request ID.
193    */
194   uint32_t rid;
195 };
196
197
198 /**
199  * Public key of all zeros.
200  */
201 static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
202
203 /**
204  * Configuration handle.
205  */
206 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
207
208 /**
209  * Namecache handle.
210  */
211 static struct GNUNET_NAMECACHE_Handle *namecache;
212
213 /**
214  * Database handle
215  */
216 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
217
218 /**
219  * Name of the database plugin
220  */
221 static char *db_lib_name;
222
223 /**
224  * Head of cop DLL.
225  */
226 static struct CacheOperation *cop_head;
227
228 /**
229  * Tail of cop DLL.
230  */
231 static struct CacheOperation *cop_tail;
232
233 /**
234  * First active zone monitor.
235  */
236 static struct ZoneMonitor *monitor_head;
237
238 /**
239  * Last active zone monitor.
240  */
241 static struct ZoneMonitor *monitor_tail;
242
243 /**
244  * Notification context shared by all monitors.
245  */
246 static struct GNUNET_NotificationContext *monitor_nc;
247
248
249 /**
250  * Task run during shutdown.
251  *
252  * @param cls unused
253  */
254 static void
255 cleanup_task (void *cls)
256 {
257   struct CacheOperation *cop;
258
259   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
260               "Stopping namestore service\n");
261   while (NULL != (cop = cop_head))
262   {
263     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
264                 "Aborting incomplete namecache operation\n");
265     GNUNET_NAMECACHE_cancel (cop->qe);
266     GNUNET_CONTAINER_DLL_remove (cop_head,
267                                  cop_tail,
268                                  cop);
269     GNUNET_free (cop);
270   }
271   GNUNET_NAMECACHE_disconnect (namecache);
272   namecache = NULL;
273   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
274                                               GSN_database));
275   GNUNET_free (db_lib_name);
276   db_lib_name = NULL;
277   if (NULL != monitor_nc)
278   {
279     GNUNET_notification_context_destroy (monitor_nc);
280     monitor_nc = NULL;
281   }
282 }
283
284
285 /**
286  * Called whenever a client is disconnected.
287  * Frees our resources associated with that client.
288  *
289  * @param cls closure
290  * @param client identification of the client
291  * @param app_ctx the `struct NamestoreClient` of @a client
292  */
293 static void
294 client_disconnect_cb (void *cls,
295                       struct GNUNET_SERVICE_Client *client,
296                       void *app_ctx)
297 {
298   struct NamestoreClient *nc = app_ctx;
299   struct ZoneIteration *no;
300   struct ZoneMonitor *zm;
301   struct CacheOperation *cop;
302
303   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304               "Client %p disconnected\n",
305               client);
306   for (zm = monitor_head; NULL != zm; zm = zm->next)
307   {
308     if (nc == zm->nc)
309     {
310       GNUNET_CONTAINER_DLL_remove (monitor_head,
311                                    monitor_tail,
312                                    zm);
313       if (NULL != zm->task)
314       {
315         GNUNET_SCHEDULER_cancel (zm->task);
316         zm->task = NULL;
317       }
318       GNUNET_free (zm);
319       break;
320     }
321   }
322   while (NULL != (no = nc->op_head))
323   {
324     GNUNET_CONTAINER_DLL_remove (nc->op_head,
325                                  nc->op_tail,
326                                  no);
327     GNUNET_free (no);
328   }
329   for (cop = cop_head; NULL != cop; cop = cop->next)
330     if (nc == cop->nc)
331       cop->nc = NULL;
332   GNUNET_free (nc);
333 }
334
335
336 /**
337  * Add a client to our list of active clients.
338  *
339  * @param cls NULL
340  * @param client client to add
341  * @param mq message queue for @a client
342  * @return internal namestore client structure for this client
343  */
344 static void *
345 client_connect_cb (void *cls,
346                    struct GNUNET_SERVICE_Client *client,
347                    struct GNUNET_MQ_Handle *mq)
348 {
349   struct NamestoreClient *nc;
350
351   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
352               "Client %p connected\n",
353               client);
354   nc = GNUNET_new (struct NamestoreClient);
355   nc->client = client;
356   nc->mq = mq;
357   return nc;
358 }
359
360
361 /**
362  * Function called with the records for the #GNUNET_GNS_MASTERZONE_STR
363  * label in the zone.  Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
364  * record, which (if found) is then copied to @a cls for future use.
365  *
366  * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
367  * @param private_key the private key of the zone (unused)
368  * @param label should be #GNUNET_GNS_MASTERZONE_STR
369  * @param rd_count number of records in @a rd
370  * @param rd records stored under @a label in the zone
371  */
372 static void
373 lookup_nick_it (void *cls,
374                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
375                 const char *label,
376                 unsigned int rd_count,
377                 const struct GNUNET_GNSRECORD_Data *rd)
378 {
379   struct GNUNET_GNSRECORD_Data **res = cls;
380
381   if (0 != strcmp (label, GNUNET_GNS_MASTERZONE_STR))
382   {
383     GNUNET_break (0);
384     return;
385   }
386   for (unsigned int c = 0; c < rd_count; c++)
387   {
388     if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
389     {
390       (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data));
391       (*res)->data = &(*res)[1];
392       GNUNET_memcpy ((void *) (*res)->data,
393                      rd[c].data,
394                      rd[c].data_size);
395       (*res)->data_size = rd[c].data_size;
396       (*res)->expiration_time = rd[c].expiration_time;
397       (*res)->flags = rd[c].flags;
398       (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
399       return;
400     }
401   }
402   (*res) = NULL;
403 }
404
405
406 /**
407  * Return the NICK record for the zone (if it exists).
408  *
409  * @param zone private key for the zone to look for nick
410  * @return NULL if no NICK record was found
411  */
412 static struct GNUNET_GNSRECORD_Data *
413 get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone)
414 {
415   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
416   struct GNUNET_GNSRECORD_Data *nick;
417   int res;
418
419   nick = NULL;
420   res = GSN_database->lookup_records (GSN_database->cls,
421                                       zone,
422                                       GNUNET_GNS_MASTERZONE_STR,
423                                       &lookup_nick_it,
424                                       &nick);
425   if ( (GNUNET_OK != res) ||
426        (NULL == nick) )
427   {
428     GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub);
429     GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
430                 "No nick name set for zone `%s'\n",
431                 GNUNET_GNSRECORD_z2s (&pub));
432     return NULL;
433   }
434   return nick;
435 }
436
437
438 static void
439 merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
440                          unsigned int rdc2,
441                          const struct GNUNET_GNSRECORD_Data *rd2,
442                          unsigned int *rdc_res,
443                          struct GNUNET_GNSRECORD_Data **rd_res)
444 {
445   uint64_t latest_expiration;
446   size_t req;
447   char *data;
448   int record_offset;
449   size_t data_offset;
450
451   (*rdc_res) = 1 + rdc2;
452   if (0 == 1 + rdc2)
453   {
454     (*rd_res) = NULL;
455     return;
456   }
457
458   req = 0;
459   for (unsigned int c=0; c< 1; c++)
460     req += sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd[c].data_size;
461   for (unsigned int c=0; c< rdc2; c++)
462     req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size;
463   (*rd_res) = GNUNET_malloc (req);
464   data = (char *) &(*rd_res)[1 + rdc2];
465   data_offset = 0;
466   latest_expiration = 0;
467
468   for (unsigned int c=0; c< rdc2; c++)
469   {
470     if (0 != (rd2[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
471     {
472       if ((GNUNET_TIME_absolute_get().abs_value_us + rd2[c].expiration_time) >
473         latest_expiration)
474           latest_expiration = rd2[c].expiration_time;
475     }
476     else if (rd2[c].expiration_time > latest_expiration)
477       latest_expiration = rd2[c].expiration_time;
478     (*rd_res)[c] = rd2[c];
479     (*rd_res)[c].data = (void *) &data[data_offset];
480     GNUNET_memcpy ((void *) (*rd_res)[c].data,
481                    rd2[c].data,
482                    rd2[c].data_size);
483     data_offset += (*rd_res)[c].data_size;
484   }
485   record_offset = rdc2;
486   for (unsigned int c=0; c< 1; c++)
487   {
488     (*rd_res)[c+record_offset] = nick_rd[c];
489     (*rd_res)[c+record_offset].expiration_time = latest_expiration;
490     (*rd_res)[c+record_offset].data = (void *) &data[data_offset];
491     GNUNET_memcpy ((void *) (*rd_res)[c+record_offset].data,
492                    nick_rd[c].data,
493                    nick_rd[c].data_size);
494     data_offset += (*rd_res)[c+record_offset].data_size;
495   }
496   GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset);
497 }
498
499
500 /**
501  * Generate a `struct LookupNameResponseMessage` and send it to the
502  * given client using the given notification context.
503  *
504  * @param nc client to unicast to
505  * @param request_id request ID to use
506  * @param zone_key zone key of the zone
507  * @param name name
508  * @param rd_count number of records in @a rd
509  * @param rd array of records
510  */
511 static void
512 send_lookup_response (struct NamestoreClient *nc,
513                       uint32_t request_id,
514                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
515                       const char *name,
516                       unsigned int rd_count,
517                       const struct GNUNET_GNSRECORD_Data *rd)
518 {
519   struct GNUNET_MQ_Envelope *env;
520   struct RecordResultMessage *zir_msg;
521   struct GNUNET_GNSRECORD_Data *nick;
522   struct GNUNET_GNSRECORD_Data *res;
523   unsigned int res_count;
524   size_t name_len;
525   size_t rd_ser_len;
526   char *name_tmp;
527   char *rd_ser;
528
529   nick = get_nick_record (zone_key);
530   if ((NULL != nick) && (0 != strcmp(name, GNUNET_GNS_MASTERZONE_STR)))
531   {
532     nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
533     merge_with_nick_records (nick,
534                              rd_count,
535                              rd,
536                              &res_count,
537                              &res);
538     GNUNET_free (nick);
539   }
540   else
541   {
542     res_count = rd_count;
543     res = (struct GNUNET_GNSRECORD_Data *) rd;
544   }
545
546   name_len = strlen (name) + 1;
547   rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
548   env = GNUNET_MQ_msg_extra (zir_msg,
549                              name_len + rd_ser_len,
550                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
551   zir_msg->gns_header.r_id = htonl (request_id);
552   zir_msg->name_len = htons (name_len);
553   zir_msg->rd_count = htons (res_count);
554   zir_msg->rd_len = htons (rd_ser_len);
555   zir_msg->private_key = *zone_key;
556   name_tmp = (char *) &zir_msg[1];
557   GNUNET_memcpy (name_tmp,
558                  name,
559                  name_len);
560   rd_ser = &name_tmp[name_len];
561   GNUNET_GNSRECORD_records_serialize (res_count,
562                                       res,
563                                       rd_ser_len,
564                                       rd_ser);
565   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
566               "Sending RECORD_RESULT message with %u records\n",
567               res_count);
568   GNUNET_MQ_send (nc->mq,
569                   env);
570   if (rd != res)
571     GNUNET_free (res);
572 }
573
574
575 /**
576  * Send response to the store request to the client.
577  *
578  * @param client client to talk to
579  * @param res status of the operation
580  * @param rid client's request ID
581  */
582 static void
583 send_store_response (struct NamestoreClient *nc,
584                      int res,
585                      uint32_t rid)
586 {
587   struct GNUNET_MQ_Envelope *env;
588   struct RecordStoreResponseMessage *rcr_msg;
589
590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
591               "Sending RECORD_STORE_RESPONSE message\n");
592   env = GNUNET_MQ_msg (rcr_msg,
593                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
594   rcr_msg->gns_header.r_id = htonl (rid);
595   rcr_msg->op_result = htonl (res);
596   GNUNET_MQ_send (nc->mq,
597                   env);
598 }
599
600
601 /**
602  * Cache operation complete, clean up.
603  *
604  * @param cls the `struct CacheOperation`
605  * @param success success
606  * @param emsg error messages
607  */
608 static void
609 finish_cache_operation (void *cls,
610                         int32_t success,
611                         const char *emsg)
612 {
613   struct CacheOperation *cop = cls;
614
615   if (NULL != emsg)
616     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
617                 _("Failed to replicate block in namecache: %s\n"),
618                 emsg);
619   else
620     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
621                 "CACHE operation completed\n");
622   GNUNET_CONTAINER_DLL_remove (cop_head,
623                                cop_tail,
624                                cop);
625   if (NULL != cop->nc)
626     send_store_response (cop->nc,
627                          success,
628                          cop->rid);
629   GNUNET_free (cop);
630 }
631
632
633 /**
634  * We just touched the plaintext information about a name in our zone;
635  * refresh the corresponding (encrypted) block in the namecache.
636  *
637  * @param nc client responsible for the request, can be NULL
638  * @param rid request ID of the client
639  * @param zone_key private key of the zone
640  * @param name label for the records
641  * @param rd_count number of records
642  * @param rd records stored under the given @a name
643  */
644 static void
645 refresh_block (struct NamestoreClient *nc,
646                uint32_t rid,
647                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
648                const char *name,
649                unsigned int rd_count,
650                const struct GNUNET_GNSRECORD_Data *rd)
651 {
652   struct GNUNET_GNSRECORD_Block *block;
653   struct CacheOperation *cop;
654   struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
655   struct GNUNET_GNSRECORD_Data *nick;
656   struct GNUNET_GNSRECORD_Data *res;
657   unsigned int res_count;
658
659   nick = get_nick_record (zone_key);
660   res_count = rd_count;
661   res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
662   if (NULL != nick)
663   {
664     nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
665     merge_with_nick_records (nick,
666                              rd_count,rd,
667                              &res_count,
668                              &res);
669     GNUNET_free (nick);
670   }
671
672   if (0 == res_count)
673     block = GNUNET_GNSRECORD_block_create (zone_key,
674                                            GNUNET_TIME_UNIT_ZERO_ABS,
675                                            name,
676                                            res, rd_count);
677   else
678     block = GNUNET_GNSRECORD_block_create (zone_key,
679                                            GNUNET_GNSRECORD_record_get_expiration_time (res_count,
680                                                res),
681                                            name,
682                                            res, res_count);
683   GNUNET_assert (NULL != block);
684   GNUNET_CRYPTO_ecdsa_key_get_public (zone_key,
685                                       &pkey);
686   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687               "Caching block for label `%s' with %u records in zone `%s' in namecache\n",
688               name,
689               res_count,
690               GNUNET_GNSRECORD_z2s (&pkey));
691   cop = GNUNET_new (struct CacheOperation);
692   cop->nc = nc;
693   cop->rid = rid;
694   GNUNET_CONTAINER_DLL_insert (cop_head,
695                                cop_tail,
696                                cop);
697   cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
698                                           block,
699                                           &finish_cache_operation,
700                                           cop);
701   GNUNET_free (block);
702 }
703
704
705 /**
706  * Closure for #lookup_it().
707  */
708 struct RecordLookupContext
709 {
710   const char *label;
711
712   int found;
713
714   unsigned int res_rd_count;
715
716   size_t rd_ser_len;
717
718   char *res_rd;
719
720   struct GNUNET_GNSRECORD_Data *nick;
721 };
722
723
724 static void
725 lookup_it (void *cls,
726            const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key,
727            const char *label,
728            unsigned int rd_count,
729            const struct GNUNET_GNSRECORD_Data *rd)
730 {
731   struct RecordLookupContext *rlc = cls;
732   struct GNUNET_GNSRECORD_Data *rd_res;
733   unsigned int rdc_res;
734
735   if (0 == strcmp (label, rlc->label))
736   {
737     rlc->found = GNUNET_YES;
738     if (0 != rd_count)
739     {
740       if ( (NULL != rlc->nick) &&
741            (0 != strcmp (label,
742                          GNUNET_GNS_MASTERZONE_STR)) )
743       {
744         /* Merge */
745         rd_res = NULL;
746         rdc_res = 0;
747         rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
748         merge_with_nick_records (rlc->nick,
749                                  rd_count, rd,
750                                  &rdc_res, &rd_res);
751
752         rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res,
753                                                              rd_res);
754         rlc->res_rd_count = rdc_res;
755         rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
756         GNUNET_GNSRECORD_records_serialize (rdc_res,
757                                             rd_res,
758                                             rlc->rd_ser_len,
759                                             rlc->res_rd);
760
761         GNUNET_free  (rd_res);
762         GNUNET_free  (rlc->nick);
763         rlc->nick = NULL;
764       }
765       else
766       {
767         rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count,
768                                                              rd);
769         rlc->res_rd_count = rd_count;
770         rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
771         GNUNET_GNSRECORD_records_serialize (rd_count,
772                                             rd,
773                                             rlc->rd_ser_len,
774                                             rlc->res_rd);
775       }
776     }
777     else
778     {
779       rlc->rd_ser_len = 0;
780       rlc->res_rd_count = 0;
781       rlc->res_rd = NULL;
782     }
783   }
784 }
785
786
787 /**
788  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
789  *
790  * @param cls client sending the message
791  * @param ll_msg message of type `struct LabelLookupMessage`
792  * @return #GNUNET_OK if @a ll_msg is well-formed
793  */
794 static int
795 check_record_lookup (void *cls,
796                      const struct LabelLookupMessage *ll_msg)
797 {
798   uint32_t name_len;
799   size_t src_size;
800   const char *name_tmp;
801
802   name_len = ntohl (ll_msg->label_len);
803   src_size = ntohs (ll_msg->gns_header.header.size);
804   if (name_len != src_size - sizeof (struct LabelLookupMessage))
805   {
806     GNUNET_break (0);
807     return GNUNET_SYSERR;
808   }
809
810   name_tmp = (const char *) &ll_msg[1];
811   if ('\0' != name_tmp[name_len -1])
812   {
813     GNUNET_break (0);
814     return GNUNET_SYSERR;
815   }
816   return GNUNET_OK;
817 }
818
819
820 /**
821  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
822  *
823  * @param cls client sending the message
824  * @param ll_msg message of type `struct LabelLookupMessage`
825  */
826 static void
827 handle_record_lookup (void *cls,
828                       const struct LabelLookupMessage *ll_msg)
829 {
830   struct NamestoreClient *nc = cls;
831   struct GNUNET_MQ_Envelope *env;
832   struct LabelLookupResponseMessage *llr_msg;
833   struct RecordLookupContext rlc;
834   const char *name_tmp;
835   char *res_name;
836   char *conv_name;
837   uint32_t name_len;
838   int res;
839
840   name_len = ntohl (ll_msg->label_len);
841   name_tmp = (const char *) &ll_msg[1];
842   GNUNET_SERVICE_client_continue (nc->client);
843   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
844               "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
845               name_tmp);
846
847   conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
848   if (NULL == conv_name)
849   {
850     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
851                 "Error converting name `%s'\n",
852                 name_tmp);
853     GNUNET_SERVICE_client_drop (nc->client);
854     return;
855   }
856   rlc.label = conv_name;
857   rlc.found = GNUNET_NO;
858   rlc.res_rd_count = 0;
859   rlc.res_rd = NULL;
860   rlc.rd_ser_len = 0;
861   rlc.nick = get_nick_record (&ll_msg->zone);
862   res = GSN_database->lookup_records (GSN_database->cls,
863                                       &ll_msg->zone,
864                                       conv_name,
865                                       &lookup_it,
866                                       &rlc);
867   GNUNET_free (conv_name);
868   env = GNUNET_MQ_msg_extra (llr_msg,
869                              name_len + rlc.rd_ser_len,
870                              GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
871   llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
872   llr_msg->private_key = ll_msg->zone;
873   llr_msg->name_len = htons (name_len);
874   llr_msg->rd_count = htons (rlc.res_rd_count);
875   llr_msg->rd_len = htons (rlc.rd_ser_len);
876   res_name = (char *) &llr_msg[1];
877   if  ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
878     llr_msg->found = ntohs (GNUNET_YES);
879   else
880     llr_msg->found = ntohs (GNUNET_NO);
881   GNUNET_memcpy (&llr_msg[1],
882                  name_tmp,
883                  name_len);
884   GNUNET_memcpy (&res_name[name_len],
885                  rlc.res_rd,
886                  rlc.rd_ser_len);
887   GNUNET_MQ_send (nc->mq,
888                   env);
889   GNUNET_free_non_null (rlc.res_rd);
890 }
891
892
893 /**
894  * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
895  *
896  * @param cls client sending the message
897  * @param rp_msg message of type `struct RecordStoreMessage`
898  * @return #GNUNET_OK if @a rp_msg is well-formed
899  */
900 static int
901 check_record_store (void *cls,
902                     const struct RecordStoreMessage *rp_msg)
903 {
904   size_t name_len;
905   size_t msg_size;
906   size_t msg_size_exp;
907   size_t rd_ser_len;
908   const char *name_tmp;
909
910   name_len = ntohs (rp_msg->name_len);
911   msg_size = ntohs (rp_msg->gns_header.header.size);
912   rd_ser_len = ntohs (rp_msg->rd_len);
913   msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len;
914   if (msg_size != msg_size_exp)
915   {
916     GNUNET_break (0);
917     return GNUNET_SYSERR;
918   }
919   if ((0 == name_len) || (name_len > MAX_NAME_LEN))
920   {
921     GNUNET_break (0);
922     return GNUNET_SYSERR;
923   }
924   name_tmp = (const char *) &rp_msg[1];
925   if ('\0' != name_tmp[name_len -1])
926   {
927     GNUNET_break (0);
928     return GNUNET_SYSERR;
929   }
930   return GNUNET_OK;
931 }
932
933
934 /**
935  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
936  *
937  * @param cls client sending the message
938  * @param rp_msg message of type `struct RecordStoreMessage`
939  */
940 static void
941 handle_record_store (void *cls,
942                      const struct RecordStoreMessage *rp_msg)
943 {
944   struct NamestoreClient *nc = cls;
945   size_t name_len;
946   size_t rd_ser_len;
947   uint32_t rid;
948   const char *name_tmp;
949   char *conv_name;
950   const char *rd_ser;
951   unsigned int rd_count;
952   int res;
953   struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
954   struct ZoneMonitor *zm;
955
956   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
957               "Received NAMESTORE_RECORD_STORE message\n");
958   rid = ntohl (rp_msg->gns_header.r_id);
959   name_len = ntohs (rp_msg->name_len);
960   rd_count = ntohs (rp_msg->rd_count);
961   rd_ser_len = ntohs (rp_msg->rd_len);
962   GNUNET_break (0 == ntohs (rp_msg->reserved));
963   name_tmp = (const char *) &rp_msg[1];
964   rd_ser = &name_tmp[name_len];
965   {
966     struct GNUNET_GNSRECORD_Data rd[rd_count];
967
968     if (GNUNET_OK !=
969         GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
970                                               rd_ser,
971                                               rd_count,
972                                               rd))
973     {
974       GNUNET_break (0);
975       GNUNET_SERVICE_client_drop (nc->client);
976       return;
977     }
978
979     /* Extracting and converting private key */
980     GNUNET_CRYPTO_ecdsa_key_get_public (&rp_msg->private_key,
981                                         &pubkey);
982     conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
983     if (NULL == conv_name)
984     {
985       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
986                   "Error converting name `%s'\n",
987                   name_tmp);
988       GNUNET_SERVICE_client_drop (nc->client);
989       return;
990     }
991     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992                 "Creating %u records for name `%s' in zone `%s'\n",
993                 (unsigned int) rd_count,
994                 conv_name,
995                 GNUNET_GNSRECORD_z2s (&pubkey));
996
997     if ( (0 == rd_count) &&
998          (GNUNET_NO ==
999           GSN_database->iterate_records (GSN_database->cls,
1000                                          &rp_msg->private_key,
1001                                          0,
1002                                          NULL,
1003                                          0)) )
1004     {
1005       /* This name does not exist, so cannot be removed */
1006       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007                   "Name `%s' does not exist, no deletion required\n",
1008                   conv_name);
1009       res = GNUNET_NO;
1010     }
1011     else
1012     {
1013       struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
1014       unsigned int rd_clean_off;
1015
1016       /* remove "NICK" records, unless this is for the
1017          #GNUNET_GNS_MASTERZONE_STR label */
1018       rd_clean_off = 0;
1019       for (unsigned int i=0;i<rd_count;i++)
1020       {
1021         rd_clean[rd_clean_off] = rd[i];
1022         if ( (0 == strcmp (GNUNET_GNS_MASTERZONE_STR,
1023                            conv_name)) ||
1024              (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type) )
1025           rd_clean_off++;
1026       }
1027       res = GSN_database->store_records (GSN_database->cls,
1028                                          &rp_msg->private_key,
1029                                          conv_name,
1030                                          rd_clean_off,
1031                                          rd_clean);
1032       if (GNUNET_OK == res)
1033       {
1034         for (zm = monitor_head; NULL != zm; zm = zm->next)
1035         {
1036           if ( (0 == memcmp (&rp_msg->private_key, &zm->zone,
1037                              sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) ||
1038                (0 == memcmp (&zm->zone,
1039                              &zero,
1040                              sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
1041           {
1042             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043                         "Notifying monitor about changes under label `%s'\n",
1044                         conv_name);
1045             send_lookup_response (zm->nc,
1046                                   0,
1047                                   &rp_msg->private_key,
1048                                   conv_name,
1049                                   rd_count, rd);
1050           }
1051           else
1052             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1053                         "Monitor is for another zone\n");
1054         }
1055         if (NULL == monitor_head)
1056           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1057                       "No monitors active\n");
1058       }
1059       else
1060       {
1061         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1062                     "Error storing record: %d\n",
1063                     res);
1064       }
1065     }
1066     if (GNUNET_OK == res)
1067     {
1068       refresh_block (nc,
1069                      rid,
1070                      &rp_msg->private_key,
1071                      conv_name,
1072                      rd_count,
1073                      rd);
1074       GNUNET_SERVICE_client_continue (nc->client);
1075       GNUNET_free (conv_name);
1076       return;
1077     }
1078     GNUNET_free (conv_name);
1079   }
1080   send_store_response (nc,
1081                        res,
1082                        rid);
1083   GNUNET_SERVICE_client_continue (nc->client);
1084 }
1085
1086
1087 /**
1088  * Context for record remove operations passed from #handle_zone_to_name to
1089  * #handle_zone_to_name_it as closure
1090  */
1091 struct ZoneToNameCtx
1092 {
1093   /**
1094    * Namestore client
1095    */
1096   struct NamestoreClient *nc;
1097
1098   /**
1099    * Request id (to be used in the response to the client).
1100    */
1101   uint32_t rid;
1102
1103   /**
1104    * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error.  Note that
1105    * not finding a name for the zone still counts as a 'success' here,
1106    * as this field is about the success of executing the IPC protocol.
1107    */
1108   int success;
1109 };
1110
1111
1112 /**
1113  * Zone to name iterator
1114  *
1115  * @param cls struct ZoneToNameCtx *
1116  * @param zone_key the zone key
1117  * @param name name
1118  * @param rd_count number of records in @a rd
1119  * @param rd record data
1120  */
1121 static void
1122 handle_zone_to_name_it (void *cls,
1123                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1124                         const char *name,
1125                         unsigned int rd_count,
1126                         const struct GNUNET_GNSRECORD_Data *rd)
1127 {
1128   struct ZoneToNameCtx *ztn_ctx = cls;
1129   struct GNUNET_MQ_Envelope *env;
1130   struct ZoneToNameResponseMessage *ztnr_msg;
1131   int16_t res;
1132   size_t name_len;
1133   size_t rd_ser_len;
1134   size_t msg_size;
1135   char *name_tmp;
1136   char *rd_tmp;
1137
1138   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1139               "Found result for zone-to-name lookup: `%s'\n",
1140               name);
1141   res = GNUNET_YES;
1142   name_len = (NULL == name) ? 0 : strlen (name) + 1;
1143   rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1144   msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1145   if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1146   {
1147     GNUNET_break (0);
1148     ztn_ctx->success = GNUNET_SYSERR;
1149     return;
1150   }
1151   env = GNUNET_MQ_msg_extra (ztnr_msg,
1152                              name_len + rd_ser_len,
1153                              GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1154   ztnr_msg->gns_header.header.size = htons (msg_size);
1155   ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1156   ztnr_msg->res = htons (res);
1157   ztnr_msg->rd_len = htons (rd_ser_len);
1158   ztnr_msg->rd_count = htons (rd_count);
1159   ztnr_msg->name_len = htons (name_len);
1160   ztnr_msg->zone = *zone_key;
1161   name_tmp = (char *) &ztnr_msg[1];
1162   GNUNET_memcpy (name_tmp,
1163                  name,
1164                  name_len);
1165   rd_tmp = &name_tmp[name_len];
1166   GNUNET_GNSRECORD_records_serialize (rd_count,
1167                                       rd,
1168                                       rd_ser_len,
1169                                       rd_tmp);
1170   ztn_ctx->success = GNUNET_OK;
1171   GNUNET_MQ_send (ztn_ctx->nc->mq,
1172                   env);
1173 }
1174
1175
1176 /**
1177  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1178  *
1179  * @param cls client client sending the message
1180  * @param ztn_msg message of type 'struct ZoneToNameMessage'
1181  */
1182 static void
1183 handle_zone_to_name (void *cls,
1184                      const struct ZoneToNameMessage *ztn_msg)
1185 {
1186   struct NamestoreClient *nc = cls;
1187   struct ZoneToNameCtx ztn_ctx;
1188   struct GNUNET_MQ_Envelope *env;
1189   struct ZoneToNameResponseMessage *ztnr_msg;
1190
1191   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1192               "Received `%s' message\n",
1193               "ZONE_TO_NAME");
1194   ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1195   ztn_ctx.nc = nc;
1196   ztn_ctx.success = GNUNET_NO;
1197   if (GNUNET_SYSERR ==
1198       GSN_database->zone_to_name (GSN_database->cls,
1199                                   &ztn_msg->zone,
1200                                   &ztn_msg->value_zone,
1201                                   &handle_zone_to_name_it, &ztn_ctx))
1202   {
1203     /* internal error, hang up instead of signalling something
1204        that might be wrong */
1205     GNUNET_break (0);
1206     GNUNET_SERVICE_client_drop (nc->client);
1207     return;
1208   }
1209   if (GNUNET_NO == ztn_ctx.success)
1210   {
1211     /* no result found, send empty response */
1212     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213                 "Found no result for zone-to-name lookup.\n");
1214     env = GNUNET_MQ_msg (ztnr_msg,
1215                          GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1216     ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1217     ztnr_msg->res = htons (GNUNET_NO);
1218     GNUNET_MQ_send (nc->mq,
1219                     env);
1220   }
1221   GNUNET_SERVICE_client_continue (nc->client);
1222 }
1223
1224
1225 /**
1226  * Zone iteration processor result
1227  */
1228 enum ZoneIterationResult
1229 {
1230   /**
1231    * Iteration start.
1232    */
1233   IT_START = 0,
1234
1235   /**
1236    * Found records,
1237    * Continue to iterate with next iteration_next call
1238    */
1239   IT_SUCCESS_MORE_AVAILABLE = 1,
1240
1241   /**
1242    * Iteration complete
1243    */
1244   IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
1245 };
1246
1247
1248 /**
1249  * Context for record remove operations passed from
1250  * #run_zone_iteration_round to #zone_iterate_proc as closure
1251  */
1252 struct ZoneIterationProcResult
1253 {
1254   /**
1255    * The zone iteration handle
1256    */
1257   struct ZoneIteration *zi;
1258
1259   /**
1260    * Iteration result: iteration done?
1261    * #IT_SUCCESS_MORE_AVAILABLE:  if there may be more results overall but
1262    * we got one for now and have sent it to the client
1263    * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1264    * #IT_START: if we are still trying to find a result.
1265    */
1266   int res_iteration_finished;
1267
1268 };
1269
1270
1271 /**
1272  * Process results for zone iteration from database
1273  *
1274  * @param cls struct ZoneIterationProcResult *proc
1275  * @param zone_key the zone key
1276  * @param name name
1277  * @param rd_count number of records for this name
1278  * @param rd record data
1279  */
1280 static void
1281 zone_iterate_proc (void *cls,
1282                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1283                    const char *name,
1284                    unsigned int rd_count,
1285                    const struct GNUNET_GNSRECORD_Data *rd)
1286 {
1287   struct ZoneIterationProcResult *proc = cls;
1288   int do_refresh_block;
1289
1290   if ((NULL == zone_key) && (NULL == name))
1291   {
1292     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1293                 "Iteration done\n");
1294     proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1295     return;
1296   }
1297   if ((NULL == zone_key) || (NULL == name))
1298   {
1299     /* what is this!? should never happen */
1300     proc->res_iteration_finished = IT_START;
1301     GNUNET_break (0);
1302     return;
1303   }
1304   proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1305   send_lookup_response (proc->zi->nc,
1306                         proc->zi->request_id,
1307                         zone_key,
1308                         name,
1309                         rd_count,
1310                         rd);
1311   do_refresh_block = GNUNET_NO;
1312   for (unsigned int i=0;i<rd_count;i++)
1313     if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1314     {
1315       do_refresh_block = GNUNET_YES;
1316       break;
1317     }
1318   if (GNUNET_YES == do_refresh_block)
1319     refresh_block (NULL,
1320                    0,
1321                    zone_key,
1322                    name,
1323                    rd_count,
1324                    rd);
1325
1326 }
1327
1328
1329 /**
1330  * Perform the next round of the zone iteration.
1331  *
1332  * @param zi zone iterator to process
1333  */
1334 static void
1335 run_zone_iteration_round (struct ZoneIteration *zi)
1336 {
1337   struct ZoneIterationProcResult proc;
1338   struct GNUNET_MQ_Envelope *env;
1339   struct RecordResultMessage *rrm;
1340   int ret;
1341
1342   memset (&proc, 0, sizeof (proc));
1343   proc.zi = zi;
1344   proc.res_iteration_finished = IT_START;
1345   while (IT_START == proc.res_iteration_finished)
1346   {
1347     if (GNUNET_SYSERR ==
1348         (ret = GSN_database->iterate_records (GSN_database->cls,
1349                                               (0 == memcmp (&zi->zone, &zero, sizeof (zero)))
1350                                               ? NULL
1351                                               : &zi->zone,
1352                                               zi->offset,
1353                                               &zone_iterate_proc, &proc)))
1354     {
1355       GNUNET_break (0);
1356       break;
1357     }
1358     if (GNUNET_NO == ret)
1359       proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1360     zi->offset++;
1361   }
1362   if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1363   {
1364     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1365                 "More results available\n");
1366     return; /* more results later */
1367   }
1368   /* send empty response to indicate end of list */
1369   env = GNUNET_MQ_msg (rrm,
1370                        GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
1371   rrm->gns_header.r_id = htonl (zi->request_id);
1372   GNUNET_MQ_send (zi->nc->mq,
1373                   env);
1374   GNUNET_CONTAINER_DLL_remove (zi->nc->op_head,
1375                                zi->nc->op_tail,
1376                                zi);
1377   GNUNET_free (zi);
1378 }
1379
1380
1381 /**
1382  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1383  *
1384  * @param cls the client sending the message
1385  * @param zis_msg message from the client
1386  */
1387 static void
1388 handle_iteration_start (void *cls,
1389                         const struct ZoneIterationStartMessage *zis_msg)
1390 {
1391   struct NamestoreClient *nc = cls;
1392   struct ZoneIteration *zi;
1393
1394   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1395               "Received ZONE_ITERATION_START message\n");
1396   zi = GNUNET_new (struct ZoneIteration);
1397   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1398   zi->offset = 0;
1399   zi->nc = nc;
1400   zi->zone = zis_msg->zone;
1401
1402   GNUNET_CONTAINER_DLL_insert (nc->op_head,
1403                                nc->op_tail,
1404                                zi);
1405   run_zone_iteration_round (zi);
1406   GNUNET_SERVICE_client_continue (nc->client);
1407 }
1408
1409
1410 /**
1411  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1412  *
1413  * @param cls the client sending the message
1414  * @param zis_msg message from the client
1415  */
1416 static void
1417 handle_iteration_stop (void *cls,
1418                        const struct ZoneIterationStopMessage *zis_msg)
1419 {
1420   struct NamestoreClient *nc = cls;
1421   struct ZoneIteration *zi;
1422   uint32_t rid;
1423
1424   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1425               "Received `%s' message\n",
1426               "ZONE_ITERATION_STOP");
1427   rid = ntohl (zis_msg->gns_header.r_id);
1428   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1429     if (zi->request_id == rid)
1430       break;
1431   if (NULL == zi)
1432   {
1433     GNUNET_break (0);
1434     GNUNET_SERVICE_client_drop (nc->client);
1435     return;
1436   }
1437   GNUNET_CONTAINER_DLL_remove (nc->op_head,
1438                                nc->op_tail,
1439                                zi);
1440   GNUNET_free (zi);
1441   GNUNET_SERVICE_client_continue (nc->client);
1442 }
1443
1444
1445 /**
1446  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1447  *
1448  * @param cls the client sending the message
1449  * @param message message from the client
1450  */
1451 static void
1452 handle_iteration_next (void *cls,
1453                        const struct ZoneIterationNextMessage *zis_msg)
1454 {
1455   struct NamestoreClient *nc = cls;
1456   struct ZoneIteration *zi;
1457   uint32_t rid;
1458
1459   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460               "Received ZONE_ITERATION_NEXT message\n");
1461   rid = ntohl (zis_msg->gns_header.r_id);
1462   for (zi = nc->op_head; NULL != zi; zi = zi->next)
1463     if (zi->request_id == rid)
1464       break;
1465   if (NULL == zi)
1466   {
1467     GNUNET_break (0);
1468     GNUNET_SERVICE_client_drop (nc->client);
1469     return;
1470   }
1471   run_zone_iteration_round (zi);
1472   GNUNET_SERVICE_client_continue (nc->client);
1473 }
1474
1475
1476 /**
1477  * Send 'sync' message to zone monitor, we're now in sync.
1478  *
1479  * @param zm monitor that is now in sync
1480  */
1481 static void
1482 monitor_sync (struct ZoneMonitor *zm)
1483 {
1484   struct GNUNET_MQ_Envelope *env;
1485   struct GNUNET_MessageHeader *sync;
1486
1487   env = GNUNET_MQ_msg (sync,
1488                        GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1489   GNUNET_MQ_send (zm->nc->mq,
1490                   env);
1491 }
1492
1493
1494 /**
1495  * Obtain the next datum during the zone monitor's zone intiial iteration.
1496  *
1497  * @param cls zone monitor that does its initial iteration
1498  */
1499 static void
1500 monitor_next (void *cls);
1501
1502
1503 /**
1504  * A #GNUNET_NAMESTORE_RecordIterator for monitors.
1505  *
1506  * @param cls a 'struct ZoneMonitor *' with information about the monitor
1507  * @param zone_key zone key of the zone
1508  * @param name name
1509  * @param rd_count number of records in @a rd
1510  * @param rd array of records
1511  */
1512 static void
1513 monitor_iterate_cb (void *cls,
1514                     const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
1515                     const char *name,
1516                     unsigned int rd_count,
1517                     const struct GNUNET_GNSRECORD_Data *rd)
1518 {
1519   struct ZoneMonitor *zm = cls;
1520
1521   if (NULL == name)
1522   {
1523     /* finished with iteration */
1524     monitor_sync (zm);
1525     return;
1526   }
1527   send_lookup_response (zm->nc,
1528                         0,
1529                         zone_key,
1530                         name,
1531                         rd_count,
1532                         rd);
1533   zm->task = GNUNET_SCHEDULER_add_now (&monitor_next,
1534                                        zm);
1535 }
1536
1537
1538 /**
1539  * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
1540  *
1541  * @param cls the client sending the message
1542  * @param message message from the client
1543  */
1544 static void
1545 handle_monitor_start (void *cls,
1546                       const struct ZoneMonitorStartMessage *zis_msg)
1547 {
1548   struct NamestoreClient *nc = cls;
1549   struct ZoneMonitor *zm;
1550
1551   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1552               "Received ZONE_MONITOR_START message\n");
1553   zm = GNUNET_new (struct ZoneMonitor);
1554   zm->nc = nc;
1555   zm->zone = zis_msg->zone;
1556   GNUNET_CONTAINER_DLL_insert (monitor_head,
1557                                monitor_tail,
1558                                zm);
1559   GNUNET_SERVICE_client_mark_monitor (nc->client);
1560   GNUNET_SERVICE_client_disable_continue_warning (nc->client);
1561   GNUNET_notification_context_add (monitor_nc,
1562                                    nc->mq);
1563   if (GNUNET_YES == ntohl (zis_msg->iterate_first))
1564     zm->task = GNUNET_SCHEDULER_add_now (&monitor_next,
1565                                          zm);
1566   else
1567     monitor_sync (zm);
1568 }
1569
1570
1571 /**
1572  * Obtain the next datum during the zone monitor's zone intiial iteration.
1573  *
1574  * @param cls zone monitor that does its initial iteration
1575  */
1576 static void
1577 monitor_next (void *cls)
1578 {
1579   struct ZoneMonitor *zm = cls;
1580   int ret;
1581
1582   zm->task = NULL;
1583   ret = GSN_database->iterate_records (GSN_database->cls,
1584                                        (0 == memcmp (&zm->zone,
1585                                                      &zero,
1586                                                      sizeof (zero)))
1587                                        ? NULL
1588                                        : &zm->zone,
1589                                        zm->offset++,
1590                                        &monitor_iterate_cb,
1591                                        zm);
1592   if (GNUNET_SYSERR == ret)
1593   {
1594     GNUNET_SERVICE_client_drop (zm->nc->client);
1595     return;
1596   }
1597   if (GNUNET_NO == ret)
1598   {
1599     /* empty zone */
1600     monitor_sync (zm);
1601     return;
1602   }
1603 }
1604
1605
1606 /**
1607  * Process namestore requests.
1608  *
1609  * @param cls closure
1610  * @param cfg configuration to use
1611  * @param service the initialized service
1612  */
1613 static void
1614 run (void *cls,
1615      const struct GNUNET_CONFIGURATION_Handle *cfg,
1616      struct GNUNET_SERVICE_Handle *service)
1617 {
1618   char *database;
1619
1620   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1621               "Starting namestore service\n");
1622   GSN_cfg = cfg;
1623   monitor_nc = GNUNET_notification_context_create (1);
1624   namecache = GNUNET_NAMECACHE_connect (cfg);
1625   /* Loading database plugin */
1626   if (GNUNET_OK !=
1627       GNUNET_CONFIGURATION_get_value_string (cfg,
1628                                              "namestore",
1629                                              "database",
1630                                              &database))
1631     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1632                 "No database backend configured\n");
1633
1634   GNUNET_asprintf (&db_lib_name,
1635                    "libgnunet_plugin_namestore_%s",
1636                    database);
1637   GSN_database = GNUNET_PLUGIN_load (db_lib_name,
1638                                      (void *) GSN_cfg);
1639   GNUNET_free (database);
1640   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
1641                                  NULL);
1642   if (NULL == GSN_database)
1643   {
1644     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1645                 "Could not load database backend `%s'\n",
1646                 db_lib_name);
1647     GNUNET_SCHEDULER_shutdown ();
1648     return;
1649   }
1650 }
1651
1652
1653 /**
1654  * Define "main" method using service macro.
1655  */
1656 GNUNET_SERVICE_MAIN
1657 ("namestore",
1658  GNUNET_SERVICE_OPTION_NONE,
1659  &run,
1660  &client_connect_cb,
1661  &client_disconnect_cb,
1662  NULL,
1663  GNUNET_MQ_hd_var_size (record_store,
1664                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
1665                         struct RecordStoreMessage,
1666                         NULL),
1667  GNUNET_MQ_hd_var_size (record_lookup,
1668                         GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
1669                         struct LabelLookupMessage,
1670                         NULL),
1671  GNUNET_MQ_hd_fixed_size (zone_to_name,
1672                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
1673                           struct ZoneToNameMessage,
1674                           NULL),
1675  GNUNET_MQ_hd_fixed_size (iteration_start,
1676                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
1677                           struct ZoneIterationStartMessage,
1678                           NULL),
1679  GNUNET_MQ_hd_fixed_size (iteration_next,
1680                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
1681                           struct ZoneIterationNextMessage,
1682                           NULL),
1683  GNUNET_MQ_hd_fixed_size (iteration_stop,
1684                           GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
1685                           struct ZoneIterationStopMessage,
1686                           NULL),
1687  GNUNET_MQ_hd_fixed_size (monitor_start,
1688                           GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
1689                           struct ZoneMonitorStartMessage,
1690                           NULL),
1691  GNUNET_MQ_handler_end ());
1692
1693
1694 /* end of gnunet-service-namestore.c */