gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r20259 - gnunet/src/gns


From: gnunet
Subject: [GNUnet-SVN] r20259 - gnunet/src/gns
Date: Mon, 5 Mar 2012 00:09:12 +0100

Author: schanzen
Date: 2012-03-05 00:09:12 +0100 (Mon, 05 Mar 2012)
New Revision: 20259

Modified:
   gnunet/src/gns/gnunet-service-gns.c
Log:
-rewritten resolver, hits some namestore bugs

Modified: gnunet/src/gns/gnunet-service-gns.c
===================================================================
--- gnunet/src/gns/gnunet-service-gns.c 2012-03-04 22:55:29 UTC (rev 20258)
+++ gnunet/src/gns/gnunet-service-gns.c 2012-03-04 23:09:12 UTC (rev 20259)
@@ -42,6 +42,7 @@
 #define DHT_OPERATION_TIMEOUT  GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 5)
 #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
 #define DHT_GNS_REPLICATION_LEVEL 5
+#define MAX_DNS_LABEL_LENGTH 63
 
 /* Ignore for now not used anyway and probably never will */
 #define GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP 23
@@ -142,13 +143,113 @@
 struct GNUNET_TIME_Relative dht_update_interval;
 GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
 
-/* Prototypes */
-static void reply_to_dns(struct GNUNET_GNS_ResolverHandle *answer,
-                         uint32_t rd_count,
-                         const struct GNUNET_NAMESTORE_RecordData *rd);
 static void resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
 
 /**
+ * Reply to client with the result from our lookup.
+ *
+ * @param rh the request handle of the lookup
+ * @param rd_count the number of records to return
+ * @param rd the record data
+ */
+static void
+reply_to_dns(struct GNUNET_GNS_ResolverHandle *rh, uint32_t rd_count,
+             const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  int i;
+  size_t len;
+  int ret;
+  char *buf;
+  struct GNUNET_DNSPARSER_Packet *packet = rh->packet;
+  struct GNUNET_DNSPARSER_Record answer_records[rh->answered];
+  struct GNUNET_DNSPARSER_Record additional_records[rd_count-(rh->answered)];
+  packet->answers = answer_records;
+  packet->additional_records = additional_records;
+  
+  /**
+   * Put records in the DNS packet and modify it
+   * to a response
+   */
+  len = sizeof(struct GNUNET_DNSPARSER_Record*);
+  for (i=0; i < rd_count; i++)
+  {
+    
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Adding type %d to DNS response\n", rd[i].record_type);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", rh->name);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "QName: %s\n", rh->query->name);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size);
+    
+    if (rd[i].record_type == rh->query->type)
+    {
+      answer_records[i].name = rh->query->name;
+      answer_records[i].type = rd[i].record_type;
+      answer_records[i].data.raw.data_len = rd[i].data_size;
+      answer_records[i].data.raw.data = (char*)rd[i].data;
+      answer_records[i].expiration_time = rd[i].expiration;
+      answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
+    }
+    else
+    {
+      additional_records[i].name = rh->query->name;
+      additional_records[i].type = rd[i].record_type;
+      additional_records[i].data.raw.data_len = rd[i].data_size;
+      additional_records[i].data.raw.data = (char*)rd[i].data;
+      additional_records[i].expiration_time = rd[i].expiration;
+      additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
+    }
+  }
+  
+  packet->num_answers = rh->answered;
+  packet->num_additional_records = rd_count-(rh->answered);
+  
+  if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash))
+    packet->flags.authoritative_answer = 1;
+  else
+    packet->flags.authoritative_answer = 0;
+
+  if (rd == NULL)
+    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
+  else
+    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
+  
+  packet->flags.query_or_response = 1;
+
+  
+  /**
+   * Reply to DNS
+   */
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "Building DNS response\n");
+  ret = GNUNET_DNSPARSER_pack (packet,
+                               1024, /* FIXME magic from dns redirector */
+                               &buf,
+                               &len);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "Built DNS response! (ret=%d,len=%d)\n", ret, len);
+  if (ret == GNUNET_OK)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Answering DNS request\n");
+    GNUNET_DNS_request_answer(rh->request_handle,
+                              len,
+                              buf);
+    //GNUNET_free(answer);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n");
+  }
+  else
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+               "Error building DNS response! (ret=%d)", ret);
+  }
+
+  GNUNET_free(rh->name);
+  GNUNET_free(rh);
+}
+
+
+/**
  * Task run during shutdown.
  *
  * @param cls unused
@@ -229,7 +330,7 @@
  * @param data the record data
  */
 static void
