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