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