-process_authority_dht_result(void* cls,
+process_record_dht_result(void* cls,
                  struct GNUNET_TIME_Absolute exp,
                  const GNUNET_HashCode * key,
                  const struct GNUNET_PeerIdentity *get_path,
@@ -243,29 +344,31 @@
   struct GNSNameRecordBlock *nrb;
   uint32_t num_records;
   char* name = NULL;
-  char* rd_data = (char*) data;
+  char* rd_data = (char*)data;
   int i;
   int rd_size;
+  
   GNUNET_HashCode zone, name_hash;
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
   
   if (data == NULL)
     return;
+
+  //FIXME maybe check expiration here, check block type
   
-  //FIXME check expiration?
-  
   rh = (struct GNUNET_GNS_ResolverHandle *)cls;
   nrb = (struct GNSNameRecordBlock*)data;
   
-  /* stop dht lookup and timeout task */
+  /* stop lookup and timeout task */
   GNUNET_DHT_get_stop (rh->get_handle);
   GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
-
+  
   rh->get_handle = NULL;
+  name = (char*)&nrb[1];
   num_records = ntohl(nrb->rd_count);
-  name = (char*)&nrb[1];
   {
     struct GNUNET_NAMESTORE_RecordData rd[num_records];
-    
+
     rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
     rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
   
@@ -278,42 +381,36 @@
       return;
     }
 
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got name: %s (wanted %s)\n", name, rh->authority_name);
     for (i=0; i<num_records; i++)
     {
-    
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                "Got name: %s (wanted %s)\n", name, rh->authority_name);
+               "Got name: %s (wanted %s)\n", name, rh->name);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "Got type: %d (wanted %d)\n",
-                 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
+               "Got type: %d (wanted %d)\n",
+               rd[i].record_type, rh->query->type);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "Got data length: %d\n", rd[i].data_size);
+               "Got data length: %d\n", rd[i].data_size);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                 "Got flag %d\n", rd[i].flags);
-
-      if ((strcmp(name, rh->authority_name) == 0) &&
-          (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
+               "Got flag %d\n", rd[i].flags);
+    
+     if ((strcmp(name, rh->name) == 0) &&
+         (rd[i].record_type == rh->query->type))
       {
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
-        rh->answered = 1;
-        GNUNET_CRYPTO_hash(
-                   (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded 
*)rd[i].data,
-                   rd[i].data_size,
-                   &rh->authority);
+        rh->answered++;
       }
 
     }
 
-
     GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
     GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
+  
+    /**
+     * FIXME check pubkey against existing key in namestore?
+     * https://gnunet.org/bugs/view.php?id=2179
+     */
 
     /* Save to namestore */
-    if (0 == GNUNET_CRYPTO_hash_cmp(&zone_hash, &zone))
-    {
-      GNUNET_NAMESTORE_record_put (namestore_handle,
+    GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
                                  name,
                                  exp,
@@ -322,57 +419,185 @@
                                  &nrb->signature,
                                  &on_namestore_record_put_result, //cont
                                  NULL); //cls
-    }
-  }
   
-  if (rh->answered)
-  {
-    rh->answered = 0;
-    resolve_name(rh);
-    return;
+    if (rh->answered)
+      reply_to_dns(rh, num_records, rd);
+    else
+      reply_to_dns(rh, 0, NULL);
   }
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No authority in records\n");
-  reply_to_dns(rh, 0, NULL);
+
 }
 
