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