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