+
 /**
- * Start DHT lookup for a name -> PKEY (compare NS) record in
+ * Start DHT lookup for a (name -> query->record_type) record in
  * query->authority's zone
  *
- * @param rh the pending gns query
- * @param name the name of the PKEY record
+ * @param rh the pending gns query context
+ * @param name the name to query record
  */
 static void
-resolve_authority_dht(struct GNUNET_GNS_ResolverHandle *rh)
+resolve_record_dht(struct GNUNET_GNS_ResolverHandle *rh)
 {
   uint32_t xquery;
   GNUNET_HashCode name_hash;
   GNUNET_HashCode lookup_key;
+  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
 
-  GNUNET_CRYPTO_hash(rh->authority_name,
-                     strlen(rh->authority_name),
-                     &name_hash);
+  GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
   GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
+  GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
+  
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "starting dht lookup for %s with key: %s\n",
+             rh->name, (char*)&lookup_key_string);
 
-  rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
-                                                       &dht_lookup_timeout, 
rh);
+  rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
+                                                      &dht_lookup_timeout, rh);
 
-  xquery = htonl(GNUNET_GNS_RECORD_PKEY);
-  //FIXME how long to wait for results?
-  rh->get_handle = GNUNET_DHT_get_start(dht_handle,
+  xquery = htonl(rh->query->type);
+  rh->get_handle = GNUNET_DHT_get_start(dht_handle, 
                        DHT_OPERATION_TIMEOUT,
                        GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
                        &lookup_key,
                        DHT_GNS_REPLICATION_LEVEL,
                        GNUNET_DHT_RO_NONE,
-                       &xquery,
+                       &xquery, 
                        sizeof(xquery),
-                       &process_authority_dht_result,
+                       &process_record_dht_result,
                        rh);
 
 }
 
+
 /**
+ * Namestore calls this function if we have record for this name.
+ * (or with rd_count=0 to indicate no matches)
+ *
+ * @param cls the pending query
+ * @param key the key of the zone we did the lookup
+ * @param expiration expiration date of the namestore entry
+ * @param name the name for which we need an authority
+ * @param rd_count the number of records with 'name'
+ * @param rd the record data
+ * @param signature the signature of the authority for the record data
+ */
+static void
+process_record_lookup(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 GNUNET_GNS_ResolverHandle *rh;
+  struct GNUNET_TIME_Relative remaining_time;
+  GNUNET_HashCode zone;
+
+  rh = (struct GNUNET_GNS_ResolverHandle *) cls;
+  GNUNET_CRYPTO_hash(key,
+                     sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                     &zone);
+  remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+
+  if (rd_count == 0)
+  {
+    /**
+     * Lookup terminated and no results
+     * -> DHT Phase unless data is recent
+     */
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Namestore lookup for %s terminated without results\n", name);
+    
+    /**
+     * Not our root and no record found. Try dht if expired
+     */
+    if ((0 != GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash)) &&
+        (remaining_time.rel_value != 0))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "Record %s unknown in namestore, trying dht\n",
+                 rh->name);
+      resolve_record_dht(rh);
+      return;
+    }
+    
+    /**
+     * Our zone and no result? Cannot resolve TT
+     */
+    GNUNET_assert(rh->answered == 0);
+    reply_to_dns(rh, 0, NULL);
+    return;
+
+  }
+  else
+  {
+    
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Processing additional result %s from namestore\n", name);
+    int i;
+    for (i=0; i<rd_count;i++)
+    {
+      
+      if (rd[i].record_type != rh->query->type)
+        continue;
+      
+      if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
+          == 0)
+      {
+        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This record is expired. 
Skipping\n");
+        continue;
+      }
+      
+      rh->answered++;
+      
+    }
+    
+    /**
+     * no answers found
+     */
+    if (rh->answered == 0)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 
+                 "No answers found. This is odd!\n");
+      reply_to_dns(rh, 0, NULL);
+      return;
+    }
+    
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
+               rh->answered);
+
+    reply_to_dns(rh, rd_count, rd);
+  }
+}
+
+
+/**
+ * The final phase of resolution.
+ * This is a name that is canonical and we do not have a delegation.
+ *
+ * @param rh the pending lookup
+ */
+static void
+resolve_record(struct GNUNET_GNS_ResolverHandle *rh)
+{
+  
+  /**
+   * Try to resolve this record in our namestore.
+   * The name to resolve is now in rh->authority_name
+   * since we tried to resolve it to an authority
+   * and failed.
+   **/
+  GNUNET_NAMESTORE_lookup_record(namestore_handle,
+                                 &rh->authority,
+                                 rh->name,
+                                 rh->query->type,
+                                 &process_record_lookup,
+                                 rh);
+
+}
+
+/**
  * Function called when we get a result from the dht
  * for our query
  *
@@ -388,7 +613,7 @@
  * @param data the record data
  */
 static void
