-fix
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
index e14497056d969a7ebaa5e4c4974b3b01cce973c1..f180f6282bddf83a00fe80d3d34d008c3ec397b9 100644 (file)
@@ -35,6 +35,7 @@
 #include "gnunet_dns_service.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_dnsparser_lib.h"
+#include "../dns/dnsparser.h"
 #include "gnunet_gns_service.h"
 #include "block_gns.h"
 #include "gns.h"
@@ -65,11 +66,21 @@ static struct GNUNET_DHT_Handle *dht_handle;
  */
 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
 
+/**
+ * Heap for namestore queues
+ */
+static struct GNUNET_CONTAINER_Heap *ns_task_heap;
+
 /**
  * Maximum amount of parallel queries in background
  */
 static unsigned long long max_allowed_background_queries;
 
+/**
+ * Maximum amount of parallel namestore tasks in background
+ */
+static unsigned long long max_allowed_ns_tasks;
+
 /**
  * Wheather or not to ignore pending records
  */
@@ -90,6 +101,36 @@ static struct GetPseuAuthorityHandle *gph_head;
  */
 static struct GetPseuAuthorityHandle *gph_tail;
 
+/**
+ * Resolver lookup list
+ */
+static struct ResolverHandle *rlh_head;
+
+/**
+ * Resolver lookup list
+ */
+static struct ResolverHandle *rlh_tail;
+
+/**
+ * Resolver shorten list
+ */
+static struct ResolverHandle *nsh_head;
+
+/**
+ * Resolver shorten list
+ */
+static struct ResolverHandle *nsh_tail;
+
+/**
+ * Resolver get auth list
+ */
+static struct ResolverHandle *nah_head;
+
+/**
+ * Resolver get auth list
+ */
+static struct ResolverHandle *nah_tail;
+
 /**
  * a resolution identifier pool variable
  * FIXME overflow?
@@ -97,6 +138,31 @@ static struct GetPseuAuthorityHandle *gph_tail;
  */
 static unsigned long long rid = 0;
 
+static int
+is_srv (char* name)
+{
+  char* ndup;
+  int ret = 1;
+
+  if (*name != '_')
+    return 0;
+  if (NULL == strstr (name, "._"))
+    return 0;
+
+  ndup = GNUNET_strdup (name);
+  strtok (ndup, ".");
+
+  if (NULL == strtok (NULL, "."))
+    ret = 0;
+
+  if (NULL == strtok (NULL, "."))
+    ret = 0;
+
+  if (NULL != strtok (NULL, "."))
+    ret = 0;
+
+  return ret;
+}
 
 /**
  * Determine if this name is canonical.
@@ -110,14 +176,23 @@ static unsigned long long rid = 0;
 static int
 is_canonical(char* name)
 {
-  uint32_t len = strlen(name);
-  int i;
+  char* ndup;
+  char* tok;
+
+  ndup = GNUNET_strdup (name);
+  strtok (ndup, ".");
 
-  for (i=0; i<len; i++)
+  for (tok = strtok (NULL, "."); tok != NULL; tok = strtok (NULL, "."))
   {
-    if (*(name+i) == '.')
-      return 0;
+    /*
+     * probably srv
+     */
+    if (*tok == '_')
+      continue;
+    GNUNET_free (ndup);
+    return 0;
   }
+  GNUNET_free (ndup);
   return 1;
 }
 
@@ -131,6 +206,26 @@ static void
 shorten_authority_chain (struct GetPseuAuthorityHandle *gph);
 
 
+static void
+create_pseu_cont (void* cls, int32_t success, const char* emsg)
+{
+  //FIXME do sth with error
+  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct AuthorityChain *iter;
+
+  gph->namestore_task = NULL;
+  do
+  {
+    iter = gph->ahead->next;
+    GNUNET_free (gph->ahead);
+    gph->ahead = iter;
+  } while (iter != NULL);
+  GNUNET_CRYPTO_rsa_key_free (gph->key);
+  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
+  GNUNET_free (gph);
+}
+
+
 /**
  * Namestore calls this function if we have record for this name.
  * (or with rd_count=0 to indicate no matches)
@@ -155,6 +250,7 @@ process_pseu_lookup_ns (void* cls,
   struct GNUNET_NAMESTORE_RecordData new_pkey;
   struct AuthorityChain *iter;
 
+  gph->namestore_task = NULL;
   if (rd_count > 0)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -191,7 +287,7 @@ process_pseu_lookup_ns (void* cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name);
     memcpy (gph->test_name, gph->name, strlen (gph->name)+1);
-    GNUNET_NAMESTORE_lookup_record (namestore_handle,
+    gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
                                     &gph->our_zone,
                                     gph->test_name,
                                     GNUNET_NAMESTORE_TYPE_ANY,
@@ -211,22 +307,12 @@ process_pseu_lookup_ns (void* cls,
   new_pkey.flags = GNUNET_NAMESTORE_RF_AUTHORITY
                  | GNUNET_NAMESTORE_RF_PRIVATE
                  | GNUNET_NAMESTORE_RF_PENDING;
-  GNUNET_NAMESTORE_record_create (namestore_handle,
+  gph->namestore_task = GNUNET_NAMESTORE_record_create (namestore_handle,
                                   gph->key,
                                   gph->test_name,
                                   &new_pkey,
-                                  NULL, //cont
-                                  NULL); //cls
-  do
-  {
-    iter = gph->ahead->next;
-    GNUNET_free (gph->ahead);
-    gph->ahead = iter;
-  } while (iter != NULL);
-  GNUNET_CRYPTO_rsa_key_free (gph->key);
-  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-  GNUNET_free (gph);
-
+                                  &create_pseu_cont, //cont
+                                  gph); //cls
 }
 
 /**
@@ -254,7 +340,7 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
   /**
    * Check for collision
    */
