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