-process_name_dht_result(void* cls,
+process_authority_dht_result(void* cls,
                  struct GNUNET_TIME_Absolute exp,
                  const GNUNET_HashCode * key,
                  const struct GNUNET_PeerIdentity *get_path,
@@ -402,31 +627,29 @@
   struct GNSNameRecordBlock *nrb;
   uint32_t num_records;
   char* name = NULL;
-  char* rd_data = (char*)data;
+  char* rd_data = (char*) data;
   int i;
   int rd_size;
-  
   GNUNET_HashCode zone, name_hash;
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
   
   if (data == NULL)
     return;
-
-  //FIXME maybe check expiration here, check block type
   
+  //FIXME check expiration?
+  
   rh = (struct GNUNET_GNS_ResolverHandle *)cls;
   nrb = (struct GNSNameRecordBlock*)data;
   
-  /* stop lookup and timeout task */
+  /* stop dht lookup and timeout task */
   GNUNET_DHT_get_stop (rh->get_handle);
   GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
-  
+
   rh->get_handle = NULL;
+  num_records = ntohl(nrb->rd_count);
   name = (char*)&nrb[1];
-  num_records = ntohl(nrb->rd_count);
   {
     struct GNUNET_NAMESTORE_RecordData rd[num_records];
-
+    
     rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
     rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
   
@@ -439,36 +662,42 @@
       return;
     }
 
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "Got name: %s (wanted %s)\n", name, rh->authority_name);
     for (i=0; i<num_records; i++)
     {
+    
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got name: %s (wanted %s)\n", name, rh->name);
+                "Got name: %s (wanted %s)\n", name, rh->authority_name);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got type: %d (wanted %d)\n",
-               rd[i].record_type, rh->query->type);
+                 "Got type: %d (wanted %d)\n",
+                 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got data length: %d\n", rd[i].data_size);
+                 "Got data length: %d\n", rd[i].data_size);
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Got flag %d\n", rd[i].flags);
-    
-     if ((strcmp(name, rh->name) == 0) &&
-         (rd[i].record_type == rh->query->type))
+                 "Got flag %d\n", rd[i].flags);
+
+      if ((strcmp(name, rh->authority_name) == 0) &&
+          (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
       {
-        rh->answered++;
+        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
+        rh->answered = 1;
+        GNUNET_CRYPTO_hash(
+                   (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded 
*)rd[i].data,
+                   rd[i].data_size,
+                   &rh->authority);
       }
 
     }
 
+
     GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
     GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
-  
-    /**
-     * FIXME check pubkey against existing key in namestore?
-     * https://gnunet.org/bugs/view.php?id=2179
-     */
 
     /* Save to namestore */
-    GNUNET_NAMESTORE_record_put (namestore_handle,
+    if (0 != GNUNET_CRYPTO_hash_cmp(&zone_hash, &zone))
+    {
+      GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
                                  name,
                                  exp,
@@ -477,66 +706,70 @@
                                  &nrb->signature,
                                  &on_namestore_record_put_result, //cont
                                  NULL); //cls
+    }
+  }
   
-    if (rh->answered)
-      reply_to_dns(rh, num_records, rd);
+  if (rh->answered)
+  {
+    rh->answered = 0;
+    /* delegate */
+    if (strcmp(rh->name, "") == 0)
+      resolve_record(rh);
     else
-      reply_to_dns(rh, 0, NULL);
+      resolve_name(rh);
+    return;
   }
 