-  GNUNET_NAMESTORE_lookup_record (namestore_handle,
+  gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
                                   &gph->our_zone,
                                   gph->test_name,
                                   GNUNET_NAMESTORE_TYPE_ANY,
@@ -444,6 +530,7 @@ process_auth_discovery_ns_result(void* cls,
   struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
   struct AuthorityChain *iter;
   
+  gph->namestore_task = NULL;
   /* no pseu found */
   if (rd_count == 0)
   {
@@ -532,7 +619,8 @@ process_zone_to_name_discover (void *cls,
 {
   struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
   struct AuthorityChain *iter;
-
+  
+  gph->namestore_task = NULL;
   /* we found a match in our own zone */
   if (rd_len != 0)
   {
@@ -553,7 +641,7 @@ process_zone_to_name_discover (void *cls,
   else
   {
 
-    GNUNET_NAMESTORE_lookup_record (namestore_handle,
+    gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
                                     &gph->ahead->zone,
                                     "+",
                                     GNUNET_GNS_RECORD_PSEU,
@@ -577,7 +665,7 @@ shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
               "GNS_AUTO_PSEU: New authority %s discovered\n",
               gph->ahead->name);
 
-  GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+  gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                  &gph->our_zone,
                                  &gph->ahead->zone,
                                  &process_zone_to_name_discover,
@@ -631,6 +719,7 @@ start_shorten (struct AuthorityChain *atail,
  * @param nh the namestore handle
  * @param dh the dht handle
  * @param lz the local zone's hash
+ * @param cfg configuration handle
  * @param max_bg_queries maximum number of parallel background queries in dht
  * @param ignore_pending ignore records that still require user confirmation
  *        on lookup
@@ -649,12 +738,22 @@ gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
   local_zone = lz;
   dht_lookup_heap =
     GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
+  ns_task_heap =
+    GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
   max_allowed_background_queries = max_bg_queries;
+  max_allowed_ns_tasks = GNUNET_GNS_MAX_NS_TASKS;
+
   ignore_pending_records = ignore_pending;
 
   gph_head = NULL;
   gph_tail = NULL;
-
+  rlh_head = NULL;
+  rlh_tail = NULL;
+  nsh_head = NULL;
+  nsh_tail = NULL;
+  nah_head = NULL;
+  nah_tail = NULL;
+  
   GNUNET_RESOLVER_connect (cfg);
   
   if (NULL == vpn_handle)
@@ -677,8 +776,55 @@ gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
   return GNUNET_SYSERR;
 }
 
+
 /**
- * Cleanup background lookups
+ * Cleanup ns tasks
+ *
+ * @param cls closure to iterator
+ * @param node heap nodes
+ * @param element the namestorebgtask
+ * @param cost heap cost
+ * @return always GNUNET_YES
+ */
+static int
+cleanup_pending_ns_tasks(void* cls,
+                         struct GNUNET_CONTAINER_HeapNode *node,
+                         void *element,
+                         GNUNET_CONTAINER_HeapCostType cost)
+{
+  struct NamestoreBGTask *nbg = (struct NamestoreBGTask *)element;
+  ResolverCleanupContinuation cont = cls;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_CLEANUP: Terminating ns task\n");
+  GNUNET_NAMESTORE_cancel (nbg->qe);
+
+  GNUNET_CONTAINER_heap_remove_node(node);
+
+  if (GNUNET_CONTAINER_heap_get_size(ns_task_heap) == 0)
+    cont();
+
+  return GNUNET_YES;
+}
+
+
+/**
+ * finish lookup
+ *
+ * @param rh resolver handle
+ * @param rlh record lookup handle
+ * @param rd_count number of results
+ * @param rd results
+ */
+static void
+finish_lookup (struct ResolverHandle *rh,
+               struct RecordLookupHandle* rlh,
+               unsigned int rd_count,
+               const struct GNUNET_NAMESTORE_RecordData *rd);
+
+
+/**
+ * Cleanup background lookups FIXME get rid of this??
  *
  * @param cls closure to iterator
  * @param node heap nodes
@@ -687,10 +833,10 @@ gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
  * @return always GNUNET_YES
  */
 static int
-cleanup_pending_background_queries(void* cls,
-                                   struct GNUNET_CONTAINER_HeapNode *node,
-                                   void *element,
-                                   GNUNET_CONTAINER_HeapCostType cost)
+cleanup_pending_background_queries (void* cls,
+                                    struct GNUNET_CONTAINER_HeapNode *node,
+                                    void *element,
+                                    GNUNET_CONTAINER_HeapCostType cost)
 {
   struct ResolverHandle *rh = (struct ResolverHandle *)element;
   ResolverCleanupContinuation cont = cls;
@@ -698,32 +844,105 @@ cleanup_pending_background_queries(void* cls,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
              rh->id, rh->name);
-  GNUNET_DHT_get_stop(rh->get_handle);
-  rh->get_handle = NULL;
-  rh->proc(rh->proc_cls, rh, 0, NULL);
+  
+  //finish_lookup (rh, rh->proc_cls, 0, NULL);
+  //rh->get_handle = NULL;
+  //rh->proc(rh->proc_cls, rh, 0, NULL);
 
   GNUNET_CONTAINER_heap_remove_node(node);
 
   if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0)
-    cont();
+  {
+    if (GNUNET_CONTAINER_heap_get_size(ns_task_heap) == 0)
+      cont();
+    else
+    {
+      GNUNET_CONTAINER_heap_iterate (ns_task_heap,
+                                     &cleanup_pending_ns_tasks,
+                                     cont);
+    }
+  }
 
 
   return GNUNET_YES;
 }
 
 
+/**
+ * Helper function to free resolver handle
+ *
+ * @param rh the handle to free
+ */
+static void
+free_resolver_handle (struct ResolverHandle* rh)
+{
+  struct AuthorityChain *ac;
+  struct AuthorityChain *ac_next;
+
+  if (NULL == rh)
+    return;
+
+  ac = rh->authority_chain_head;
+
+  while (NULL != ac)
+  {
+    ac_next = ac->next;
+    GNUNET_free(ac);
+    ac = ac_next;
+  }
+  
+  if (NULL != rh->get_handle)
+    GNUNET_DHT_get_stop (rh->get_handle);
+
+  if (NULL != rh->dns_raw_packet)
+    GNUNET_free (rh->dns_raw_packet);
+
+  if (NULL != rh->namestore_task)
+    GNUNET_NAMESTORE_cancel (rh->namestore_task);
+  rh->namestore_task = NULL;
+
+  if (GNUNET_SCHEDULER_NO_TASK != rh->dns_read_task)
+    GNUNET_SCHEDULER_cancel (rh->dns_read_task);
+
+  if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
+    GNUNET_SCHEDULER_cancel (rh->timeout_task);
+
+  if (NULL != rh->dns_sock)
+    GNUNET_NETWORK_socket_close (rh->dns_sock);
+  if (NULL != rh->dns_resolver_handle)
+    GNUNET_RESOLVER_request_cancel (rh->dns_resolver_handle);
+  GNUNET_free(rh);
+}
+
+
+/**
+ * finish shorten
+ *
+ * @param rh resolver handle
+ * @param nsh name shorten handle
+ */
+static void
+finish_shorten (struct ResolverHandle *rh,
+                struct NameShortenHandle *nsh);
+/**
+ * finish get auth
+ *
+ * @param rh resolver handle
+ * @param nah get name authority handle
+ */
+static void
+finish_get_auth (struct ResolverHandle *rh,
+                 struct GetNameAuthorityHandle* rlh);
 /**
  * Shutdown resolver
  */
 void
-gns_resolver_cleanup(ResolverCleanupContinuation cont)
+gns_resolver_cleanup (ResolverCleanupContinuation cont)
 {
-  unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
+  unsigned int s;
   struct GetPseuAuthorityHandle *tmp;
   struct AuthorityChain *iter;
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_CLEANUP: %d pending background queries to terminate\n", s);
   
   tmp = gph_head;
   for (tmp = gph_head; tmp != NULL; tmp = gph_head)
@@ -734,6 +953,10 @@ gns_resolver_cleanup(ResolverCleanupContinuation cont)
     if (tmp->timeout != GNUNET_SCHEDULER_NO_TASK)
       GNUNET_SCHEDULER_cancel (tmp->timeout);
     tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
+
+    if (NULL != tmp->namestore_task)
+      GNUNET_NAMESTORE_cancel (tmp->namestore_task);
+    tmp->namestore_task = NULL;
     
     iter = tmp->ahead;
     do
@@ -747,45 +970,40 @@ gns_resolver_cleanup(ResolverCleanupContinuation cont)
     GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, tmp);
     GNUNET_free (tmp);
   }
+
+  while (NULL != rlh_head)
+  {
+    finish_lookup (rlh_head, rlh_head->proc_cls, 0, NULL);
+  }
   
-  
+  while (NULL != nsh_head)
+  {
+    finish_shorten (nsh_head, nsh_head->proc_cls);
+  }
+
+  while (NULL != nah_head)
+  {
+    finish_get_auth (nah_head, nah_head->proc_cls);
+  }
+
+  s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_CLEANUP: %d pending background queries to terminate\n", s);
   if (0 != s)
     GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
                                    &cleanup_pending_background_queries,
                                    cont);
+  else if (0 != GNUNET_CONTAINER_heap_get_size(ns_task_heap))
+  {
+    GNUNET_CONTAINER_heap_iterate (ns_task_heap,
+                                   &cleanup_pending_ns_tasks,
+                                   cont);
+  }
   else
     cont();
 }
 
 
-/**
- * Helper function to free resolver handle
- *
- * @param rh the handle to free
- */
-static void
-free_resolver_handle(struct ResolverHandle* rh)
-{
-  struct AuthorityChain *ac;
-  struct AuthorityChain *ac_next;
-
-  if (NULL == rh)
-    return;
-
-  ac = rh->authority_chain_head;
-
-  while (NULL != ac)
-  {
-    ac_next = ac->next;
-    GNUNET_free(ac);
-    ac = ac_next;
-  }
-
-  if (NULL != rh->dns_raw_packet)
-    GNUNET_free (rh->dns_raw_packet);
-
-  GNUNET_free(rh);
-}
 
 
 /**
@@ -800,6 +1018,11 @@ on_namestore_record_put_result(void *cls,
                                int32_t success,
                                const char *emsg)
 {
+  struct NamestoreBGTask *nbg = cls;
+
+  GNUNET_CONTAINER_heap_remove_node (nbg->node);
+  GNUNET_free (nbg);
+
   if (GNUNET_NO == success)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -858,7 +1081,7 @@ dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   char new_name[MAX_DNS_NAME_LENGTH];
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n",
+             "GNS_PHASE_REC-%llu: dht lookup for query %s (%ds)timed out.\n",
              rh->id, rh->name, rh->timeout.rel_value);
   /**
    * Start resolution in bg
@@ -869,7 +1092,7 @@ dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                   rh->name, GNUNET_GNS_TLD);
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n",
+             "GNS_PHASE_REC-%llu: Starting background lookup for %s type %d\n",
              rh->id, new_name, rlh->record_type);
 
   gns_resolver_lookup_record(rh->authority,
@@ -926,7 +1149,7 @@ process_record_result_dht(void* cls,
 
   rh = (struct ResolverHandle *)cls;
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size);
+             "GNS_PHASE_REC-%llu: got dht result (size=%d)\n", rh->id, size);
 
   //FIXME maybe check expiration here, check block type
 
@@ -955,6 +1178,8 @@ process_record_result_dht(void* cls,
   num_records = ntohl(nrb->rd_count);
   {
     struct GNUNET_NAMESTORE_RecordData rd[num_records];
+    struct NamestoreBGTask *ns_heap_root;
+    struct NamestoreBGTask *namestore_bg_task;
 
     rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
     rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
@@ -965,23 +1190,23 @@ process_record_result_dht(void* cls,
                                                                rd))
     {
       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-                 "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id);
+                 "GNS_PHASE_REC-%llu: Error deserializing data!\n", rh->id);
       return;
     }
 
     for (i=0; i<num_records; i++)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n",
+                 "GNS_PHASE_REC-%llu: Got name: %s (wanted %s)\n",
                  rh->id, name, rh->name);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Got type: %d (wanted %d)\n",
+                 "GNS_PHASE_REC-%llu: Got type: %d (wanted %d)\n",
                  rh->id, rd[i].record_type, rlh->record_type);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Got data length: %d\n",
+                 "GNS_PHASE_REC-%llu: Got data length: %d\n",
                  rh->id, rd[i].data_size);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Got flag %d\n",
+                 "GNS_PHASE_REC-%llu: Got flag %d\n",
                  rh->id, rd[i].flags);
 
       if ((strcmp(name, rh->name) == 0) &&
@@ -996,9 +1221,20 @@ process_record_result_dht(void* cls,
      * FIXME check pubkey against existing key in namestore?
      * https://gnunet.org/bugs/view.php?id=2179
      */
+    if (max_allowed_ns_tasks <=
+        GNUNET_CONTAINER_heap_get_size (ns_task_heap))
+    {
+      ns_heap_root = GNUNET_CONTAINER_heap_remove_root (ns_task_heap);
+      GNUNET_NAMESTORE_cancel (ns_heap_root->qe);
 
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "GNS_PHASE_REC-%llu: Replacing oldest background ns task\n",
+                 rh->id);
+    }
+    
     /* Save to namestore */
-    GNUNET_NAMESTORE_record_put (namestore_handle,
+    namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask));
+    namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
                                  name,
                                  exp,
@@ -1006,13 +1242,17 @@ process_record_result_dht(void* cls,
                                  rd,
                                  &nrb->signature,
                                  &on_namestore_record_put_result, //cont
-                                 NULL); //cls
+                                 namestore_bg_task);
 
+    namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap,
+                                  namestore_bg_task,
+                                  GNUNET_TIME_absolute_get().abs_value);
 
