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