+  /* resolve */
+  if (strcmp(rh->name, "") == 0)
+  {
+    /* promote authority back to name */
+    strcpy(rh->name, rh->authority_name);
+    resolve_record(rh);
+    return;
+  }
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No authority in records\n");
+  reply_to_dns(rh, 0, NULL);
 }
 
-
-
-
 /**
- * Start DHT lookup for a (name -> query->record_type) record in
+ * Start DHT lookup for a name -> PKEY (compare NS) record in
  * query->authority's zone
  *
- * @param rh the pending gns query context
- * @param name the name to query record
+ * @param rh the pending gns query
+ * @param name the name of the PKEY record
  */
 static void
-resolve_name_dht(struct GNUNET_GNS_ResolverHandle *rh, const char* name)
+resolve_authority_dht(struct GNUNET_GNS_ResolverHandle *rh)
 {
   uint32_t xquery;
   GNUNET_HashCode name_hash;
   GNUNET_HashCode lookup_key;
-  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "A\n");
-
-  GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
+  GNUNET_CRYPTO_hash(rh->authority_name,
+                     strlen(rh->authority_name),
+                     &name_hash);
   GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
-  GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
-  
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "starting dht lookup for %s with key: %s\n",
-             name, (char*)&lookup_key_string);
 
-  rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
-                                                      &dht_lookup_timeout, rh);
+  rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
+                                                       &dht_lookup_timeout,
+                                                       rh);
 
-  xquery = htonl(rh->query->type);
+  xquery = htonl(GNUNET_GNS_RECORD_PKEY);
   //FIXME how long to wait for results?
-  rh->get_handle = GNUNET_DHT_get_start(dht_handle, 
+  rh->get_handle = GNUNET_DHT_get_start(dht_handle,
                        DHT_OPERATION_TIMEOUT,
                        GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
                        &lookup_key,
                        DHT_GNS_REPLICATION_LEVEL,
                        GNUNET_DHT_RO_NONE,
-                       &xquery, 
-                       sizeof(xquery),
-                       &process_name_dht_result,
+                       NULL,
+                       0,//sizeof(xquery),
+                       &process_authority_dht_result,
                        rh);
 
 }
 
-//Prototype
-static void
-resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
-
 /**
  * This is a callback function that should give us only PKEY
  * records. Used to query the namestore for the authority (PKEY)
@@ -582,15 +815,49 @@
      * _IF_ the current authoritative zone is us we cannot resolve
      * _ELSE_ we can still check the _expired_ dht
      */
-    if ((0 != GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash)) &&
-        (remaining_time.rel_value == 0))
+    
+    /**
+     * No PKEY in our root. Try to resolve actual type in our zone
+     * if name is canonical. Else we cannot resolve.
+     */
+    if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash))
     {
+      if (strcmp(rh->name, "") == 0)
+      {
+        /**
+         * Promote this authority back to a name
+         */
+        strcpy(rh->name, rh->authority_name);
+        resolve_record(rh);
+        return;
+      }
+      else
+      {
+        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                   "Authority %s unknown in namestore, cannot resolve\n",
+                   rh->authority_name);
+      }
+      reply_to_dns(rh, 0, NULL);
+      return;
+    }
+    
+    /**
+     * Not our root and no PKEY found. Try dht if expired
+     * FIXME only do when expired?
+     */
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "AAAA %d\n", remaining_time.rel_value);
+    if ((0 != GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash)))
+    {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                  "Authority %s unknown in namestore, trying dht\n",
                  rh->authority_name);
       resolve_authority_dht(rh);
       return;
     }
+    
+    /**
+     * Not our root and not expired or no records. Cannot resolve
+     */
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority %s unknown\n",
                rh->authority_name);
     reply_to_dns(rh, 0, NULL);
@@ -618,6 +885,7 @@
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                    "This dht entry is expired. Refreshing\n");
         resolve_authority_dht(rh);