+  
     if (rh->answered)
-      rh->proc(rh->proc_cls, rh, num_records, rd);
-    else
-      rh->proc(rh->proc_cls, rh, 0, NULL);
+     rh->proc(rh->proc_cls, rh, num_records, rd);
+   else
+     rh->proc(rh->proc_cls, rh, 0, NULL);
   }
 
 }
@@ -1043,7 +1283,7 @@ resolve_record_dht (struct ResolverHandle *rh)
   GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n",
+             "GNS_PHASE_REC-%llu: starting dht lookup for %s with key: %s\n",
              rh->id, rh->name, (char*)&lookup_key_string);
 
   //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
@@ -1058,7 +1298,7 @@ resolve_record_dht (struct ResolverHandle *rh)
     {
 
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id);
+                 "GNS_PHASE_REC-%llu: Adjusting timeout\n", rh->id);
       /*
        * Set timeout for authority lookup phase to 1/2
        */
@@ -1084,7 +1324,7 @@ resolve_record_dht (struct ResolverHandle *rh)
       rh_heap_root->dht_heap_node = NULL;
 
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n",
+                 "GNS_PHASE_REC-%llu: Replacing oldest background query for %s\n",
                  rh->id, rh_heap_root->name);
       rh_heap_root->proc(rh_heap_root->proc_cls,
                          rh_heap_root,
@@ -1125,12 +1365,12 @@ resolve_record_dht (struct ResolverHandle *rh)
  * @param signature the signature of the authority for the record data
  */
 static void
-process_record_result_ns(void* cls,
-                         const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
-                         struct GNUNET_TIME_Absolute expiration,
-                         const char *name, unsigned int rd_count,
-                         const struct GNUNET_NAMESTORE_RecordData *rd,
-                         const struct GNUNET_CRYPTO_RsaSignature *signature)
+process_record_result_ns (void* cls,
+                          const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+                          struct GNUNET_TIME_Absolute expiration,
+                          const char *name, unsigned int rd_count,
+                          const struct GNUNET_NAMESTORE_RecordData *rd,
+                          const struct GNUNET_CRYPTO_RsaSignature *signature)
 {
   struct ResolverHandle *rh;
   struct RecordLookupHandle *rlh;
@@ -1141,6 +1381,8 @@ process_record_result_ns(void* cls,
 
   rh = (struct ResolverHandle *) cls;
   rlh = (struct RecordLookupHandle *)rh->proc_cls;
+
+  rh->namestore_task = NULL;
   GNUNET_CRYPTO_short_hash(key,
                            sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                            &zone);
@@ -1166,11 +1408,11 @@ process_record_result_ns(void* cls,
      * Lookup terminated and no results
      */
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n",
+               "GNS_PHASE_REC-%llu: Namestore lookup for %s terminated without results\n",
                rh->id, name);
 
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Record %s unknown in namestore\n",
+               "GNS_PHASE_REC-%llu: Record %s unknown in namestore\n",
                rh->id, rh->name);
     /**
      * Our zone and no result? Cannot resolve TT
@@ -1182,7 +1424,7 @@ process_record_result_ns(void* cls,
   else
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n",
+               "GNS_PHASE_REC-%llu: Processing additional result %s from namestore\n",
                rh->id, name);
     for (i=0; i<rd_count;i++)
     {
@@ -1193,7 +1435,7 @@ process_record_result_ns(void* cls,
           (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
       {
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "GNS_PHASE_REC-%d: Record %s is awaiting user confirmation. Skipping\n",
+                   "GNS_PHASE_REC-%llu: Record %s is awaiting user confirmation. Skipping\n",
                    rh->id, name);
         continue;
       }
@@ -1204,7 +1446,7 @@ process_record_result_ns(void* cls,
           == 0)
       {
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "GNS_PHASE_REC-%d: This record is expired. Skipping\n",
+                   "GNS_PHASE_REC-%llu: This record is expired. Skipping\n",
                    rh->id);
         continue;
       }
@@ -1217,13 +1459,13 @@ process_record_result_ns(void* cls,
     if (rh->answered == 0)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 
-                 "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id);
+                 "GNS_PHASE_REC-%llu: No answers found. This is odd!\n", rh->id);
       rh->proc(rh->proc_cls, rh, 0, NULL);
       return;
     }
 
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n",
+               "GNS_PHASE_REC-%llu: Found %d answer(s) to query in %d records!\n",
                rh->id, rh->answered, rd_count);
 
     rh->proc(rh->proc_cls, rh, rd_count, rd);
@@ -1253,17 +1495,17 @@ process_record_result_vpn (void* cls, int af, const void *address)
   if (af == AF_INET)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Answer is IPv4!\n",
+               "GNS_PHASE_REC-%llu: Answer is IPv4!\n",
                rh->id);
-    if (rlh->record_type != GNUNET_GNS_RECORD_TYPE_A)
+    if (rlh->record_type != GNUNET_GNS_RECORD_A)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Requested record is not IPv4!\n",
+                 "GNS_PHASE_REC-%llu: Requested record is not IPv4!\n",
                  rh->id);
       rh->proc (rh->proc_cls, rh, 0, NULL);
       return;
     }
-    rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
+    rd.record_type = GNUNET_GNS_RECORD_A;
     rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter... */
     rd.data = address;
     rd.data_size = sizeof (struct in_addr);
@@ -1274,12 +1516,12 @@ process_record_result_vpn (void* cls, int af, const void *address)
   else if (af == AF_INET6)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: Answer is IPv6!\n",
+               "GNS_PHASE_REC-%llu: Answer is IPv6!\n",
                rh->id);
     if (rlh->record_type != GNUNET_GNS_RECORD_AAAA)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_REC-%d: Requested record is not IPv6!\n",
+                 "GNS_PHASE_REC-%llu: Requested record is not IPv6!\n",
                  rh->id);
       rh->proc (rh->proc_cls, rh, 0, NULL);
       return;
@@ -1294,25 +1536,13 @@ process_record_result_vpn (void* cls, int af, const void *address)
   }
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: Got garbage from VPN!\n",
+             "GNS_PHASE_REC-%llu: Got garbage from VPN!\n",
              rh->id);
   rh->proc (rh->proc_cls, rh, 0, NULL);
 }
 
 
-/**
- * finish lookup
- *
- * @param rh resolver handle
- * @param rlh record lookup handle
- * @param rd_count number of results
- * @param rd results
- */
-static void
-finish_lookup(struct ResolverHandle *rh,
-              struct RecordLookupHandle* rlh,
-              unsigned int rd_count,
-              const struct GNUNET_NAMESTORE_RecordData *rd);
+
 
 /**
  * Process VPN lookup result for record
@@ -1332,22 +1562,19 @@ handle_record_vpn (void* cls, struct ResolverHandle *rh,
   if (rd_count == 0)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC_VPN-%d: VPN returned no records. (status: %d)!\n",
+               "GNS_PHASE_REC_VPN-%llu: VPN returned no records. (status: %d)!\n",
                rh->id,
                rh->status);
     /* give up, cannot resolve */
     finish_lookup(rh, rlh, 0, NULL);
-    free_resolver_handle(rh);
     return;
   }
 
   /* results found yay */
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC_VPN-%d: Record resolved from VPN!", rh->id);
+             "GNS_PHASE_REC_VPN-%llu: Record resolved from VPN!", rh->id);
 
   finish_lookup(rh, rlh, rd_count, rd);
-
-  free_resolver_handle(rh);
 }
 
 
@@ -1376,14 +1603,13 @@ handle_dns_resolver (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "No address found in DNS!\n");
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
   
   if (addrlen == sizeof (struct sockaddr_in))
   {
     sai = (struct sockaddr_in*) addr;
-    rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
+    rd.record_type = GNUNET_GNS_RECORD_A;
     rd.data_size = sizeof (struct in_addr);
     rd.data = &sai->sin_addr;
   }
@@ -1399,8 +1625,7 @@ handle_dns_resolver (void *cls,
   rd.flags = 0;
 
   finish_lookup (rh, rlh, 1, &rd);
-  GNUNET_RESOLVER_request_cancel (rh->dns_resolver_handle);
-  free_resolver_handle (rh);
+  
 }
 
 /**
@@ -1414,17 +1639,16 @@ resolve_dns_name (struct ResolverHandle *rh)
   struct RecordLookupHandle *rlh = rh->proc_cls;
   int af;
 
-  if ((rlh->record_type != GNUNET_GNS_RECORD_TYPE_A) &&
+  if ((rlh->record_type != GNUNET_GNS_RECORD_A) &&
       (rlh->record_type != GNUNET_GNS_RECORD_AAAA))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Can only resolve A/AAAA via stub... abort\n");
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
 
-  if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_A)
+  if (rlh->record_type == GNUNET_GNS_RECORD_A)
     af = AF_INET;
   else
     af = AF_INET6;
@@ -1468,10 +1692,8 @@ read_dns_response (void *cls,
   {
     /* timeout or shutdown */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Terminating DNS query\n");
+                "Terminating DNS query %d\n", tc->reason);
     finish_lookup (rh, rlh, 0, NULL);
-    GNUNET_NETWORK_socket_close (rh->dns_sock);
-    free_resolver_handle (rh);
     return;
   }
 
@@ -1485,8 +1707,6 @@ read_dns_response (void *cls,
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
     finish_lookup (rh, rlh, 0, NULL);
-    GNUNET_NETWORK_socket_close (rh->dns_sock);
-    free_resolver_handle (rh);
     return;
   }
 
