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