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