@@ -1497,8 +1717,6 @@ read_dns_response (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Failed to parse DNS reply!\n");
     finish_lookup (rh, rlh, 0, NULL);
-    GNUNET_NETWORK_socket_close (rh->dns_sock);
-    free_resolver_handle (rh);
     return;
   }
 
@@ -1509,7 +1727,7 @@ read_dns_response (void *cls,
                packet->answers[i].type,
                rlh->record_type);
     /* http://tools.ietf.org/html/rfc1034#section-3.6.2 */
-    if (packet->answers[i].type == GNUNET_GNS_RECORD_TYPE_CNAME)
+    if (packet->answers[i].type == GNUNET_GNS_RECORD_CNAME)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "CNAME... restarting query with %s\n",
@@ -1533,9 +1751,7 @@ read_dns_response (void *cls,
       rd.flags = 0;
       rd.expiration_time = packet->answers[i].expiration_time.abs_value;
       finish_lookup (rh, rlh, 1, &rd);
-      GNUNET_NETWORK_socket_close (rh->dns_sock);
       GNUNET_DNSPARSER_free_packet (packet);
-      free_resolver_handle (rh);
       return;
     }
   }
@@ -1568,7 +1784,7 @@ read_dns_response (void *cls,
   for (i = 0; i < packet->num_authority_records; i++)
   {
     
-    if (packet->authority_records[i].type == GNUNET_GNS_RECORD_TYPE_NS)
+    if (packet->authority_records[i].type == GNUNET_GNS_RECORD_NS)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Found NS delegation!\n");
@@ -1583,7 +1799,7 @@ read_dns_response (void *cls,
     if (found_delegation == GNUNET_NO)
       break;
 
-    if ((packet->additional_records[i].type == GNUNET_GNS_RECORD_TYPE_A) &&
+    if ((packet->additional_records[i].type == GNUNET_GNS_RECORD_A) &&
         (0 == strcmp (packet->additional_records[i].name, delegation_name)))
     {
       GNUNET_assert (sizeof (struct in_addr) ==
@@ -1600,8 +1816,6 @@ read_dns_response (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Nothing useful in DNS reply!\n");
   finish_lookup (rh, rlh, 0, NULL);
-  GNUNET_NETWORK_socket_close (rh->dns_sock);
-  free_resolver_handle (rh);
   GNUNET_DNSPARSER_free_packet (packet);
   return;
 }
@@ -1616,6 +1830,10 @@ send_dns_packet (struct ResolverHandle *rh)
 {
   struct GNUNET_NETWORK_FDSet *rset = GNUNET_NETWORK_fdset_create ();
   GNUNET_NETWORK_fdset_set (rset, rh->dns_sock);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending %dbyte DNS query\n",
+              rh->dns_raw_packet_size);
   
   GNUNET_NETWORK_socket_sendto (rh->dns_sock,
                                 rh->dns_raw_packet,
@@ -1677,7 +1895,7 @@ resolve_record_dns (struct ResolverHandle *rh,
   for (i = 0; i < rd_count; i++)
   {
     /* Synthesize dns name */
-    if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS)
+    if (rd[i].record_type == GNUNET_GNS_RECORD_NS)
     {
       strcpy (rh->dns_zone, (char*)rd[i].data);
       if (0 == strcmp (rh->name, ""))
@@ -1686,7 +1904,7 @@ resolve_record_dns (struct ResolverHandle *rh,
         sprintf (rh->dns_name, "%s.%s", rh->name, (char*)rd[i].data);
     }
     /* The glue */
-    if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+    if (rd[i].record_type == GNUNET_GNS_RECORD_A)
       dnsip = *((struct in_addr*)rd[i].data);
   }
   
@@ -1702,7 +1920,6 @@ resolve_record_dns (struct ResolverHandle *rh,
                 "GNS_PHASE_REC_DNS-%llu: Error creating udp socket for dns!\n",
                 rh->id);
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
 
@@ -1716,9 +1933,7 @@ resolve_record_dns (struct ResolverHandle *rh,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "GNS_PHASE_REC_DNS-%llu: Error binding udp socket for dns!\n",
                 rh->id);
-    GNUNET_NETWORK_socket_close (rh->dns_sock);
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
   
@@ -1748,7 +1963,6 @@ resolve_record_dns (struct ResolverHandle *rh,
                 rh->id);
     GNUNET_NETWORK_socket_close (rh->dns_sock);
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
 
@@ -1776,14 +1990,10 @@ resolve_record_vpn (struct ResolverHandle *rh,
                     int rd_count,
                     const struct GNUNET_NAMESTORE_RecordData *rd)
 {
-  int af;
-  int proto;
-  struct GNUNET_HashCode peer_id;
-  struct GNUNET_CRYPTO_HashAsciiEncoded s_pid;
+  struct RecordLookupHandle *rlh = rh->proc_cls;
   struct GNUNET_HashCode serv_desc;
-  struct GNUNET_CRYPTO_HashAsciiEncoded s_sd;
-  char* pos;
-  size_t len = (sizeof (uint32_t) * 2) + (sizeof (struct GNUNET_HashCode) * 2);
+  struct vpn_data* vpn;
+  int af;
   
   /* We cancel here as to not include the ns lookup in the timeout */
   if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
@@ -1801,38 +2011,23 @@ resolve_record_vpn (struct ResolverHandle *rh,
                    rh->priv_key);
   }
 
-  /* Extracting VPN information FIXME rd parsing with NS API?*/
-  if (len != rd->data_size)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR!\n",
-                rh->id);
-    finish_lookup (rh, rh->proc_cls, 0, NULL);
-    free_resolver_handle (rh);
-    return;
-  }
-
-  pos = (char*)rd;
-  memcpy (&af, pos, sizeof (uint32_t));
-  pos += sizeof (uint32_t);
-  memcpy (&proto, pos, sizeof (uint32_t));
-  pos += sizeof (uint32_t);
-  memcpy (&s_pid, pos, sizeof (struct GNUNET_HashCode));
-  pos += sizeof (struct GNUNET_HashCode);
-  memcpy (&s_sd, pos, sizeof (struct GNUNET_HashCode));
+  vpn = (struct vpn_data*)rd->data;
 
 
-  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_pid, &peer_id)) ||
-      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_sd, &serv_desc)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR hashes!\n",
-                rh->id);
-    finish_lookup (rh, rh->proc_cls, 0, NULL);
-    free_resolver_handle (rh);
-    return;
-  }
+  GNUNET_CRYPTO_hash ((char*)&vpn[1],
+                      strlen ((char*)&vpn[1]) + 1,
+                      &serv_desc);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS_PHASE_REC_VPN-%llu: proto %hu peer %s!\n",
+              rh->id,
+              ntohs (vpn->proto),
+              GNUNET_h2s (&vpn->peer));
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS_PHASE_REC_VPN-%llu: service %s -> %s!\n",
+              rh->id,
+              (char*)&vpn[1],
+              GNUNET_h2s (&serv_desc));
   rh->proc = &handle_record_vpn;
 
   if (NULL == vpn_handle)
