-ensure external symbols have proper prefix for conversation service
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
index 6ef9467475d9e0041a9ad9b52d1675f5a2a64937..110263eeefb9b3be47972da345fba6d8efeb0484 100644 (file)
@@ -263,7 +263,7 @@ struct GNS_ResolverHandle
   struct GNUNET_RESOLVER_RequestHandle *std_resolve;
 
   /**
-   * Pending Namestore task
+   * Pending Namestore lookup task
    */
   struct GNUNET_NAMESTORE_QueueEntry *namestore_qe;
 
@@ -333,6 +333,30 @@ struct GNS_ResolverHandle
 };
 
 
+/**
+ * Active namestore caching operations.
+ */
+struct CacheOps
+{
+
+  /**
+   * Organized in a DLL.
+   */
+  struct CacheOps *next;
+
+  /**
+   * Organized in a DLL.
+   */
+  struct CacheOps *prev;
+
+  /**
+   * Pending Namestore caching task.
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *namestore_qe_cache;
+
+};
+
+
 /**
  * Our handle to the namestore service
  */
@@ -373,6 +397,17 @@ static struct GNS_ResolverHandle *rlh_head;
  */
 static struct GNS_ResolverHandle *rlh_tail;
 
+/**
+ * Organized in a DLL.
+ */
+static struct CacheOps *co_head;
+
+/**
+ * Organized in a DLL.
+ */
+static struct CacheOps *co_tail;
+
+
 /**
  * Global configuration.
  */
@@ -752,6 +787,7 @@ dns_result_parser (void *cls,
     unsigned int skip;
     char buf[UINT16_MAX];
     size_t buf_off;
+    size_t buf_start;
 
     buf_off = 0;
     skip = 0;
@@ -804,6 +840,7 @@ dns_result_parser (void *cls,
       case GNUNET_DNSPARSER_TYPE_CNAME:
       case GNUNET_DNSPARSER_TYPE_PTR:
       case GNUNET_DNSPARSER_TYPE_NS:
+       buf_start = buf_off;
        if (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_name (buf,
                                               sizeof (buf),
@@ -814,8 +851,11 @@ dns_result_parser (void *cls,
          skip++;
          continue;
        }
+       rd[i - skip].data_size = buf_off - buf_start;
+       rd[i - skip].data = &buf[buf_start];    
        break;
       case GNUNET_DNSPARSER_TYPE_SOA:
+       buf_start = buf_off;
        if (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_soa (buf,
                                               sizeof (buf),
@@ -826,8 +866,11 @@ dns_result_parser (void *cls,
          skip++;
          continue;
        }
+       rd[i - skip].data_size = buf_off - buf_start;
+       rd[i - skip].data = &buf[buf_start];    
        break;
       case GNUNET_DNSPARSER_TYPE_MX:
+       buf_start = buf_off;
        if (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_mx (buf,
                                             sizeof (buf),
@@ -838,8 +881,11 @@ dns_result_parser (void *cls,
          skip++;
          continue;
        }
+       rd[i - skip].data_size = buf_off - buf_start;
+       rd[i - skip].data = &buf[buf_start];    
        break;
       case GNUNET_DNSPARSER_TYPE_SRV:
+       buf_start = buf_off;
        if (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_srv (buf,
                                              sizeof (buf),
@@ -850,6 +896,8 @@ dns_result_parser (void *cls,
          skip++;
          continue;
        }
+       rd[i - skip].data_size = buf_off - buf_start;
+       rd[i - skip].data = &buf[buf_start];    
        break;
       default:
        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -907,7 +955,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
   query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
   query->name = GNUNET_strdup (ac->label);
   query->type = rh->record_type;
-  query->class = GNUNET_TUN_DNS_CLASS_INTERNET;
+  query->dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
   p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
   p->queries = query;
   p->num_queries = 1;
@@ -1152,48 +1200,58 @@ handle_gns_resolution_result (void *cls,
     {
       for (i=0;i<rd_count;i++)
       {
-       if (GNUNET_NAMESTORE_TYPE_VPN == rd[i].record_type)
+       switch (rd[i].record_type)
        {
-         af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
-         if (sizeof (struct GNUNET_TUN_GnsVpnRecord) <
-             rd[i].data_size)
+       case GNUNET_NAMESTORE_TYPE_VPN:
          {
-           GNUNET_break_op (0);
-           rh->proc (rh->proc_cls, 0, NULL);
-           GNS_resolver_lookup_cancel (rh);
-           return;         
+           af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
+           if (sizeof (struct GNUNET_TUN_GnsVpnRecord) <
+               rd[i].data_size)
+           {
+             GNUNET_break_op (0);
+             rh->proc (rh->proc_cls, 0, NULL);
+             GNS_resolver_lookup_cancel (rh);
+             return;         
+           }
+           vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
+           vname = (const char *) &vpn[1];
+           if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
+           {
+             GNUNET_break_op (0);
+             rh->proc (rh->proc_cls, 0, NULL);
+             GNS_resolver_lookup_cancel (rh);
+             return;
+           }
+           GNUNET_CRYPTO_hash (vname,
+                               strlen (vname), // FIXME: +1?
+                               &vhash);
+           vpn_ctx = GNUNET_new (struct VpnContext);
+           rh->vpn_ctx = vpn_ctx;
+           vpn_ctx->rh = rh;
+           vpn_ctx->rd_data_size = GNUNET_NAMESTORE_records_get_size (rd_count,
+                                                                      rd);
+           vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size);
+           (void) GNUNET_NAMESTORE_records_serialize (rd_count,
+                                                      rd,
+                                                      vpn_ctx->rd_data_size,
+                                                      vpn_ctx->rd_data);
+           vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
+                                                               af,
+                                                               ntohs (vpn->proto),
+                                                               &vpn->peer,
+                                                               &vhash,
+                                                               GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT),
+                                                               &vpn_allocation_cb,
+                                                               rh);
+           return;
          }
-         vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
-         vname = (const char *) &vpn[1];
-         if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
+       case GNUNET_NAMESTORE_TYPE_GNS2DNS:
          {
-           GNUNET_break_op (0);
-           rh->proc (rh->proc_cls, 0, NULL);
-           GNS_resolver_lookup_cancel (rh);
-           return;
+           /* delegation to DNS */
+           goto do_recurse;
          }
-         GNUNET_CRYPTO_hash (vname,
-                             strlen (vname), // FIXME: +1?
-                             &vhash);
-         vpn_ctx = GNUNET_new (struct VpnContext);
-         rh->vpn_ctx = vpn_ctx;
-         vpn_ctx->rh = rh;
-         vpn_ctx->rd_data_size = GNUNET_NAMESTORE_records_get_size (rd_count,
-                                                                    rd);
-         vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size);
-         (void) GNUNET_NAMESTORE_records_serialize (rd_count,
-                                                    rd,
-                                                    vpn_ctx->rd_data_size,
-                                                    vpn_ctx->rd_data);
-         vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
-                                                             af,
-                                                             ntohs (vpn->proto),
-                                                             &vpn->peer,
-                                                             &vhash,
-                                                             GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT),
-                                                             &vpn_allocation_cb,
-                                                             rh);
-         return;
+       default:
+         break;
        }
       }
     }
@@ -1387,6 +1445,7 @@ handle_gns_resolution_result (void *cls,
     GNS_resolver_lookup_cancel (rh);
     return;         
   }
+ do_recurse:
   /* need to recurse, check if we can */
   for (i=0;i<rd_count;i++)
   {
@@ -1423,7 +1482,7 @@ handle_gns_resolution_result (void *cls,
       rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
                                              rh);
       return;
-    case GNUNET_DNSPARSER_TYPE_NS:
+    case GNUNET_NAMESTORE_TYPE_GNS2DNS:
       {
        char *ns;
        /* resolution continues within DNS */
@@ -1522,9 +1581,10 @@ handle_gns_resolution_result (void *cls,
           created from the remainder of the GNS name and the
           name in the NS record */
        GNUNET_asprintf (&ac->label,
-                        "%.*s.%s",
+                        "%.*s%s%s",
                         (int) rh->name_resolution_pos,
                         rh->name,
+                        (0 != rh->name_resolution_pos) ? "." : "",
                         ns);
        GNUNET_free (ns);
        GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
@@ -1582,7 +1642,7 @@ handle_gns_resolution_result (void *cls,
  * Function called once the namestore has completed the request for
  * caching a block.
  *
- * @param cls closure with the 'struct GNS_ResolverHandle'
+ * @param cls closure with the `struct CacheOps`
  * @param success #GNUNET_OK on success
  * @param emsg error message
  */
@@ -1591,13 +1651,17 @@ namestore_cache_continuation (void *cls,
                              int32_t success,
                              const char *emsg)
 {
-  struct GNS_ResolverHandle *rh = cls;
+  struct CacheOps *co = cls;
 
-  rh->namestore_qe = NULL;
+  co->namestore_qe_cache = NULL;
   if (NULL != emsg)
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Failed to cache GNS resolution: %s\n"),
                emsg);
+  GNUNET_CONTAINER_DLL_remove (co_head,
+                              co_tail,
+                              co);
+  GNUNET_free (co);
 }
 
 
@@ -1632,11 +1696,14 @@ handle_dht_response (void *cls,
   struct GNS_ResolverHandle *rh = cls;
   struct AuthorityChain *ac = rh->ac_tail;
   const struct GNUNET_NAMESTORE_Block *block;
+  struct CacheOps *co;
   
   GNUNET_DHT_get_stop (rh->get_handle);
   rh->get_handle = NULL;
   GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
   rh->dht_heap_node = NULL;  
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Handling response from the DHT\n");
   if (size < sizeof (struct GNUNET_NAMESTORE_Block))
   {
     /* how did this pass DHT block validation!? */
@@ -1670,10 +1737,16 @@ handle_dht_response (void *cls,
     return;
   }
   /* Cache well-formed blocks */
-  rh->namestore_qe = GNUNET_NAMESTORE_block_cache (namestore_handle,
-                                                  block,
-                                                  &namestore_cache_continuation,
-                                                  rh);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Caching response from the DHT in namestore\n");
+  co = GNUNET_new (struct CacheOps);
+  co->namestore_qe_cache = GNUNET_NAMESTORE_block_cache (namestore_handle,
+                                                        block,
+                                                        &namestore_cache_continuation,
+                                                        co);
+  GNUNET_CONTAINER_DLL_insert (co_head,
+                              co_tail,
+                              co);
 }
 
 
@@ -1697,6 +1770,7 @@ handle_namestore_block_response (void *cls,
   GNUNET_NAMESTORE_query_from_public_key (auth,
                                          label,
                                          &query);
+  GNUNET_assert (NULL != rh->namestore_qe);
   rh->namestore_qe = NULL;
   if ( (GNUNET_NO == rh->only_cached) &&
        ( (NULL == block) ||
@@ -1707,6 +1781,7 @@ handle_namestore_block_response (void *cls,
                "Starting DHT lookup for `%s' in zone %s\n",
                ac->label,
                GNUNET_NAMESTORE_z2s (&ac->authority_info.gns_authority));
+    GNUNET_assert (NULL == rh->get_handle);
     rh->get_handle = GNUNET_DHT_get_start (dht_handle,
                                           GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
                                           &query,
@@ -1739,6 +1814,8 @@ handle_namestore_block_response (void *cls,
     GNS_resolver_lookup_cancel (rh);
     return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Decrypting block from the namestore\n");
   if (GNUNET_OK !=
       GNUNET_NAMESTORE_block_decrypt (block,
                                      auth,
@@ -1776,6 +1853,7 @@ recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh)
                                                    &query,
                                                    &handle_namestore_block_response,
                                                    rh);
+  GNUNET_assert (NULL != rh->namestore_qe);
 }
 
 
@@ -1923,7 +2001,9 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicSignKey *zone,
   struct GNS_ResolverHandle *rh;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Starting lookup for `%s'\n",
+             (NULL == shorten_key)
+             ? "Starting lookup for `%s' with shortening disabled\n" 
+             : "Starting lookup for `%s' with shortening enabled\n",
              name);
   rh = GNUNET_new (struct GNS_ResolverHandle);
   GNUNET_CONTAINER_DLL_insert (rlh_head,
@@ -2067,6 +2147,7 @@ void
 GNS_resolver_done ()
 {
   struct GNS_ResolverHandle *rh;
+  struct CacheOps *co;
 
   /* abort active resolutions */
   while (NULL != (rh = rlh_head))
@@ -2074,6 +2155,14 @@ GNS_resolver_done ()
     rh->proc (rh->proc_cls, 0, NULL);
     GNS_resolver_lookup_cancel (rh);    
   }
+  while (NULL != (co = co_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (co_head,
+                                co_tail,
+                                co);
+    GNUNET_NAMESTORE_cancel (co->namestore_qe_cache);
+    GNUNET_free (co);
+  }
   GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
   dht_lookup_heap = NULL;
   GNUNET_DNSSTUB_stop (dns_handle);