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