+        return;
       }
 
       continue;
@@ -630,7 +898,10 @@
     GNUNET_CRYPTO_hash(rd[i].data,
                        sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                        &rh->authority);
-    resolve_name(rh);
+    if (strcmp(rh->name, "") == 0)
+      resolve_record(rh);
+    else
+      resolve_name(rh);
     return;
   }
     
@@ -644,220 +915,6 @@
 
 
 /**
- * Reply to client with the result from our lookup.
- *
- * @param rh the request handle of the lookup
- * @param rd_count the number of records to return
- * @param rd the record data
- */
-static void
-reply_to_dns(struct GNUNET_GNS_ResolverHandle *rh, uint32_t rd_count,
-             const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  int i;
-  size_t len;
-  int ret;
-  char *buf;
-  struct GNUNET_DNSPARSER_Packet *packet = rh->packet;
-  struct GNUNET_DNSPARSER_Record answer_records[rh->answered];
-  struct GNUNET_DNSPARSER_Record additional_records[rd_count-(rh->answered)];
-  packet->answers = answer_records;
-  packet->additional_records = additional_records;
-  
-  /**
-   * Put records in the DNS packet and modify it
-   * to a response
-   */
-  len = sizeof(struct GNUNET_DNSPARSER_Record*);
-  for (i=0; i < rd_count; i++)
-  {
-    
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Adding type %d to DNS response\n", rd[i].record_type);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", rh->name);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "QName: %s\n", rh->query->name);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size);
-    
-    if (rd[i].record_type == rh->query->type)
-    {
-      answer_records[i].name = rh->query->name;
-      answer_records[i].type = rd[i].record_type;
-      answer_records[i].data.raw.data_len = rd[i].data_size;
-      answer_records[i].data.raw.data = (char*)rd[i].data;
-      answer_records[i].expiration_time = rd[i].expiration;
-      answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
-    }
-    else
-    {
-      additional_records[i].name = rh->query->name;
-      additional_records[i].type = rd[i].record_type;
-      additional_records[i].data.raw.data_len = rd[i].data_size;
-      additional_records[i].data.raw.data = (char*)rd[i].data;
-      additional_records[i].expiration_time = rd[i].expiration;
-      additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
-    }
-  }
-  
-  packet->num_answers = rh->answered;
-  packet->num_additional_records = rd_count-(rh->answered);
-  
-  if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash))
-    packet->flags.authoritative_answer = 1;
-  else
-    packet->flags.authoritative_answer = 0;
-
-  if (rd == NULL)
-    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
-  else
-    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
-  
-  packet->flags.query_or_response = 1;
-
-  
-  /**
-   * Reply to DNS
-   */
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "Building DNS response\n");
-  ret = GNUNET_DNSPARSER_pack (packet,
-                               1024, /* FIXME magic from dns redirector */
-                               &buf,
-                               &len);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "Built DNS response! (ret=%d,len=%d)\n", ret, len);
-  if (ret == GNUNET_OK)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Answering DNS request\n");
-    GNUNET_DNS_request_answer(rh->request_handle,
-                              len,
-                              buf);
-    //GNUNET_free(answer);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n");
-  }
-  else
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-               "Error building DNS response! (ret=%d)", ret);
-  }
-
-  GNUNET_free(rh->name);
-  GNUNET_free(rh);
-}
-
-
-/**
- * Namestore calls this function if we have record for this name.
- * (or with rd_count=0 to indicate no matches)
- *
- * @param cls the pending query
- * @param key the key of the zone we did the lookup
- * @param expiration expiration date of the namestore entry
- * @param name the name for which we need an authority
- * @param rd_count the number of records with 'name'
- * @param rd the record data
- * @param signature the signature of the authority for the record data
- */
-static void
-process_authoritative_result(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 GNUNET_GNS_ResolverHandle *rh;
-  struct GNUNET_TIME_Relative remaining_time;
-  GNUNET_HashCode zone;
-
-  rh = (struct GNUNET_GNS_ResolverHandle *) cls;
-  GNUNET_CRYPTO_hash(key,
-                     sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &zone);
-  remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
-
-  if (rd_count == 0)
-  {
-    /**
-     * Lookup terminated and no results
-     * -> DHT Phase unless data is recent
-     */
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Namestore lookup for %s terminated without results\n", name);
-    
-    /**
-     * if this is not our zone we cannot rely on the namestore to be
-     * complete. -> Query DHT
-     */
-    if (GNUNET_CRYPTO_hash_cmp(&zone, &zone_hash))
-    {
-      if (remaining_time.rel_value == 0)
-      {
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "trying dht...\n");
-        resolve_name_dht(rh, rh->name);
-        return;
-      }
-      else
-      {
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "Record is still recent. No DHT lookup\n");
-      }
-    }
-
-    /**
-     * Our zone and no result? Cannot resolve TT
-     */
-    GNUNET_assert(rh->answered == 0);
-    reply_to_dns(rh, 0, NULL);
-    return;
-
-  }
-  else
-  {
-    
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Processing additional result %s from namestore\n", name);
-    int i;
-    for (i=0; i<rd_count;i++)
-    {
-      
-      if ((strcmp(name, rh->query->name) == 0)
-          && (rd[i].record_type != rh->query->type))
-        continue;
-      
-      if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
-          == 0)
-      {
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This record is expired. 
Skipping\n");
-        continue;
-      }
-      
-      rh->answered++;
-      
-    }
-    
-    /**
-     * no answers found
-     * consult dht if expired
-     */
-    if ((remaining_time.rel_value == 0) && (rh->answered == 0))
-    {
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 
-                 "This dht entry is old. Refreshing.\n");
-      resolve_name_dht(rh, name);
-      return;
-    }
-    
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
-               rh->answered);
-
-    reply_to_dns(rh, rd_count, rd);
-  }
-}
-
-/**
  * Determine if this name is canonical.
  * i.e.
  * a.b.gnunet  = not canonical
@@ -885,28 +942,33 @@
  * passed top level domain.
  *
  * @param name the domain
- * @return the tld
+ * @param dest the destination where the tld will be put
  */