@@ -1841,14 +2036,18 @@ resolve_record_vpn (struct ResolverHandle *rh,
                 "GNS_PHASE_REC_VPN-%llu: VPN not connected!\n",
                 rh->id);
     finish_lookup (rh, rh->proc_cls, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
+
+  if (rlh->record_type == GNUNET_GNS_RECORD_A)
+    af = AF_INET;
+  else
+    af = AF_INET6;
   
   //FIXME timeout??
   rh->vpn_handle = GNUNET_VPN_redirect_to_peer (vpn_handle,
-                                          af, proto,
-                                          (struct GNUNET_PeerIdentity*)&peer_id,
+                                          af, ntohs (vpn->proto),
+                                          (struct GNUNET_PeerIdentity *)&vpn->peer,
                                           &serv_desc,
                                           GNUNET_NO, //nac
                                           GNUNET_TIME_UNIT_FOREVER_ABS, //FIXME
@@ -1891,7 +2090,7 @@ resolve_record_ns(struct ResolverHandle *rh)
    * since we tried to resolve it to an authority
    * and failed.
    **/
-  GNUNET_NAMESTORE_lookup_record(namestore_handle,
+  rh->namestore_task = GNUNET_NAMESTORE_lookup_record(namestore_handle,
                                  &rh->authority,
                                  rh->name,
                                  rlh->record_type,
@@ -2018,6 +2217,7 @@ process_pkey_revocation_result_ns (void *cls,
   struct GNUNET_TIME_Relative remaining_time;
   int i;
   
+  rh->namestore_task = NULL;
   remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
   
   for (i = 0; i < rd_count; i++)
@@ -2043,7 +2243,7 @@ process_pkey_revocation_result_ns (void *cls,
     if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-        "GNS_PHASE_DELEGATE_REV-%d: Starting background lookup for %s type %d\n",
+        "GNS_PHASE_DELEGATE_REV-%llu: Starting background lookup for %s type %d\n",
         rh->id, "+.gnunet", GNUNET_GNS_RECORD_REV);
 
       gns_resolver_lookup_record(rh->authority,
@@ -2058,7 +2258,7 @@ process_pkey_revocation_result_ns (void *cls,
     }
   }
  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_DELEGATE_REV-%llu: Revocation checkpassed\n",
+             "GNS_PHASE_DELEGATE_REV-%llu: Revocation check passed\n",
              rh->id);
   /**
    * We are done with PKEY resolution if name is empty
@@ -2072,6 +2272,40 @@ process_pkey_revocation_result_ns (void *cls,
 }
 
 
+/**
+ * Callback when record data is put into namestore
+ *
+ * @param cls the closure
+ * @param success GNUNET_OK on success
+ * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
+ */
+void
+on_namestore_delegation_put_result(void *cls,
+                                   int32_t success,
+                                   const char *emsg)
+{
+  struct NamestoreBGTask *nbg = cls;
+
+  GNUNET_CONTAINER_heap_remove_node (nbg->node);
+  GNUNET_free (nbg);
+
+  if (GNUNET_NO == success)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GNS_NS: records already in namestore\n");
+    return;
+  }
+  else if (GNUNET_YES == success)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GNS_NS: records successfully put in namestore\n");
+    return;
+  }
+
+  GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+             "GNS_NS: Error putting records into namestore: %s\n", emsg);
+}
+
 /**
  * Function called when we get a result from the dht
  * for our query. Recursively tries to resolve authorities
@@ -2134,6 +2368,8 @@ process_delegation_result_dht(void* cls,
   name = (char*)&nrb[1];
   {
     struct GNUNET_NAMESTORE_RecordData rd[num_records];
+    struct NamestoreBGTask *ns_heap_root;
+    struct NamestoreBGTask *namestore_bg_task;
     
     rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
     rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
@@ -2169,8 +2405,8 @@ process_delegation_result_dht(void* cls,
                  rh->id, rd[i].flags);
       
       if ((rd[i].record_type == GNUNET_GNS_RECORD_VPN) ||
-          (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS) ||
-          (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_CNAME))
+          (rd[i].record_type == GNUNET_GNS_RECORD_NS) ||
+          (rd[i].record_type == GNUNET_GNS_RECORD_CNAME))
       {
         /**
          * This is a VPN,NS,CNAME entry. Let namestore handle this after caching
@@ -2220,18 +2456,34 @@ process_delegation_result_dht(void* cls,
     if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
                                           &zone))
     {
-      GNUNET_NAMESTORE_record_put (namestore_handle,
+      if (max_allowed_ns_tasks <=
+          GNUNET_CONTAINER_heap_get_size (ns_task_heap))
+      {
+        ns_heap_root = GNUNET_CONTAINER_heap_remove_root (ns_task_heap);
+        GNUNET_NAMESTORE_cancel (ns_heap_root->qe);
+
+        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                   "GNS_PHASE_REC-%llu: Replacing oldest background ns task\n",
+                   rh->id);
+      }
+      
+      namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask));
+
+      namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap,
+                                    namestore_bg_task,
+                                    GNUNET_TIME_absolute_get().abs_value);
+      namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
                                  name,
                                  exp,
                                  num_records,
                                  rd,
                                  &nrb->signature,
-                                 &on_namestore_record_put_result, //cont
-                                 NULL); //cls
+                                 &on_namestore_delegation_put_result, //cont
+                                 namestore_bg_task); //cls
     }
   }
-  
+
   if (rh->answered)
   {
     rh->answered = 0;
@@ -2240,8 +2492,8 @@ process_delegation_result_dht(void* cls,
      * FIXME in this case. should we ask namestore again?
      */
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
-      rh->id, rh->authority_name, rh->name);
+    "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
+    rh->id, rh->authority_name, rh->name);
 
     if (strcmp(rh->name, "") == 0)
     {
@@ -2259,32 +2511,13 @@ process_delegation_result_dht(void* cls,
       rh->proc = &handle_delegation_ns;
 
     /* Check for key revocation and delegate */
-    GNUNET_NAMESTORE_lookup_record (namestore_handle,
+    rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
                                     &rh->authority,
                                     "+",
                                     GNUNET_GNS_RECORD_REV,
                                     &process_pkey_revocation_result_ns,
-                                    rh);   
-    
-    /*if (strcmp(rh->name, "") == 0)
-    {
-      if ((rh->priv_key != NULL) && is_canonical (rh->name))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n",
-             rh->id);
-        start_shorten (rh->authority_chain_tail,
-                       rh->priv_key);
-      }
-      
-      rh->proc(rh->proc_cls, rh, 0, NULL);
-    }
-    else
-    {
-      rh->proc = &handle_delegation_ns;
-      resolve_delegation_ns (rh);
-    }
-    */
+                                    rh);
+
     return;
   }
   
@@ -2304,7 +2537,7 @@ process_delegation_result_dht(void* cls,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-           "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
+          "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
            rh->id);
   rh->proc(rh->proc_cls, rh, 0, NULL);
 }
@@ -2312,10 +2545,11 @@ process_delegation_result_dht(void* cls,
 #define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
                         +(MAX_DNS_NAME_LENGTH*2)
 #define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH
+#define MAX_SRV_LENGTH (sizeof(uint16_t)*3)+MAX_DNS_NAME_LENGTH
 
 
 static void
-expand_plus(char** dest, char* src, char* repl)
+expand_plus(char* dest, char* src, char* repl)
 {
   char* pos;
   unsigned int s_len = strlen(src)+1;
@@ -2329,7 +2563,7 @@ expand_plus(char** dest, char* src, char* repl)
                "GNS_POSTPROCESS: %s to short\n", src);
 
     /* no postprocessing */
-    memcpy(*dest, src, s_len+1);
+    memcpy(dest, src, s_len+1);
     return;
   }
   
@@ -2337,17 +2571,17 @@ expand_plus(char** dest, char* src, char* repl)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "GNS_POSTPROCESS: Expanding .+ in %s\n", src);
-    memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
-    strcpy(*dest, src);
-    pos = *dest+s_len-2;
+    memset(dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
+    strcpy(dest, src);
+    pos = dest+s_len-2;
     strcpy(pos, repl);
     pos += strlen(repl);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_POSTPROCESS: Expanded to %s\n", *dest);
+               "GNS_POSTPROCESS: Expanded to %s\n", dest);
   }
   else
   {
-    memcpy(*dest, src, s_len+1);
+    memcpy(dest, src, s_len+1);
   }
 }
 
@@ -2355,15 +2589,20 @@ expand_plus(char** dest, char* src, char* repl)
  * finish lookup
  */
 static void
-finish_lookup(struct ResolverHandle *rh,
-              struct RecordLookupHandle* rlh,
-              unsigned int rd_count,
-              const struct GNUNET_NAMESTORE_RecordData *rd)
+finish_lookup (struct ResolverHandle *rh,
+               struct RecordLookupHandle* rlh,
+               unsigned int rd_count,
+               const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   int i;
   char new_rr_data[MAX_DNS_NAME_LENGTH];
   char new_mx_data[MAX_MX_LENGTH];
   char new_soa_data[MAX_SOA_LENGTH];
+  char new_srv_data[MAX_SRV_LENGTH];
+  struct srv_data *old_srv;
+  struct srv_data *new_srv;
+  struct soa_data *old_soa;
+  struct soa_data *new_soa;
   struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
   char* repl_string;
   char* pos;
@@ -2375,16 +2614,20 @@ finish_lookup(struct ResolverHandle *rh,
     rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   }
 
+  GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
+
   if (rd_count > 0)
     memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
 
   for (i = 0; i < rd_count; i++)
   {
     
-    if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
-        rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
+    if (rd[i].record_type != GNUNET_GNS_RECORD_NS &&
+        rd[i].record_type != GNUNET_GNS_RECORD_PTR &&
+        rd[i].record_type != GNUNET_GNS_RECORD_CNAME &&
         rd[i].record_type != GNUNET_GNS_RECORD_MX &&
-        rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA)
+        rd[i].record_type != GNUNET_GNS_RECORD_SOA &&
+        rd[i].record_type != GNUNET_GNS_RECORD_SRV)
     {
       p_rd[i].data = rd[i].data;
       continue;
@@ -2407,34 +2650,50 @@ finish_lookup(struct ResolverHandle *rh,
     offset = 0;
     if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
     {
-      memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
+      memcpy (new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
       offset = sizeof(uint16_t);
       pos = new_mx_data+offset;
-      expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t),
+      expand_plus(pos, (char*)rd[i].data+sizeof(uint16_t),
                   repl_string);
       offset += strlen(new_mx_data+sizeof(uint16_t))+1;
       p_rd[i].data = new_mx_data;
       p_rd[i].data_size = offset;
     }
-    else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA)
+    else if (rd[i].record_type == GNUNET_GNS_RECORD_SRV)
+    {
+      /*
+       * Prio, weight and port
+       */
+      new_srv = (struct srv_data*)new_srv_data;
+      old_srv = (struct srv_data*)rd[i].data;
+      new_srv->prio = old_srv->prio;
+      new_srv->weight = old_srv->weight;
+      new_srv->port = old_srv->port;
+      expand_plus((char*)&new_srv[1], (char*)&old_srv[1],
+                  repl_string);
+      p_rd[i].data = new_srv_data;
+      p_rd[i].data_size = sizeof (struct srv_data) + strlen ((char*)&new_srv[1]) + 1;
+    }
+    else if (rd[i].record_type == GNUNET_GNS_RECORD_SOA)
     {
       /* expand mname and rname */
-      pos = new_soa_data;
-      expand_plus(&pos, (char*)rd[i].data, repl_string);
-      offset = strlen(new_soa_data)+1;
-      pos = new_soa_data+offset;
-      expand_plus(&pos, (char*)rd[i].data+offset, repl_string);
-      offset += strlen(new_soa_data+offset)+1;
-      /* cpy the 4 numbers serial refresh retry and expire */
-      memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5);
-      offset += sizeof(uint32_t)*5;
-      p_rd[i].data_size = offset;
+      old_soa = (struct soa_data*)rd[i].data;
+      new_soa = (struct soa_data*)new_soa_data;
+      memcpy (new_soa, old_soa, sizeof (struct soa_data));
+      expand_plus((char*)&new_soa[1], (char*)&old_soa[1], repl_string);
+      offset = strlen ((char*)&new_soa[1]) + 1;
+      expand_plus((char*)&new_soa[1] + offset,
+                  (char*)&old_soa[1] + strlen ((char*)&old_soa[1]) + 1,
+                  repl_string);
+      p_rd[i].data_size = sizeof (struct soa_data)
+                          + offset
+                          + strlen ((char*)&new_soa[1] + offset);
       p_rd[i].data = new_soa_data;
     }
     else
     {
       pos = new_rr_data;
-      expand_plus(&pos, (char*)rd[i].data, repl_string);
+      expand_plus(pos, (char*)rd[i].data, repl_string);
       p_rd[i].data_size = strlen(new_rr_data)+1;
       p_rd[i].data = new_rr_data;
     }
@@ -2443,7 +2702,7 @@ finish_lookup(struct ResolverHandle *rh,
 
   rlh->proc(rlh->proc_cls, rd_count, p_rd);
   GNUNET_free(rlh);
-  
+  free_resolver_handle (rh);
 }
 
 /**
@@ -2465,20 +2724,18 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
   if (rd_count == 0)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n",
+               "GNS_PHASE_REC-%llu: No records for %s found in DHT. Aborting\n",
                rh->id, rh->name);
     /* give up, cannot resolve */
     finish_lookup(rh, rlh, 0, NULL);
-    free_resolver_handle(rh);
     return;
   }
 
   /* results found yay */
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id);
+             "GNS_PHASE_REC-%llu: Record resolved from DHT!", rh->id);
 
   finish_lookup(rh, rlh, rd_count, rd);
