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