- doxygen
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
33
34
35
36 /**
37  * A namestore operation.
38  */
39 struct GNUNET_NAMESTORE_ZoneIteration
40 {
41   struct GNUNET_NAMESTORE_ZoneIteration *next;
42   struct GNUNET_NAMESTORE_ZoneIteration *prev;
43
44   struct GNUNET_NAMESTORE_Client * client;
45
46   GNUNET_HashCode zone;
47
48   uint64_t request_id;
49   uint32_t offset;
50
51 };
52
53
54 /**
55  * A namestore client
56  */
57 struct GNUNET_NAMESTORE_Client
58 {
59   struct GNUNET_NAMESTORE_Client *next;
60   struct GNUNET_NAMESTORE_Client *prev;
61
62   struct GNUNET_SERVER_Client * client;
63
64   struct GNUNET_NAMESTORE_ZoneIteration *op_head;
65   struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
66 };
67
68
69
70 /**
71  * Configuration handle.
72  */
73 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
74
75 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
76
77 /**
78  * Our notification context.
79  */
80 static struct GNUNET_SERVER_NotificationContext *snc;
81
82 static char *db_lib_name;
83
84 static struct GNUNET_NAMESTORE_Client *client_head;
85 static struct GNUNET_NAMESTORE_Client *client_tail;
86
87
88 /**
89  * Task run during shutdown.
90  *
91  * @param cls unused
92  * @param tc unused
93  */
94 static void
95 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
96 {
97   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
98
99   struct GNUNET_NAMESTORE_ZoneIteration * no;
100   struct GNUNET_NAMESTORE_ZoneIteration * tmp;
101   struct GNUNET_NAMESTORE_Client * nc;
102   struct GNUNET_NAMESTORE_Client * next;
103
104   GNUNET_SERVER_notification_context_destroy (snc);
105   snc = NULL;
106
107   for (nc = client_head; nc != NULL; nc = next)
108   {
109     next = nc->next;
110     for (no = nc->op_head; no != NULL; no = tmp)
111     {
112       GNUNET_break (0);
113       GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
114       tmp = no->next;
115       GNUNET_free (no);
116     }
117     GNUNET_SERVER_client_drop(nc->client);
118     GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
119     GNUNET_free (nc);
120   }
121
122   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
123   GNUNET_free (db_lib_name);
124 }
125
126 static struct GNUNET_NAMESTORE_Client *
127 client_lookup (struct GNUNET_SERVER_Client *client)
128 {
129   struct GNUNET_NAMESTORE_Client * nc;
130
131   GNUNET_assert (NULL != client);
132
133   for (nc = client_head; nc != NULL; nc = nc->next)
134   {
135     if (client == nc->client)
136       break;
137   }
138   return nc;
139 }
140
141 /**
142  * Called whenever a client is disconnected.  Frees our
143  * resources associated with that client.
144  *
145  * @param cls closure
146  * @param client identification of the client
147  */
148 static void
149 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
150 {
151   struct GNUNET_NAMESTORE_ZoneIteration * no;
152   struct GNUNET_NAMESTORE_Client * nc;
153   if (NULL == client)
154     return;
155
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
157
158   nc = client_lookup (client);
159
160   if ((NULL == client) || (NULL == nc))
161     return;
162
163   for (no = nc->op_head; no != NULL; no = no->next)
164   {
165     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
166     GNUNET_free (no);
167   }
168
169   GNUNET_SERVER_client_drop(nc->client);
170   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
171   GNUNET_free (nc);
172 }
173
174
175
176 static void handle_start (void *cls,
177                           struct GNUNET_SERVER_Client * client,
178                           const struct GNUNET_MessageHeader * message)
179 {
180   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
181
182   struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
183   nc->client = client;
184   GNUNET_SERVER_notification_context_add (snc, client);
185   GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
186   GNUNET_SERVER_client_keep (client);
187   GNUNET_SERVER_receive_done (client, GNUNET_OK);
188 }
189
190 struct LookupNameContext
191 {
192   struct GNUNET_NAMESTORE_Client *nc;
193   uint32_t request_id;
194   uint32_t record_type;
195   GNUNET_HashCode *zone;
196   char * name;
197 };
198
199 void drop_iterator (void *cls,
200                    const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
201                    struct GNUNET_TIME_Absolute expire,
202                    const char *name,
203                    unsigned int rd_len,
204                    const struct GNUNET_NAMESTORE_RecordData *rd,
205                    const struct GNUNET_CRYPTO_RsaSignature *signature)
206 {
207   GNUNET_HashCode zone_hash;
208   int * stop = cls;
209   if (NULL != zone_key)
210   {
211     GNUNET_CRYPTO_hash(zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone_hash);
212     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting zone `%s'\n", GNUNET_h2s (&zone_hash));
213     GSN_database->delete_zone (GSN_database->cls, &zone_hash);
214   }
215   else
216   {
217     (*stop) = GNUNET_YES;
218   }
219 }
220
221
222 /**
223  * Called whenever a client is disconnected.  Frees our
224  * resources associated with that client.
225  *
226  * @param cls closure
227  * @param client identification of the client
228  * @param message the stop message
229  */
230 static void handle_stop (void *cls,
231                           struct GNUNET_SERVER_Client * client,
232                           const struct GNUNET_MessageHeader * message)
233 {
234   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
235   struct DisconnectMessage * msg = (struct DisconnectMessage *) message;
236   struct GNUNET_NAMESTORE_ZoneIteration * no;
237   struct GNUNET_NAMESTORE_Client * nc;
238   int drop;
239
240   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
241
242   nc = client_lookup (client);
243   if (nc == NULL)
244   {
245     GNUNET_break (0);
246     return;
247   }
248
249   for (no = nc->op_head; no != NULL; no = no->next)
250   {
251     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
252     GNUNET_free (no);
253   }
254
255   drop = ntohl(msg->drop);
256   if (GNUNET_YES == drop)
257   {
258     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping namestore content\n");
259     int stop = GNUNET_NO;
260     int offset = 0;
261     while (stop == GNUNET_NO)
262     {
263       GSN_database->iterate_records (GSN_database->cls, NULL, NULL, offset, &drop_iterator, &stop);
264       offset ++;
265     }
266   }
267
268   GNUNET_SERVER_client_drop(nc->client);
269   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
270   GNUNET_free (nc);
271 }
272
273 static void
274 handle_lookup_name_it (void *cls,
275     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
276     struct GNUNET_TIME_Absolute expire,
277     const char *name,
278     unsigned int rd_count,
279     const struct GNUNET_NAMESTORE_RecordData *rd,
280     const struct GNUNET_CRYPTO_RsaSignature *signature)
281 {
282   /* send response */
283   struct LookupNameContext *lnc = cls;
284   struct LookupNameResponseMessage *lnr_msg;
285
286   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp;
287   struct GNUNET_NAMESTORE_RecordData *rd_selected = NULL;
288   char *rd_tmp;
289   char *name_tmp;
290   size_t rd_ser_len;
291   struct GNUNET_CRYPTO_RsaSignature *signature_tmp;
292
293   size_t r_size = 0;
294
295   size_t name_len = 0;
296   if (NULL != name)
297     name_len = strlen(name) + 1;
298
299   int copied_elements = 0;
300   int contains_signature = 0;
301   int c;
302
303   /* count records to copy */
304   if (rd_count != 0)
305   {
306     if (lnc->record_type != 0)
307     {
308       /* special record type needed */
309       for (c = 0; c < rd_count; c ++)
310         if (rd[c].record_type == lnc->record_type)
311           copied_elements++; /* found matching record */
312       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records with type %u for name `%s' in zone `%s'\n",
313           copied_elements, lnc->record_type, lnc->name, GNUNET_h2s(lnc->zone));
314       rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
315       copied_elements = 0;
316       for (c = 0; c < rd_count; c ++)
317       {
318         if (rd[c].record_type == lnc->record_type)
319         {
320           /* found matching record */
321           memcpy (&rd_selected[copied_elements], &rd[c], sizeof (struct GNUNET_NAMESTORE_RecordData));
322           copied_elements++;
323         }
324       }
325     }
326     else
327     {
328       copied_elements = rd_count;
329       rd_selected = (struct GNUNET_NAMESTORE_RecordData *) rd;
330     }
331   }
332   else
333   {
334     /* No results */
335     copied_elements = 0;
336     rd_selected = NULL;
337     expire = GNUNET_TIME_UNIT_ZERO_ABS;
338   }
339
340   rd_ser_len = GNUNET_NAMESTORE_records_get_size(copied_elements, rd_selected);
341   char rd_ser[rd_ser_len];
342   GNUNET_NAMESTORE_records_serialize(copied_elements, rd_selected, rd_ser_len, rd_ser);
343
344   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u records for name `%s' in zone `%s'\n",
345       copied_elements, lnc->name, GNUNET_h2s(lnc->zone));
346
347   if ((copied_elements == rd_count) && (signature != NULL))
348       contains_signature = GNUNET_YES;
349
350   if (rd_selected != rd)
351     GNUNET_free (rd_selected);
352
353   r_size = sizeof (struct LookupNameResponseMessage) +
354            sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
355            name_len +
356            rd_ser_len +
357            contains_signature * sizeof (struct GNUNET_CRYPTO_RsaSignature);
358
359   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE");
360
361   lnr_msg = GNUNET_malloc (r_size);
362
363   lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
364   lnr_msg->gns_header.header.size = ntohs (r_size);
365   lnr_msg->gns_header.r_id = htonl (lnc->request_id);
366   lnr_msg->rd_count = htons (copied_elements);
367   lnr_msg->rd_len = htons (rd_ser_len);
368   lnr_msg->name_len = htons (name_len);
369   lnr_msg->expire = GNUNET_TIME_absolute_hton(expire);
370   lnr_msg->contains_sig = htons (contains_signature);
371
372   zone_key_tmp =  (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &lnr_msg[1];
373   name_tmp = (char *) &zone_key_tmp[1];
374   rd_tmp = &name_tmp[name_len];
375   signature_tmp = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[rd_ser_len];
376
377   if (zone_key != NULL)
378     memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
379   else
380   {
381     struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy;
382     memset (&dummy, '0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
383     memcpy (zone_key_tmp, &dummy, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
384   }
385   memcpy (name_tmp, name, name_len);
386   memcpy (rd_tmp, rd_ser, rd_ser_len);
387
388   if (GNUNET_YES == contains_signature)
389     memcpy (signature_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature));
390   GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO);
391
392   GNUNET_free (lnr_msg);
393 }
394
395 static void handle_lookup_name (void *cls,
396                           struct GNUNET_SERVER_Client * client,
397                           const struct GNUNET_MessageHeader * message)
398 {
399   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
400   struct LookupNameContext lnc;
401   struct GNUNET_NAMESTORE_Client *nc;
402   size_t name_len;
403   char * name;
404   uint32_t rid = 0;
405   uint32_t type = 0;
406   int res;
407
408   if (ntohs (message->size) < sizeof (struct LookupNameMessage))
409   {
410     GNUNET_break_op (0);
411     GNUNET_SERVER_receive_done (client, GNUNET_OK);
412     return;
413   }
414
415   nc = client_lookup(client);
416   if (nc == NULL)
417   {
418     GNUNET_break_op (0);
419     GNUNET_SERVER_receive_done (client, GNUNET_OK);
420     return;
421   }
422
423   struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message;
424   rid = ntohl (ln_msg->gns_header.r_id);
425   name_len = ntohl (ln_msg->name_len);
426   type = ntohl (ln_msg->record_type);
427
428   if ((name_len == 0) || (name_len > 256))
429   {
430     GNUNET_break_op (0);
431     GNUNET_SERVER_receive_done (client, GNUNET_OK);
432     return;
433   }
434
435   name = (char *) &ln_msg[1];
436   if (name[name_len -1] != '\0')
437   {
438     GNUNET_break_op (0);
439     GNUNET_SERVER_receive_done (client, GNUNET_OK);
440     return;
441   }
442
443   if (0 == type)
444     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up all records for name `%s' in zone `%s'\n", name, GNUNET_h2s(&ln_msg->zone));
445   else
446     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up records with type %u for name `%s' in zone `%s'\n", type, name, GNUNET_h2s(&ln_msg->zone));
447   /* do the actual lookup */
448   lnc.request_id = rid;
449   lnc.nc = nc;
450   lnc.record_type = type;
451   lnc.name = name;
452   lnc.zone = &ln_msg->zone;
453   res = GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, name, 0, &handle_lookup_name_it, &lnc);
454
455   GNUNET_SERVER_receive_done (client, GNUNET_OK);
456 }
457
458 static void handle_record_put (void *cls,
459                           struct GNUNET_SERVER_Client * client,
460                           const struct GNUNET_MessageHeader * message)
461 {
462   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT");
463   struct GNUNET_NAMESTORE_Client *nc;
464   struct GNUNET_TIME_Absolute expire;
465   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
466   struct GNUNET_CRYPTO_RsaSignature *signature;
467   struct RecordPutResponseMessage rpr_msg;
468   size_t name_len;
469   size_t msg_size;
470   size_t msg_size_exp;
471   size_t key_len;
472   char * name;
473   char * rd_ser;
474   uint32_t rid = 0;
475   uint32_t rd_ser_len;
476   uint32_t rd_count;
477   int res = GNUNET_SYSERR;
478
479   if (ntohs (message->size) < sizeof (struct RecordPutMessage))
480   {
481     GNUNET_break_op (0);
482     GNUNET_SERVER_receive_done (client, GNUNET_OK);
483     return;
484   }
485
486   nc = client_lookup (client);
487   if (nc == NULL)
488   {
489     GNUNET_break_op (0);
490     GNUNET_SERVER_receive_done (client, GNUNET_OK);
491     return;
492   }
493
494   struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message;
495
496   rid = ntohl (rp_msg->gns_header.r_id);
497   msg_size = ntohs (rp_msg->gns_header.header.size);
498   key_len = ntohs (rp_msg->key_len);
499   name_len = ntohs (rp_msg->name_len);
500   rd_count = ntohs (rp_msg->rd_count);
501   rd_ser_len = ntohs(rp_msg->rd_len);
502
503   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
504   {
505     GNUNET_break_op (0);
506     GNUNET_SERVER_receive_done (client, GNUNET_OK);
507     return;
508   }
509
510   if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
511   {
512     GNUNET_break_op (0);
513     GNUNET_SERVER_receive_done (client, GNUNET_OK);
514     return;
515   }
516
517   msg_size_exp = sizeof (struct RecordPutMessage) + key_len + name_len  + rd_ser_len;
518   if (msg_size != msg_size_exp)
519   {
520     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
521     GNUNET_break_op (0);
522     GNUNET_SERVER_receive_done (client, GNUNET_OK);
523     return;
524   }
525   if ((name_len == 0) || (name_len > 256))
526   {
527     GNUNET_break_op (0);
528     GNUNET_SERVER_receive_done (client, GNUNET_OK);
529     return;
530   }
531
532   zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &rp_msg[1];
533   name =  &((char *)zone_key)[key_len];
534
535   if (name[name_len -1] != '\0')
536   {
537     GNUNET_break_op (0);
538     GNUNET_SERVER_receive_done (client, GNUNET_OK);
539     return;
540   }
541
542   expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
543   signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature;
544
545   rd_ser = &name[name_len];
546   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
547   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
548   if (res != GNUNET_OK)
549   {
550     GNUNET_break_op (0);
551     goto send;
552   }
553
554
555   GNUNET_HashCode zone_hash;
556   GNUNET_CRYPTO_hash (zone_key, key_len, &zone_hash);
557
558   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting %u record for name `%s' in zone `%s'\n", rd_count, name, GNUNET_h2s(&zone_hash));
559
560   /* Database operation */
561   res = GSN_database->put_records(GSN_database->cls,
562                                 zone_key,
563                                 expire,
564                                 name,
565                                 rd_count, rd,
566                                 signature);
567
568   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n",
569       name, (res == GNUNET_OK) ? "OK" : "FAIL");
570
571   /* Send response */
572 send:
573   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE");
574   rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
575   rpr_msg.op_id = rp_msg->gns_header.r_id;
576   rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage));
577   if (GNUNET_OK == res)
578     rpr_msg.op_result = htons (GNUNET_OK);
579   else
580     rpr_msg.op_result = htons (GNUNET_NO);
581   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO);
582
583   GNUNET_SERVER_receive_done (client, GNUNET_OK);
584 }
585
586 struct CreateRecordContext
587 {
588   struct GNUNET_NAMESTORE_RecordData *rd;
589   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
590   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey;
591   struct GNUNET_TIME_Absolute expire;
592   char *name;
593   int res;
594 };
595
596
597 static void
598 handle_create_record_it (void *cls,
599     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
600     struct GNUNET_TIME_Absolute expire,
601     const char *name,
602     unsigned int rd_count,
603     const struct GNUNET_NAMESTORE_RecordData *rd,
604     const struct GNUNET_CRYPTO_RsaSignature *signature)
605 {
606   struct CreateRecordContext * crc = cls;
607   struct GNUNET_CRYPTO_RsaSignature *signature_new = NULL;
608   struct GNUNET_NAMESTORE_RecordData *rd_new = NULL;
609   int res;
610   int exist = GNUNET_SYSERR;
611   int update = GNUNET_NO;
612   int c;
613   int rd_count_new = 0;
614
615   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u existing records for `%s'\n", rd_count, crc->name);
616
617   for (c = 0; c < rd_count; c++)
618   {
619
620     if ((crc->rd->record_type == rd[c].record_type) &&
621         (crc->rd->data_size == rd[c].data_size) &&
622         (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
623     {
624       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing records for `%s' to update expiration date!\n", crc->name);
625       exist = c;
626       if (crc->rd->expiration.abs_value != rd[c].expiration.abs_value)
627         update = GNUNET_YES;
628        break;
629     }
630   }
631
632   if (exist == GNUNET_SYSERR)
633     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NO existing records for `%s' to update!\n", crc->name);
634
635   if (exist == GNUNET_SYSERR)
636   {
637     rd_new = GNUNET_malloc ((rd_count+1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
638     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
639     rd_count_new = rd_count + 1;
640     rd_new[rd_count] = *(crc->rd);
641     signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count+1);
642
643     if (NULL == signature_new)
644     {
645       GNUNET_break (0);
646       res = GNUNET_SYSERR;
647       goto end;
648     }
649   }
650   else if (update == GNUNET_NO)
651   {
652     /* Exact same record already exists */
653     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No update for %s' record required!\n", crc->name);
654     res = GNUNET_NO;
655     goto end;
656   }
657   else if (update == GNUNET_YES)
658   {
659     /* Update record */
660     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating existing records for `%s'!\n", crc->name);
661     rd_new = GNUNET_malloc ((rd_count) * sizeof (struct GNUNET_NAMESTORE_RecordData));
662     memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
663     rd_count_new = rd_count;
664     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating expiration from %llu to %llu!\n", rd_new[exist].expiration.abs_value, crc->rd->expiration.abs_value);
665     rd_new[exist].expiration = crc->rd->expiration;
666     signature_new = GNUNET_NAMESTORE_create_signature (crc->pkey, crc->name, rd_new, rd_count_new);
667     if (NULL == signature_new)
668     {
669       GNUNET_break (0);
670       res = GNUNET_SYSERR;
671       goto end;
672     }
673   }
674
675   /* Database operation */
676   GNUNET_assert ((rd_new != NULL) && (rd_count_new > 0));
677   res = GSN_database->put_records(GSN_database->cls,
678                                 (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) crc->pubkey,
679                                 crc->expire,
680                                 crc->name,
681                                 rd_count_new, rd_new,
682                                 signature_new);
683   GNUNET_break (GNUNET_OK == res);
684   res = GNUNET_YES;
685
686 end:
687   GNUNET_free_non_null (rd_new);
688   GNUNET_free_non_null (signature_new);
689
690   switch (res) {
691     case GNUNET_SYSERR:
692        /* failed to create the record */
693        crc->res = GNUNET_SYSERR;
694       break;
695     case GNUNET_YES:
696       /* database operations OK */
697       if (GNUNET_YES == update)
698         /* we updated an existing record */
699         crc->res = GNUNET_NO;
700       else
701         /* we created a new record */
702         crc->res = GNUNET_YES;
703       break;
704     case GNUNET_NO:
705         /* identical entry existed, so we did nothing */
706         crc->res = GNUNET_NO;
707       break;
708     default:
709       break;
710   }
711
712   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Update result for name `%s' %u\n", crc->name, res);
713
714 }
715
716 static void handle_record_create (void *cls,
717                           struct GNUNET_SERVER_Client * client,
718                           const struct GNUNET_MessageHeader * message)
719 {
720   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
721   struct GNUNET_NAMESTORE_Client *nc;
722   struct CreateRecordContext crc;
723   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
724   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
725   struct RecordCreateResponseMessage rcr_msg;
726   GNUNET_HashCode pubkey_hash;
727   size_t name_len;
728   size_t msg_size;
729   size_t msg_size_exp;
730   size_t rd_ser_len;
731   size_t key_len;
732   uint32_t rid = 0;
733   char *pkey_tmp;
734   char *name_tmp;
735   char *rd_ser;
736   int rd_count;
737
738   int res = GNUNET_SYSERR;
739
740   if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
741   {
742     GNUNET_break_op (0);
743     GNUNET_SERVER_receive_done (client, GNUNET_OK);
744     return;
745   }
746
747   nc = client_lookup(client);
748   if (nc == NULL)
749   {
750     GNUNET_break_op (0);
751     GNUNET_SERVER_receive_done (client, GNUNET_OK);
752     return;
753   }
754
755   struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message;
756   rid = ntohl (rp_msg->gns_header.r_id);
757   name_len = ntohs (rp_msg->name_len);
758   msg_size = ntohs (message->size);
759   rd_count = ntohs (rp_msg->rd_count);
760   rd_ser_len = ntohs (rp_msg->rd_len);
761   key_len = ntohs (rp_msg->pkey_len);
762   msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
763
764   if (msg_size != msg_size_exp)
765   {
766     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
767     GNUNET_break_op (0);
768     GNUNET_SERVER_receive_done (client, GNUNET_OK);
769     return;
770   }
771
772   if ((name_len == 0) || (name_len > 256))
773   {
774     GNUNET_break_op (0);
775     GNUNET_SERVER_receive_done (client, GNUNET_OK);
776     return;
777   }
778
779   pkey_tmp = (char *) &rp_msg[1];
780   name_tmp = &pkey_tmp[key_len];
781   rd_ser = &name_tmp[name_len];
782
783   if (name_tmp[name_len -1] != '\0')
784   {
785     GNUNET_break_op (0);
786     GNUNET_SERVER_receive_done (client, GNUNET_OK);
787     return;
788   }
789
790   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
791   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
792   if ((res != GNUNET_OK) || (rd_count != 1))
793   {
794     GNUNET_break_op (0);
795     goto send;
796   }
797
798   /* Extracting and converting private key */
799   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
800   GNUNET_assert (pkey != NULL);
801   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
802   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
803
804   crc.pkey = pkey;
805   crc.pubkey = &pub;
806   crc.rd = rd;
807   crc.name = name_tmp;
808
809   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
810
811   /* Get existing records for name */
812   res = GSN_database->iterate_records(GSN_database->cls, &pubkey_hash, name_tmp, 0, &handle_create_record_it, &crc);
813   if (res != GNUNET_SYSERR)
814     res = GNUNET_OK;
815   GNUNET_CRYPTO_rsa_key_free(pkey);
816
817   /* Send response */
818 send:
819   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
820   rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
821   rcr_msg.gns_header.r_id = htonl (rid);
822   rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
823   if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
824     rcr_msg.op_result = htons (GNUNET_YES);
825   else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
826     rcr_msg.op_result = htons (GNUNET_NO);
827   else
828     rcr_msg.op_result = htons (GNUNET_SYSERR);
829   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO);
830
831   GNUNET_SERVER_receive_done (client, GNUNET_OK);
832 }
833
834
835 struct RemoveRecordContext
836 {
837   struct GNUNET_NAMESTORE_RecordData *rd;
838   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
839   uint16_t op_res;
840 };
841
842 static void
843 handle_record_remove_it (void *cls,
844     const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
845     struct GNUNET_TIME_Absolute expire,
846     const char *name,
847     unsigned int rd_count,
848     const struct GNUNET_NAMESTORE_RecordData *rd,
849     const struct GNUNET_CRYPTO_RsaSignature *signature)
850 {
851   struct RemoveRecordContext *rrc = cls;
852   unsigned int rd_count_new = rd_count -1;
853   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count_new];
854   unsigned int c;
855   int res;
856   int found = GNUNET_NO;
857
858   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s 'currently has %u records\n", name, rd_count);
859
860   if (rd_count == 0)
861   {
862     /* Could not find record to remove */
863     rrc->op_res = 1;
864     return;
865   }
866
867   /* Find record to remove */
868   unsigned int c2 = 0;
869   for (c = 0; c < rd_count; c++)
870   {
871     if ((rd[c].expiration.abs_value == rrc->rd->expiration.abs_value) &&
872         (rd[c].flags == rrc->rd->flags) &&
873         (rd[c].record_type == rrc->rd->record_type) &&
874         (rd[c].data_size == rrc->rd->data_size) &&
875         (0 == memcmp (rd[c].data, rrc->rd->data, rrc->rd->data_size)))
876         {
877           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
878           found = GNUNET_YES;
879           continue;
880         }
881     else
882     {
883       rd_new[c2] = rd[c];
884       c2 ++;
885     }
886   }
887   if ((c2 != rd_count_new) || (found == GNUNET_NO))
888   {
889     /* Could not find record to remove */
890     rrc->op_res = 2;
891     return;
892   }
893   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' now has %u records\n", name, rd_count_new);
894
895   /* Create new signature */
896   struct GNUNET_CRYPTO_RsaSignature * new_signature;
897   new_signature = GNUNET_NAMESTORE_create_signature (rrc->pkey, name, rd_new, rd_count_new);
898
899   if (new_signature == NULL)
900   {
901     /* Signature failed */
902     rrc->op_res = 3;
903     return;
904   }
905
906   /* Put records */
907   res = GSN_database->put_records(GSN_database->cls,
908                                   zone_key,
909                                   expire,
910                                   name,
911                                   rd_count_new, rd_new,
912                                   new_signature);
913   GNUNET_free (new_signature);
914
915   if (GNUNET_OK != res)
916   {
917     /* Could put records into database */
918     rrc->op_res = 4;
919     return;
920   }
921
922   rrc->op_res = 0;
923 }
924
925 static void handle_record_remove (void *cls,
926                           struct GNUNET_SERVER_Client * client,
927                           const struct GNUNET_MessageHeader * message)
928 {
929   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE");
930   struct GNUNET_NAMESTORE_Client *nc;
931   struct RecordRemoveResponseMessage rrr_msg;
932   struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
933   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
934   GNUNET_HashCode pubkey_hash;
935   char * pkey_tmp = NULL;
936   char * name_tmp = NULL;
937   char * rd_ser = NULL;
938   size_t key_len = 0;
939   size_t name_len = 0;
940   size_t rd_ser_len = 0;
941   size_t msg_size = 0;
942   size_t msg_size_exp = 0;
943   uint32_t rd_count;
944   uint32_t rid = 0;
945
946   int res = GNUNET_SYSERR;
947
948   if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
949   {
950     GNUNET_break_op (0);
951     GNUNET_SERVER_receive_done (client, GNUNET_OK);
952     return;
953   }
954
955   nc = client_lookup(client);
956   if (nc == NULL)
957   {
958     GNUNET_break_op (0);
959     GNUNET_SERVER_receive_done (client, GNUNET_OK);
960     return;
961   }
962
963   struct RecordRemoveMessage * rr_msg = (struct RecordRemoveMessage *) message;
964   rid = ntohl (rr_msg->gns_header.r_id);
965   name_len = ntohs (rr_msg->name_len);
966   rd_ser_len = ntohs (rr_msg->rd_len);
967   rd_count = ntohs (rr_msg->rd_count);
968   key_len = ntohs (rr_msg->key_len);
969   msg_size = ntohs (message->size);
970
971   if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
972   {
973     GNUNET_break_op (0);
974     GNUNET_SERVER_receive_done (client, GNUNET_OK);
975     return;
976   }
977
978   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
979   {
980     GNUNET_break_op (0);
981     GNUNET_SERVER_receive_done (client, GNUNET_OK);
982     return;
983   }
984
985   msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
986   if (msg_size != msg_size_exp)
987   {
988     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size);
989     GNUNET_break_op (0);
990     GNUNET_SERVER_receive_done (client, GNUNET_OK);
991     return;
992   }
993
994   if ((rd_count != 1) || (rd_ser_len < 1) || (name_len >=256) || (name_len == 0))
995   {
996     GNUNET_break_op (0);
997     GNUNET_SERVER_receive_done (client, GNUNET_OK);
998     return;
999   }
1000
1001   pkey_tmp = (char *) &rr_msg[1];
1002   name_tmp = &pkey_tmp[key_len];
1003   rd_ser = &name_tmp[name_len];
1004
1005
1006   if ((name_len == 0) || (name_len > 256))
1007   {
1008     GNUNET_break_op (0);
1009     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1010     return;
1011   }
1012
1013   if (name_tmp[name_len -1] != '\0')
1014   {
1015     GNUNET_break_op (0);
1016     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1017     return;
1018   }
1019
1020   /* Extracting and converting private key */
1021   pkey = GNUNET_CRYPTO_rsa_decode_key((char *) pkey_tmp, key_len);
1022   GNUNET_assert (pkey != NULL);
1023   GNUNET_CRYPTO_rsa_key_get_public(pkey, &pub);
1024   GNUNET_CRYPTO_hash (&pub, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &pubkey_hash);
1025
1026   struct GNUNET_NAMESTORE_RecordData rd[rd_count];
1027   res = GNUNET_NAMESTORE_records_deserialize(rd_ser_len, rd_ser, rd_count, rd);
1028   if ((res != GNUNET_OK) || (rd_count != 1))
1029   {
1030     GNUNET_break_op (0);
1031     goto send;
1032   }
1033
1034   struct RemoveRecordContext rrc;
1035   rrc.rd = rd;
1036   rrc.pkey = pkey;
1037
1038   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s' in zone `%s'\n", name_tmp, GNUNET_h2s(&pubkey_hash));
1039
1040   /* Database operation */
1041   res = GSN_database->iterate_records (GSN_database->cls,
1042                                        &pubkey_hash,
1043                                        name_tmp,
1044                                        0,
1045                                        handle_record_remove_it, &rrc);
1046
1047   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing record for name `%s': %s\n",
1048       name_tmp, (rrc.op_res == 0) ? "OK" : "FAIL");
1049   res = rrc.op_res;
1050
1051   /* Send response */
1052 send:
1053   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE");
1054   rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1055   rrr_msg.gns_header.r_id = rr_msg->gns_header.r_id;
1056   rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1057   rrr_msg.op_result = htons (res);
1058   GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO);
1059
1060   GNUNET_CRYPTO_rsa_key_free (pkey);
1061
1062   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1063 }
1064
1065 struct ZoneIterationProcResult
1066 {
1067   int have_zone_key;
1068   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key;
1069
1070   int have_signature;
1071   struct GNUNET_CRYPTO_RsaSignature signature;
1072   struct GNUNET_TIME_Absolute expire;
1073
1074   int have_name;
1075   char name[256];
1076
1077   size_t rd_ser_len;
1078   char *rd_ser;
1079 };
1080
1081
1082 void zone_iteration_proc (void *cls,
1083                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1084                          struct GNUNET_TIME_Absolute expire,
1085                          const char *name,
1086                          unsigned int rd_count,
1087                          const struct GNUNET_NAMESTORE_RecordData *rd,
1088                          const struct GNUNET_CRYPTO_RsaSignature *signature)
1089 {
1090   struct ZoneIterationProcResult *zipr = cls;
1091   size_t len;
1092   if (zone_key != NULL)
1093   {
1094     zipr->zone_key = *zone_key;
1095     zipr->have_zone_key = GNUNET_YES;
1096   }
1097   else
1098     zipr->have_zone_key = GNUNET_NO;
1099
1100   zipr->expire = expire;
1101
1102   if (name != NULL)
1103   {
1104     memcpy (zipr->name, name, strlen(name) + 1);
1105     zipr->have_name = GNUNET_YES;
1106   }
1107   else
1108     zipr->have_name = GNUNET_NO;
1109
1110   if (signature != NULL)
1111   {
1112     zipr->signature = *signature;
1113     zipr->have_signature = GNUNET_YES;
1114   }
1115   else
1116     zipr->have_signature = GNUNET_NO;
1117
1118   if ((rd_count > 0) && (rd != NULL))
1119   {
1120     len = GNUNET_NAMESTORE_records_get_size(rd_count, rd);
1121     zipr->rd_ser = GNUNET_malloc (len);
1122     GNUNET_NAMESTORE_records_serialize(rd_count, rd, len, zipr->rd_ser);
1123     zipr->rd_ser_len = len;
1124   }
1125 }
1126
1127 static void handle_iteration_start (void *cls,
1128                           struct GNUNET_SERVER_Client * client,
1129                           const struct GNUNET_MessageHeader * message)
1130 {
1131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1132
1133   struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message;
1134   struct GNUNET_NAMESTORE_Client *nc;
1135   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1136   struct ZoneIterationResponseMessage zir_msg;
1137   struct ZoneIterationProcResult zipr;
1138   int res;
1139
1140   nc = client_lookup(client);
1141   if (nc == NULL)
1142   {
1143     GNUNET_break_op (0);
1144     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1145     return;
1146   }
1147
1148   zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1149   zi->request_id = ntohl (zis_msg->gns_header.r_id);
1150   zi->offset = 0;
1151   zi->client = nc;
1152   zi->zone = zis_msg->zone;
1153
1154   GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1155
1156   res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr);
1157   switch (res) {
1158     case GNUNET_OK:
1159       /* GNUNET_OK on success */
1160
1161       break;
1162     case GNUNET_SYSERR:
1163       /* GNUNET_SYSERR on error */
1164       break;
1165     case GNUNET_NO:
1166       /* GNUNET_NO if there were no results, */
1167       break;
1168     default:
1169       break;
1170   }
1171
1172
1173
1174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE");
1175   zir_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1176   zir_msg.gns_header.r_id = htonl(zi->request_id);
1177   zir_msg.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1178
1179
1180   GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO);
1181
1182
1183   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1184 }
1185
1186 static void handle_iteration_stop (void *cls,
1187                           struct GNUNET_SERVER_Client * client,
1188                           const struct GNUNET_MessageHeader * message)
1189 {
1190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP");
1191
1192   struct GNUNET_NAMESTORE_Client *nc;
1193   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1194   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1195   uint32_t rid;
1196
1197   nc = client_lookup(client);
1198   if (nc == NULL)
1199   {
1200     GNUNET_break_op (0);
1201     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202     return;
1203   }
1204
1205   rid = ntohl (zis_msg->gns_header.r_id);
1206   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1207   {
1208     if (zi->request_id == rid)
1209       break;
1210   }
1211   if (zi == NULL)
1212   {
1213     GNUNET_break_op (0);
1214     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1215     return;
1216   }
1217
1218   GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi);
1219   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone));
1220   GNUNET_free (zi);
1221
1222   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1223 }
1224
1225 static void handle_iteration_next (void *cls,
1226                           struct GNUNET_SERVER_Client * client,
1227                           const struct GNUNET_MessageHeader * message)
1228 {
1229   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
1230
1231   struct GNUNET_NAMESTORE_Client *nc;
1232   struct GNUNET_NAMESTORE_ZoneIteration *zi;
1233   struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message;
1234   uint32_t rid;
1235   int res;
1236
1237   nc = client_lookup(client);
1238   if (nc == NULL)
1239   {
1240     GNUNET_break_op (0);
1241     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1242     return;
1243   }
1244
1245   rid = ntohl (zis_msg->gns_header.r_id);
1246   for (zi = nc->op_head; zi != NULL; zi = zi->next)
1247   {
1248     if (zi->request_id == rid)
1249       break;
1250   }
1251   if (zi == NULL)
1252   {
1253     GNUNET_break_op (0);
1254     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1255     return;
1256   }
1257
1258   zi->offset++;
1259   res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi);
1260 }
1261
1262
1263
1264 /**
1265  * Process template requests.
1266  *
1267  * @param cls closure
1268  * @param server the initialized server
1269  * @param cfg configuration to use
1270  */
1271 static void
1272 run (void *cls, struct GNUNET_SERVER_Handle *server,
1273      const struct GNUNET_CONFIGURATION_Handle *cfg)
1274 {
1275   char * database;
1276
1277   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
1278
1279   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1280     {&handle_start, NULL,
1281      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
1282     {&handle_stop, NULL,
1283      GNUNET_MESSAGE_TYPE_NAMESTORE_DISCONNECT, sizeof (struct DisconnectMessage)},
1284     {&handle_lookup_name, NULL,
1285      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
1286     {&handle_record_put, NULL,
1287     GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
1288     {&handle_record_create, NULL,
1289      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
1290     {&handle_record_remove, NULL,
1291      GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
1292     {&handle_iteration_start, NULL,
1293      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)},
1294     {&handle_iteration_stop, NULL,
1295      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)},
1296     {&handle_iteration_next, NULL,
1297      GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0},
1298     {NULL, NULL, 0, 0}
1299   };
1300
1301   GSN_cfg = cfg;
1302
1303   /* Loading database plugin */
1304   if (GNUNET_OK !=
1305       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
1306                                              &database))
1307     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
1308
1309   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
1310   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
1311   if (GSN_database == NULL)
1312     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
1313         db_lib_name);
1314   GNUNET_free (database);
1315
1316   /* Configuring server handles */
1317   GNUNET_SERVER_add_handlers (server, handlers);
1318   snc = GNUNET_SERVER_notification_context_create (server, 16);
1319   GNUNET_SERVER_disconnect_notify (server,
1320                                    &client_disconnect_notification,
1321                                    NULL);
1322
1323   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1324                                 NULL);
1325
1326 }
1327
1328
1329 /**
1330  * The main function for the template service.
1331  *
1332  * @param argc number of arguments from the command line
1333  * @param argv command line arguments
1334  * @return 0 ok, 1 on error
1335  */
1336 int
1337 main (int argc, char *const *argv)
1338 {
1339   return (GNUNET_OK ==
1340           GNUNET_SERVICE_run (argc, argv, "namestore",
1341                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1342 }
1343
1344 /* end of gnunet-service-namestore.c */
1345