-  free_resolver_handle(rh);
 
 }
 
@@ -2500,10 +2757,12 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
 {
   struct RecordLookupHandle* rlh;
   rlh = (struct RecordLookupHandle*) cls;
+  int check_dht = GNUNET_YES;
+
   if (rd_count == 0)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n",
+               "GNS_PHASE_REC-%llu: NS returned no records. (status: %d)!\n",
                rh->id,
                rh->status);
     
@@ -2518,12 +2777,22 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
      *    would already have an entry in the NS for the record)
      * 5. We are not in cache only mode
      */
-    if (( ((rh->status & RSL_RECORD_EXPIRED) != 0) ||
-         ((rh->status & RSL_RECORD_EXISTS) == 0) ) &&
-        GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
-                                        &rh->private_local_zone) &&
-        (strcmp(rh->name, "+") == 0) &&
-        (rh->only_cached == GNUNET_NO))
+    if (((rh->status & RSL_RECORD_EXPIRED) != 0) &&
+        ((rh->status & RSL_RECORD_EXISTS) == 0) )
+      check_dht = GNUNET_NO;
+    
+    if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                          &rh->private_local_zone))
+      check_dht = GNUNET_NO;
+    
+    if ((strcmp (rh->name, "+") != 0) && (is_srv (rh->name) != 0))
+        check_dht = GNUNET_NO;
+
+
+    if (rh->only_cached == GNUNET_YES)
+      check_dht = GNUNET_NO;
+    
+    if (GNUNET_YES == check_dht)
     {
       rh->proc = &handle_record_dht;
       resolve_record_dht(rh);
@@ -2531,17 +2800,15 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
     }
     /* give up, cannot resolve */
     finish_lookup(rh, rlh, 0, NULL);
-    free_resolver_handle(rh);
     return;
   }
 
   /* results found yay */
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id);
+             "GNS_PHASE_REC-%llu: Record resolved from namestore!\n", rh->id);
 
   finish_lookup(rh, rlh, rd_count, rd);
 
-  free_resolver_handle(rh);
 
 }
 
@@ -2558,7 +2825,7 @@ pop_tld(char* name, char* dest)
 {
   uint32_t len;
 
-  if (is_canonical(name))
+  if (is_canonical (name))
   {
     strcpy(dest, name);
     strcpy(name, "");
@@ -2632,7 +2899,6 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh,
                  "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
                  rh->id);
       finish_lookup(rh, rlh, rd_count, rd);
-      free_resolver_handle(rh);
       return;
     }
     /* We resolved full name for delegation. resolving record */
@@ -2663,7 +2929,6 @@ handle_delegation_dht(void* cls, struct ResolverHandle *rh,
  "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
  rh->id, rh->name);
   finish_lookup(rh, rlh, 0, NULL);
-  free_resolver_handle(rh);
 }
 
 
@@ -2708,7 +2973,8 @@ resolve_delegation_dht(struct ResolverHandle *rh)
     {
       /* terminate oldest lookup */
       rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
-      GNUNET_DHT_get_stop(rh_heap_root->get_handle);
+      GNUNET_DHT_get_stop (rh_heap_root->get_handle);
+      rh_heap_root->get_handle = NULL;
       rh_heap_root->dht_heap_node = NULL;
       
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -2756,6 +3022,8 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
 {
   struct RecordLookupHandle* rlh;
   rlh = (struct RecordLookupHandle*) cls;
+  int check_dht = GNUNET_YES;
+  int s_len = 0;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
@@ -2764,7 +3032,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
   if (rh->status & RSL_PKEY_REVOKED)
   {
     finish_lookup (rh, rlh, 0, NULL);
-    free_resolver_handle (rh);
     return;
   }
   
@@ -2777,21 +3044,49 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
               rh->id);
     if (rh->status & RSL_CNAME_FOUND)
     {
-      if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
+      if (rlh->record_type == GNUNET_GNS_RECORD_CNAME)
       {
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                   "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n",
                   rh->id);
-        finish_lookup(rh, rlh, rd_count, rd);
-        free_resolver_handle(rh);
+        strcpy (rh->name, rh->authority_name);
+        finish_lookup (rh, rlh, rd_count, rd);
         return;
       }
       
-      /* A CNAME can only occur alone */
-      GNUNET_assert (is_canonical ((char*)rd->data));
-      strcpy (rh->name, rd->data);
-      resolve_delegation_ns (rh);
-      return;
+      /* A .+ CNAME  */
+      if (is_tld ((char*)rd->data, GNUNET_GNS_TLD_PLUS))
+      {
+        s_len = strlen (rd->data) - 2;
+        memcpy (rh->name, rd->data, s_len);
+        rh->name[s_len] = '\0';
+        resolve_delegation_ns (rh);
+        return;
+      }
+      else if (is_tld ((char*)rd->data, GNUNET_GNS_TLD_ZKEY))
+      {
+        gns_resolver_lookup_record (rh->authority,
+                                    rh->private_local_zone,
+                                    rlh->record_type,
+                                    (char*)rd->data,
+                                    rh->priv_key,
+                                    rh->timeout,
+                                    rh->only_cached,
+                                    rlh->proc,
+                                    rlh->proc_cls);
+        GNUNET_free (rlh);
+        GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
+        free_resolver_handle (rh);
+        return;
+      }
+      else
+      {
+        //Try DNS resolver
+        strcpy (rh->dns_name, (char*)rd->data);
+        resolve_dns_name (rh);
+        return;
+      }
+
     }
     else if (rh->status & RSL_DELEGATE_VPN)
     {
@@ -2801,7 +3096,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
                  "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n",
                  rh->id);
         finish_lookup(rh, rlh, rd_count, rd);
-        free_resolver_handle(rh);
         return;
       }
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -2814,13 +3108,12 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
     }
     else if (rh->status & RSL_DELEGATE_NS)
     {
-      if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
+      if (rlh->record_type == GNUNET_GNS_RECORD_NS)
       {
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                    "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
                    rh->id);
         finish_lookup(rh, rlh, rd_count, rd);
-        free_resolver_handle(rh);
         return;
       }
       
@@ -2840,7 +3133,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
                    "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n",
                    rh->id);
         finish_lookup (rh, rlh, 0, NULL);
-        free_resolver_handle (rh);
         return;
       }
       else if (rlh->record_type == GNUNET_GNS_RECORD_PKEY)
@@ -2850,7 +3142,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
                    "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
                    rh->id);
         finish_lookup(rh, rlh, rd_count, rd);
-        free_resolver_handle(rh);
         return;
       }
     }
@@ -2865,13 +3156,12 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
   
   if (rh->status & RSL_DELEGATE_NS)
   {
-    if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
+    if (rlh->record_type == GNUNET_GNS_RECORD_NS)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                  "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
                  rh->id);
       finish_lookup(rh, rlh, rd_count, rd);
-      free_resolver_handle(rh);
       return;
     }
     
@@ -2890,9 +3180,19 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
    * and exists
    * or we are authority
    **/
-  if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED)))
-      || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
-                                       &rh->private_local_zone))
+
+  if ((rh->status & RSL_RECORD_EXISTS) &&
+       !(rh->status & RSL_RECORD_EXPIRED))
+    check_dht = GNUNET_NO;
+
+  if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                        &rh->private_local_zone))
+    check_dht = GNUNET_NO;
+
+  if (rh->only_cached == GNUNET_YES)
+    check_dht = GNUNET_NO;
+
+  if (check_dht == GNUNET_NO)
   {
     if (is_canonical(rh->name))
     {
@@ -2916,15 +3216,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh,
     return;
   }
 
-  if (rh->only_cached == GNUNET_YES)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_DELEGATE_NS-%llu: Only cache resolution, no result\n",
-               rh->id, rh->name);
-    finish_lookup(rh, rlh, rd_count, rd);
-    return;
-  }
-  
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
       rh->id, rh->name);
@@ -2963,30 +3254,31 @@ process_delegation_result_ns (void* cls,
   unsigned int i;
   struct GNUNET_TIME_Absolute et;
  
-  rh = (struct ResolverHandle *)cls; 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
-             rh->id, rd_count);
+  rh = (struct ResolverHandle *)cls;
+  rh->namestore_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+          "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
+          rh->id, rd_count);
 
-  GNUNET_CRYPTO_short_hash(key,
-                     sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &zone);
+  GNUNET_CRYPTO_short_hash (key,
+                      sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &zone);
   remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
   
   rh->status = 0;
   
   if (name != NULL)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