-static char*
-pop_tld(char* name)
+void
+pop_tld(char* name, char* dest)
 {
   uint32_t len;
 
   if (is_canonical(name))
-    return NULL;
+  {
+    strcpy(dest, name);
+    strcpy(name, "");
+    return;
+  }
 
   for (len = strlen(name); len > 0; len--)
   {
     if (*(name+len) == '.')
       break;
   }
-
+  
+  //Was canonical?
   if (len == 0)
-    return NULL;
+    return;
 
   name[len] = '\0';
 
-  return (name+len+1);
+  strcpy(dest, (name+len+1));
 }
 
 
@@ -921,27 +983,18 @@
 static void
 resolve_name(struct GNUNET_GNS_ResolverHandle *rh)
 {
-  if (is_canonical(rh->name))
-  {
-    /* We only need to check the current zone's ns */
-    GNUNET_NAMESTORE_lookup_record(namestore_handle,
-                               &rh->authority,
-                               rh->name,
-                               rh->query->type,
-                               &process_authoritative_result,
-                               rh);
-  }
-  else
-  {
-    /* We have to resolve the authoritative entity first */
-    rh->authority_name = pop_tld(rh->name);
-    GNUNET_NAMESTORE_lookup_record(namestore_handle,
+  
+  /**
+   * Try to resolve this name to a delegation.
+   **/
+  pop_tld(rh->name, rh->authority_name);
+  GNUNET_NAMESTORE_lookup_record(namestore_handle,
                                  &rh->authority,
                                  rh->authority_name,
                                  GNUNET_GNS_RECORD_PKEY,
                                  &process_authority_lookup,
                                  rh);
-  }
+
 }
 
 /**
@@ -975,6 +1028,8 @@
   memcpy(rh->name, q->name,
          strlen(q->name)-strlen(gnunet_tld));
 
+  rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
+
   rh->request_handle = request;
 
   /* Start resolution in our zone */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]