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