-               rh->id, name);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
+                rh->id, name);
     rh->status |= RSL_RECORD_EXISTS;
   
     if (remaining_time.rel_value == 0)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
-                 rh->id, name);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
+                  rh->id, name);
       rh->status |= RSL_RECORD_EXPIRED;
     }
   }
@@ -3005,31 +3297,29 @@ process_delegation_result_ns (void* cls,
      * Promote this authority back to a name maybe it is
      * our record.
      */
-    if (strcmp(rh->name, "") == 0)
+    if (strcmp (rh->name, "") == 0)
     {
       /* simply promote back */
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
-                 rh->id, rh->authority_name);
-      strcpy(rh->name, rh->authority_name);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
+                  rh->id, rh->authority_name);
+      strcpy (rh->name, rh->authority_name);
     }
     else
     {
       /* add back to existing name */
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
-                 rh->id, rh->authority_name, rh->name);
-      //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
-      GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
-                      rh->name, rh->authority_name);
-      //strcpy(new_name, rh->name);
-      //strcpy(new_name+strlen(new_name), ".");
-      //strcpy(new_name+strlen(new_name), rh->authority_name);
-      strcpy(rh->name, new_name);
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
+                  rh->id, rh->authority_name, rh->name);
+      GNUNET_snprintf (new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
+                       rh->name, rh->authority_name);
+      strcpy (rh->name, new_name);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n",
+                  rh->id, rh->name);
     }
-    rh->proc(rh->proc_cls, rh, 0, NULL);
+
+    rh->proc (rh->proc_cls, rh, 0, NULL);
     return;
   }
 
@@ -3038,21 +3328,18 @@ process_delegation_result_ns (void* cls,
    * move on with query
    * Note only 1 pkey should have been returned.. anything else would be strange
    */
-  for (i=0; i<rd_count;i++)
+  for (i=0; i < rd_count;i++)
   {
     
     /**
      * A CNAME. Like regular DNS this means the is no other record for this
      * name.
      */
-    if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
+    if (rd[i].record_type == GNUNET_GNS_RECORD_CNAME)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                  "GNS_PHASE_DELEGATE_NS-%llu: CNAME found.\n",
                  rh->id);
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: new name to resolve: %s.\n",
-                 rh->id, rh->name);
 
       rh->status |= RSL_CNAME_FOUND;
       rh->proc (rh->proc_cls, rh, rd_count, rd);
@@ -3076,7 +3363,7 @@ process_delegation_result_ns (void* cls,
      * Redirect via NS
      * FIXME make optional
      */
-    if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS)
+    if (rd[i].record_type == GNUNET_GNS_RECORD_NS)
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                  "GNS_PHASE_DELEGATE_NS-%llu: NS found.\n",
@@ -3091,11 +3378,11 @@ process_delegation_result_ns (void* cls,
 
     rh->status |= RSL_DELEGATE_PKEY;
 
-    if (ignore_pending_records &&
+    if ((ignore_pending_records != 0) &&
         (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+     "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
         rh->id,
         name);
       continue;
@@ -3106,16 +3393,16 @@ process_delegation_result_ns (void* cls,
     if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value
          == 0)
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
-                 rh->id);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
+                  rh->id);
       if (remaining_time.rel_value == 0)
       {
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
-                   rh->id);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
+                    rh->id);
         rh->authority_chain_head->fresh = 0;
-        rh->proc(rh->proc_cls, rh, 0, NULL);
+        rh->proc (rh->proc_cls, rh, 0, NULL);
         return;
       }
 
@@ -3125,19 +3412,19 @@ process_delegation_result_ns (void* cls,
     /**
      * Resolve rest of query with new authority
      */
-    GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
-    memcpy(&rh->authority, rd[i].data,
-           sizeof(struct GNUNET_CRYPTO_ShortHashCode));
-    struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
+    GNUNET_assert (rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
+    memcpy (&rh->authority, rd[i].data,
+            sizeof (struct GNUNET_CRYPTO_ShortHashCode));
+    struct AuthorityChain *auth = GNUNET_malloc(sizeof (struct AuthorityChain));
     auth->zone = rh->authority;
-    memset(auth->name, 0, strlen(rh->authority_name)+1);
-    strcpy(auth->name, rh->authority_name);
+    memset (auth->name, 0, strlen (rh->authority_name)+1);
+    strcpy (auth->name, rh->authority_name);
     GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
                                  rh->authority_chain_tail,
                                  auth);
     
     /* Check for key revocation and delegate */
-    GNUNET_NAMESTORE_lookup_record (namestore_handle,
+    rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
                                     &rh->authority,
                                     "+",
                                     GNUNET_GNS_RECORD_REV,
@@ -3193,7 +3480,7 @@ resolve_delegation_ns (struct ResolverHandle *rh)
              "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
              rh->id, rh->name);
   pop_tld(rh->name, rh->authority_name);
-  GNUNET_NAMESTORE_lookup_record(namestore_handle,
+  rh->namestore_task = GNUNET_NAMESTORE_lookup_record(namestore_handle,
                                  &rh->authority,
                                  rh->authority_name,
                                  GNUNET_GNS_RECORD_ANY,
@@ -3218,15 +3505,15 @@ resolve_delegation_ns (struct ResolverHandle *rh)
  * @param cls the closure to pass to proc
  */
 void
-gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
-                           struct GNUNET_CRYPTO_ShortHashCode pzone,
-                           uint32_t record_type,
-                           const char* name,
-                           struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                           struct GNUNET_TIME_Relative timeout,
-                           int only_cached,
-                           RecordLookupProcessor proc,
-                           void* cls)
+gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone,
+                            struct GNUNET_CRYPTO_ShortHashCode pzone,
+                            uint32_t record_type,
+                            const char* name,
+                            struct GNUNET_CRYPTO_RsaPrivateKey *key,
+                            struct GNUNET_TIME_Relative timeout,
+                            int only_cached,
+                            RecordLookupProcessor proc,
+                            void* cls)
 {
   struct ResolverHandle *rh;
   struct RecordLookupHandle* rlh;
@@ -3247,9 +3534,10 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
     return;
   }
   
-  rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
-  rh = GNUNET_malloc(sizeof (struct ResolverHandle));
-
+  rlh = GNUNET_malloc (sizeof(struct RecordLookupHandle));
+  rh = GNUNET_malloc (sizeof (struct ResolverHandle));
+  
+  memset (rh, 0, sizeof (struct ResolverHandle));
   rh->authority = zone;
   rh->id = rid++;
   rh->proc_cls = rlh;
@@ -3258,6 +3546,9 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
   rh->get_handle = NULL;
   rh->private_local_zone = pzone;
   rh->only_cached = only_cached;
+  rh->namestore_task = NULL;
+
+  GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh);
   
   if (NULL == key)
   {
@@ -3320,9 +3611,11 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "Cannot convert ZKEY %s to hash!\n", string_hash);
-        GNUNET_free(rh);
-        GNUNET_free(rlh);
-        proc(cls, 0, NULL);
+        
+        GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
+        GNUNET_free (rh);
+        GNUNET_free (rlh);
+        proc (cls, 0, NULL);
         return;
       }
 
@@ -3334,10 +3627,10 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
       /**
        * Presumably GNUNET tld
        */
-      memset(rh->name, 0,
-             strlen(name)-strlen(GNUNET_GNS_TLD));
-      memcpy(rh->name, name,
-             strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+      memset (rh->name, 0,
+              strlen(name)-strlen(GNUNET_GNS_TLD));
+      memcpy (rh->name, name,
+              strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
     }
   }
   
@@ -3365,6 +3658,19 @@ gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
 
 /******** END Record Resolver ***********/
 
