struct AuthorityChain *next;
GNUNET_HashCode zone;
+
+ /* was the ns entry fresh */
+ int fresh;
};
struct GNUNET_GNS_ResolverHandle;
uint32_t rd_count,
const struct GNUNET_NAMESTORE_RecordData *rd);
+enum ResolutionStatus
+{
+ EXISTS = 1,
+ EXPIRED = 2
+};
+
/**
* Handle to a currenty pending resolution
*/
struct AuthorityChain *authority_chain_head;
struct AuthorityChain *authority_chain_tail;
+ enum ResolutionStatus status;
+
};
struct ClientShortenHandle
struct GNUNET_TIME_Relative dht_update_interval;
GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
-static void resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
+//static void resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
/**
* Reply to client with the result from our lookup.
* @param name the name to query record
*/
static void
-resolve_record_dht(struct GNUNET_GNS_ResolverHandle *rh)
+resolve_record_from_dht(struct GNUNET_GNS_ResolverHandle *rh)
{
uint32_t xquery;
GNUNET_HashCode name_hash;
* @param signature the signature of the authority for the record data
*/
static void
-process_record_lookup(void* cls,
+process_record_lookup_ns(void* cls,
const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
struct GNUNET_TIME_Absolute expiration,
const char *name, unsigned int rd_count,
&zone);
remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+ rh->status = 0;
+
+ if (name != NULL)
+ {
+ rh->status |= EXISTS;
+ }
+
+ if (remaining_time.rel_value == 0)
+ {
+ rh->status |= EXPIRED;
+ }
+
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)) &&
- ((name == NULL) || (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;
- }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Record %s unknown in namestore\n",
+ rh->name);
/**
* Our zone and no result? Cannot resolve TT
*/
- GNUNET_assert(rh->answered == 0);
rh->proc(rh->proc_cls, rh, 0, NULL);
return;
}
}
-
/**
* 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)
+resolve_record_from_ns(struct GNUNET_GNS_ResolverHandle *rh)
{
/**
&rh->authority,
rh->name,
rh->query->type,
- &process_record_lookup,
+ &process_record_lookup_ns,
rh);
}
* promote authority back to name and try to resolve record
*/
strcpy(rh->name, rh->authority_name);
- resolve_record(rh);
- }
- else
- {
- rh->proc(rh->proc_cls, rh, 0, NULL);
}
+ rh->proc(rh->proc_cls, rh, 0, NULL);
}
+// Prototype
+static void resolve_delegation_from_dht(struct GNUNET_GNS_ResolverHandle *rh);
/**
* Function called when we get a result from the dht
rh->answered = 0;
/* delegate */
if (strcmp(rh->name, "") == 0)
- resolve_record(rh);
+ rh->proc(rh->proc_cls, rh, 0, NULL);
else
- resolve_name(rh);
+ resolve_delegation_from_dht(rh);
return;
}
- /* resolve */
+ /* resolve never get here, should timeout??*/
+
+
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");
rh->proc(rh->proc_cls, rh, 0, NULL);
}
+
+/**
+ * DHT lookup result for record.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+process_record_result_dht(void* cls, struct GNUNET_GNS_ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ if (rd_count == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "No records for %s found in DHT. Aborting\n",
+ rh->name);
+ /* give up, cannot resolve */
+ reply_to_dns(NULL, rh, 0, NULL);
+ return;
+ }
+
+ /* results found yay */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Record resolved from namestore!");
+ reply_to_dns(NULL, rh, rd_count, rd);
+
+}
+
+
+/**
+ * Namestore lookup result for record.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+process_record_result_ns(void* cls, struct GNUNET_GNS_ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ if (rd_count == 0)
+ {
+ /* ns entry expired. try dht */
+ if (rh->status & (EXPIRED | !EXISTS))
+ {
+ rh->proc = &process_record_result_dht;
+ resolve_record_from_dht(rh);
+ return;
+ }
+ /* give up, cannot resolve */
+ reply_to_dns(NULL, rh, 0, NULL);
+ return;
+ }
+
+ /* results found yay */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Record resolved from namestore!");
+ reply_to_dns(NULL, rh, rd_count, rd);
+
+}
+
+
+/**
+ * Determine if this name is canonical.
+ * i.e.
+ * a.b.gnunet = not canonical
+ * a = canonical
+ *
+ * @param name the name to test
+ * @return 1 if canonical
+ */
+static int
+is_canonical(char* name)
+{
+ uint32_t len = strlen(name);
+ int i;
+
+ for (i=0; i<len; i++)
+ {
+ if (*(name+i) == '.')
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Move one level up in the domain hierarchy and return the
+ * passed top level domain.
+ *
+ * @param name the domain
+ * @param dest the destination where the tld will be put
+ */
+void
+pop_tld(char* name, char* dest)
+{
+ uint32_t len;
+
+ if (is_canonical(name))
+ {
+ strcpy(dest, name);
+ strcpy(name, "");
+ return;
+ }
+
+ for (len = strlen(name); len > 0; len--)
+ {
+ if (*(name+len) == '.')
+ break;
+ }
+
+ //Was canonical?
+ if (len == 0)
+ return;
+
+ name[len] = '\0';
+
+ strcpy(dest, (name+len+1));
+}
+
+/**
+ * Namestore resolution for delegation finished. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+process_dht_delegation_dns(void* cls, struct GNUNET_GNS_ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ if (strcmp(rh->name, "") == 0)
+ {
+ /* We resolved full name for delegation. resolving record */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Resolved full name for delegation via DHT. resolving record '' in ns\n");
+ rh->proc = &process_record_result_ns;
+ resolve_record_from_ns(rh);
+ return;
+ }
+
+ /**
+ * we still have some left
+ **/
+ if (is_canonical(rh->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Resolving canonical record %s in ns\n", rh->name);
+ rh->proc = &process_record_result_ns;
+ resolve_record_from_ns(rh);
+ return;
+ }
+ /* give up, cannot resolve */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Cannot fully resolve delegation for %s via DHT!\n",
+ rh->name);
+ reply_to_dns(NULL, rh, 0, NULL);
+}
+
+
/**
* Start DHT lookup for a name -> PKEY (compare NS) record in
- * query->authority's zone
+ * rh->authority's zone
*
* @param rh the pending gns query
* @param name the name of the PKEY record
*/
static void
-resolve_authority_dht(struct GNUNET_GNS_ResolverHandle *rh)
+resolve_delegation_from_dht(struct GNUNET_GNS_ResolverHandle *rh)
{
uint32_t xquery;
GNUNET_HashCode name_hash;
}
+
+/**
+ * Namestore resolution for delegation finished. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+process_ns_delegation_dns(void* cls, struct GNUNET_GNS_ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ if (strcmp(rh->name, "") == 0)
+ {
+ /* We resolved full name for delegation. resolving record */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Resolved full name for delegation. resolving record ''\n");
+ rh->proc = &process_record_result_ns;
+ resolve_record_from_ns(rh);
+ return;
+ }
+
+ /**
+ * we still have some left
+ * check if ns entry is fresh
+ **/
+ if (rh->status & (EXISTS | !EXPIRED))
+ {
+ if (is_canonical(rh->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Resolving canonical record %s\n", rh->name);
+ rh->proc = &process_record_result_ns;
+ resolve_record_from_ns(rh);
+ }
+ else
+ {
+ /* give up, cannot resolve */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Cannot fully resolve delegation for %s!\n",
+ rh->name);
+ reply_to_dns(NULL, rh, 0, NULL);
+ }
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to resolve delegation for %s via DHT\n",
+ rh->name);
+ rh->proc = &process_dht_delegation_dns;
+ resolve_delegation_from_dht(rh);
+}
+
+//Prototype
+static void resolve_delegation_from_ns(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)
* @param signature the signature of the authority for the record data
*/
static void
-process_authority_lookup(void* cls,
+process_authority_lookup_ns(void* cls,
const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
struct GNUNET_TIME_Absolute expiration,
const char *name,
struct GNUNET_GNS_ResolverHandle *rh;
struct GNUNET_TIME_Relative remaining_time;
GNUNET_HashCode zone;
+ char* new_name;
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
rd_count);
&zone);
remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+ rh->status = 0;
+
+ if (name != NULL)
+ {
+ rh->status |= EXISTS;
+ }
+
+ if (remaining_time.rel_value == 0)
+ {
+ rh->status |= EXPIRED;
+ }
+
/**
* No authority found in namestore.
*/
{
/**
* We did not find an authority in the namestore
- * _IF_ the current authoritative zone is us we cannot resolve
- * _ELSE_ we can still check the _expired_ dht
*/
/**
- * No PKEY in our root. Try to resolve actual type in our zone
- * if name is canonical. Else we cannot resolve.
+ * No PKEY in zone.
+ * Promote this authority back to a name maybe it is
+ * our record.
*/
- if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash))
+ if (strcmp(rh->name, "") == 0)
{
- 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 for %s unknown in namestore, cannot resolve\n",
- rh->authority_name, rh->name);
- }
- rh->proc(rh->proc_cls, rh, 0, NULL);
- return;
+ /* simply promote back */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Promoting %s back to name\n", rh->authority_name);
+ strcpy(rh->name, rh->authority_name);
}
-
- /**
- * 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)))
+ else
{
- if (strcmp(rh->name, "") == 0)
- {
- /**
- * Promote this authority back to a name
- */
- strcpy(rh->name, rh->authority_name);
- resolve_record(rh);
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Authority %s for %s unknown in namestore, trying dht\n",
- rh->authority_name, rh->name);
- resolve_authority_dht(rh);
- }
- return;
+ /* add back to existing name */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Adding %s back to %s\n",
+ rh->authority_name, rh->name);
+ new_name = GNUNET_malloc(strlen(rh->name)
+ + strlen(rh->authority_name) + 2);
+ memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
+ strcpy(new_name, rh->name);
+ strcpy(new_name+strlen(new_name)+1, ".");
+ strcpy(new_name+strlen(new_name)+2, rh->authority_name);
+ GNUNET_free(rh->name);
+ rh->name = new_name;
}
-
- /**
- * Not our root and not expired or no records. Cannot resolve
- */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority %s unknown\n",
- rh->authority_name);
rh->proc(rh->proc_cls, rh, 0, NULL);
return;
}
if (remaining_time.rel_value == 0)
{
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "This dht entry is expired. Refreshing\n");
- resolve_authority_dht(rh);
+ "This dht entry is expired.\n");
+ rh->authority_chain_head->fresh = 0;
+ rh->proc(rh->proc_cls, rh, 0, NULL);
return;
}
auth);
if (strcmp(rh->name, "") == 0)
- resolve_record(rh);
+ rh->proc(rh->proc_cls, rh, 0, NULL);
else
- resolve_name(rh);
+ resolve_delegation_from_ns(rh);
return;
}
}
-/**
- * Determine if this name is canonical.
- * i.e.
- * a.b.gnunet = not canonical
- * a = canonical
- *
- * @param name the name to test
- * @return 1 if canonical
- */
-static int
-is_canonical(char* name)
-{
- uint32_t len = strlen(name);
- int i;
-
- for (i=0; i<len; i++)
- {
- if (*(name+i) == '.')
- return 0;
- }
- return 1;
-}
/**
- * Move one level up in the domain hierarchy and return the
- * passed top level domain.
+ * The first phase of resolution.
+ * First check if the name is canonical.
+ * If it is then try to resolve directly.
+ * If not then we first have to resolve the authoritative entities.
*
- * @param name the domain
- * @param dest the destination where the tld will be put
+ * @param rh the pending lookup
*/
-void
-pop_tld(char* name, char* dest)
+/*static void
+resolve_name(struct GNUNET_GNS_ResolverHandle *rh)
{
- uint32_t len;
-
- if (is_canonical(name))
- {
- strcpy(dest, name);
- strcpy(name, "");
- return;
- }
-
- for (len = strlen(name); len > 0; len--)
- {
- if (*(name+len) == '.')
- break;
- }
- //Was canonical?
- if (len == 0)
- return;
+ 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);
- name[len] = '\0';
+}*/
- strcpy(dest, (name+len+1));
-}
-/**
- * The first phase of resolution.
- * First check if the name is canonical.
- * If it is then try to resolve directly.
- * If not then we first have to resolve the authoritative entities.
- *
- * @param rh the pending lookup
- */
static void
-resolve_name(struct GNUNET_GNS_ResolverHandle *rh)
+resolve_delegation_from_ns(struct GNUNET_GNS_ResolverHandle *rh)
{
/**
&rh->authority,
rh->authority_name,
GNUNET_GNS_RECORD_PKEY,
- &process_authority_lookup,
+ &process_authority_lookup_ns,
rh);
}
rh->packet = p;
rh->query = q;
rh->authority = zone_hash;
- rh->proc = &reply_to_dns;
+
rh->name = GNUNET_malloc(strlen(q->name)
- strlen(gnunet_tld) + 1);
rh->authority_chain_head->zone = zone_hash;
/* Start resolution in our zone */
- resolve_name(rh);
+ rh->proc = &process_ns_delegation_dns;
+ resolve_delegation_from_ns(rh);
+ //resolve_name(rh);
}
/**
rh->proc_cls = (void*)csh;
/* Start resolution in our zone */
- resolve_name(rh);
+ //resolve_name(rh);
}