+static void
+finish_shorten (struct ResolverHandle *rh,
+                struct NameShortenHandle *nsh)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending %s as shorten result\n", nsh->result);
+  nsh->proc (nsh->proc_cls, nsh->result);
+  GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
+  GNUNET_free (nsh);
+  free_resolver_handle (rh);
+}
+
+
 /**
  * Callback calles by namestore for a zone to name
  * result
@@ -3416,25 +3722,24 @@ process_zone_to_name_shorten_shorten (void *cls,
   char tmp_name[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
   
+  rh->namestore_task = NULL;
   /* we found a match in our own root zone */
   if (rd_len != 0)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "result strlen %d\n", strlen(name));
     answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
     memset(result, 0, answer_len);
 
     if (strlen(rh->name) > 0)
     {
-      sprintf (result, "%s.%s.%s.%s.%s",
+      sprintf (result, "%s.%s.%s.%s",
                rh->name, name,
-               nsh->shorten_zone_name, nsh->private_zone_name,
+               nsh->shorten_zone_name,
                GNUNET_GNS_TLD);
     }
     else
     {
-      sprintf (result, "%s.%s.%s.%s", name,
-               nsh->shorten_zone_name, nsh->private_zone_name,
+      sprintf (result, "%s.%s.%s", name,
+               nsh->shorten_zone_name,
                GNUNET_GNS_TLD);
     }
     
@@ -3452,9 +3757,9 @@ process_zone_to_name_shorten_shorten (void *cls,
      * shorten to our zone to a "" record??)
      */
     
-    sprintf (result, "%s.%s.%s.%s",
+    sprintf (result, "%s.%s.%s",
              rh->name,
-             nsh->shorten_zone_name, nsh->private_zone_name,
+             nsh->shorten_zone_name,
              GNUNET_GNS_TLD);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Our zone: Found %s as shorten result\n", result);
@@ -3474,11 +3779,7 @@ process_zone_to_name_shorten_shorten (void *cls,
    */
   if ((rh->authority_chain_head->next == NULL))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Sending %s as shorten result\n", nsh->result);
-    nsh->proc(nsh->proc_cls, nsh->result);
-    GNUNET_free (nsh);
-    free_resolver_handle (rh);
+    finish_shorten (rh, nsh);
     return;
   }
   next_authority = rh->authority_chain_head;
@@ -3495,7 +3796,9 @@ process_zone_to_name_shorten_shorten (void *cls,
                             rh->authority_chain_tail,
                             next_authority);
 
-  GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+  GNUNET_free (next_authority);
+
+  rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                  &rh->authority_chain_tail->zone,
                                  &rh->authority_chain_head->zone,
                                  &process_zone_to_name_shorten_root,
@@ -3531,11 +3834,10 @@ process_zone_to_name_shorten_private (void *cls,
   char tmp_name[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
   
+  rh->namestore_task = NULL;
   /* we found a match in our own root zone */
   if (rd_len != 0)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "result strlen %d\n", strlen(name));
     answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
     memset(result, 0, answer_len);
 
@@ -3570,10 +3872,10 @@ process_zone_to_name_shorten_private (void *cls,
       strcpy (nsh->result, result);
   }
   
-  if (nsh->shorten_zone != NULL)
+  if (0 != strcmp (nsh->shorten_zone_name, ""))
   {
     /* backtrack authorities for names in priv zone */
-    GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                    nsh->shorten_zone,
                                    &rh->authority_chain_head->zone,
                                    &process_zone_to_name_shorten_shorten,
@@ -3587,11 +3889,7 @@ process_zone_to_name_shorten_private (void *cls,
      */
     if ((rh->authority_chain_head->next == NULL))
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending %s as shorten result\n", nsh->result);
-      nsh->proc(nsh->proc_cls, nsh->result);
-      GNUNET_free(nsh);
-      free_resolver_handle(rh);
+      finish_shorten (rh, nsh);
       return;
     }
     next_authority = rh->authority_chain_head;
@@ -3608,7 +3906,9 @@ process_zone_to_name_shorten_private (void *cls,
                               rh->authority_chain_tail,
                               next_authority);
 
-    GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+    GNUNET_free (next_authority);
+
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                    &rh->authority_chain_tail->zone,
                                    &rh->authority_chain_head->zone,
                                    &process_zone_to_name_shorten_root,
@@ -3645,11 +3945,10 @@ process_zone_to_name_shorten_root (void *cls,
   char tmp_name[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
   
+  rh->namestore_task = NULL;
   /* we found a match in our own root zone */
   if (rd_len != 0)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "result strlen %d\n", strlen(name));
     answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
     memset(result, 0, answer_len);
 
@@ -3683,15 +3982,24 @@ process_zone_to_name_shorten_root (void *cls,
       strcpy (nsh->result, result);
   }
   
-  if (nsh->private_zone != NULL)
+  if (NULL != nsh->private_zone)
   {
     /* backtrack authorities for names in priv zone */
-    GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                    nsh->private_zone,
                                    &rh->authority_chain_head->zone,
                                    &process_zone_to_name_shorten_private,
                                    rh);
   }
+  else if (NULL != nsh->shorten_zone)
+  {
+    /* backtrack authorities for names in shorten zone */
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+                                          nsh->shorten_zone,
+                                          &rh->authority_chain_head->zone,
+                                          &process_zone_to_name_shorten_shorten,
+                                          rh);
+  }
   else
   {
     /**
@@ -3700,11 +4008,7 @@ process_zone_to_name_shorten_root (void *cls,
      */
     if ((rh->authority_chain_head->next == NULL))
     {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "Sending %s as shorten result\n", nsh->result);
-      nsh->proc(nsh->proc_cls, nsh->result);
-      GNUNET_free(nsh);
-      free_resolver_handle(rh);
+      finish_shorten (rh, nsh);
       return;
     }
     next_authority = rh->authority_chain_head;
@@ -3721,7 +4025,9 @@ process_zone_to_name_shorten_root (void *cls,
                               rh->authority_chain_tail,
                               next_authority);
 
-    GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+    GNUNET_free (next_authority);
+
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                    &rh->authority_chain_tail->zone,
                                    &rh->authority_chain_head->zone,
                                    &process_zone_to_name_shorten_root,
@@ -3778,44 +4084,51 @@ handle_delegation_ns_shorten (void* cls,
       strcpy (nsh->result, result);
 
   }
-  else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
-                                        nsh->private_zone) == 0)
+  else if (NULL != nsh->private_zone)
   {
     /**
      * This is our zone append .gnunet unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
+    if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                     nsh->private_zone) == 0)
+    {
     
-    sprintf (result, "%s.%s.%s",
-             rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Our zone: Found %s as shorten result %s\n", result);
+      sprintf (result, "%s.%s.%s",
+               rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Our zone: Found %s as shorten result in private zone %s\n",
+                 result);
     
-    if (strlen (nsh->result) > strlen (result))
-      strcpy (nsh->result, result);
+      if (strlen (nsh->result) > strlen (result))
+        strcpy (nsh->result, result);
+    }
   }
-  else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
-                                        nsh->shorten_zone) == 0)
+  else if (NULL != nsh->shorten_zone)
   {
     /**
      * This is our zone append .gnunet unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
+    if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                     nsh->shorten_zone) == 0)
+    {
+      sprintf (result, "%s.%s.%s",
+               rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Our zone: Found %s as shorten result in shorten zone\n",
+                 result);
     
-    sprintf (result, "%s.%s.%s",
-             rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Our zone: Found %s as shorten result\n", result);
-    
-    if (strlen (nsh->result) > strlen (result))
-      strcpy (nsh->result, result);
+      if (strlen (nsh->result) > strlen (result))
+        strcpy (nsh->result, result);
+    }
   }
   
   
   /* backtrack authorities for names */
-  GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+  rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                  nsh->root_zone,
                                  &rh->authority_chain_head->zone,
                                  &process_zone_to_name_shorten_root,
@@ -3873,9 +4186,7 @@ process_zone_to_name_zkey(void *cls,
 
     strcpy (nsh->result, new_name);
 
-    nsh->proc(nsh->proc_cls, new_name);
-    GNUNET_free(nsh);
-    free_resolver_handle(rh);
+    finish_shorten (rh, nsh);
     return;
   }
   
@@ -3896,7 +4207,7 @@ process_zone_to_name_zkey(void *cls,
   
   
   /* Start delegation resolution in our namestore */
-  resolve_delegation_ns(rh);
+  resolve_delegation_ns (rh);
 }
 
 
@@ -3952,14 +4263,18 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
   strcpy (nsh->shorten_zone_name, shorten_zone_name);
   strcpy (nsh->result, name);
   
+
   rh = GNUNET_malloc (sizeof (struct ResolverHandle));
   rh->authority = *zone;
   rh->id = rid++;
   rh->priv_key = NULL;
+  rh->namestore_task = NULL;
   rh->proc = &handle_delegation_ns_shorten;
   rh->proc_cls = nsh;
   rh->id = rid++;
   rh->private_local_zone = *zone;
+
+  GNUNET_CONTAINER_DLL_insert (nsh_head, nsh_tail, rh);
   
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Checking for TLD...\n");
@@ -3990,11 +4305,12 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
                   "Cannot convert ZKEY %s to hash!\n", nzkey);
       GNUNET_free (rh);
       GNUNET_free (nsh);
+      GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
       proc (proc_cls, name);
       return;
     }
 
-    GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+    rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
                                    zone, //ours
                                    &zkey,
                                    &process_zone_to_name_zkey,
@@ -4026,6 +4342,18 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
 
 /*********** END NAME SHORTEN ********************/
 
+static void
+finish_get_auth (struct ResolverHandle *rh,
+                 struct GetNameAuthorityHandle *nah)
+{
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "Got authority result %s\n", nah->result);
+  
+  nah->proc(nah->proc_cls, nah->result);
+  GNUNET_CONTAINER_DLL_remove (nah_head, nah_tail, rh);
+  GNUNET_free(nah);
+  free_resolver_handle(rh);
+}
 
 /**
  * Process result from namestore delegation lookup
@@ -4043,7 +4371,6 @@ handle_delegation_result_ns_get_auth(void* cls,
                       const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   struct GetNameAuthorityHandle* nah;
-  char result[MAX_DNS_NAME_LENGTH];
   size_t answer_len;
 
   nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
@@ -4077,23 +4404,17 @@ handle_delegation_result_ns_get_auth(void* cls,
 
     answer_len = strlen(nah->name) - strlen(rh->name)
       + strlen(GNUNET_GNS_TLD) + 1;
-    memset(result, 0, answer_len);
-    strcpy(result, nah->name + strlen(rh->name) + 1);
+    memset(nah->result, 0, answer_len);
+    strcpy(nah->result, nah->name + strlen(rh->name) + 1);
 
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got authority result %s\n", result);
-    
-    nah->proc(nah->proc_cls, result);
-    GNUNET_free(nah);
-    free_resolver_handle(rh);
+    finish_get_auth (rh, nah);
   }
   else
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "Unable to resolve authority for remaining %s!\n", rh->name);
-    nah->proc(nah->proc_cls, "");
-    GNUNET_free(nah);
-    free_resolver_handle(rh);
+    strcpy(nah->result, "");
+    finish_get_auth (rh, nah);
   }
 
 
@@ -4128,6 +4449,9 @@ gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
   rh->authority = zone;
   rh->id = rid++;
   rh->private_local_zone = pzone;
+  rh->namestore_task = NULL;
+
+  GNUNET_CONTAINER_DLL_insert (nah_head, nah_tail, rh);
   
   if (strcmp(GNUNET_GNS_TLD, name) == 0)
   {
@@ -4153,6 +4477,7 @@ gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
 
   nah->proc = proc;
   nah->proc_cls = proc_cls;
+  strcpy (nah->result, "");
 
   /* Start delegation resolution in our namestore */
   resolve_delegation_ns(rh);