+static void
+backward_resolution (void* cls,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+ struct VerifyRequestHandle *vrh;
+ const struct GNUNET_CREDENTIAL_DelegationRecord *sets;
+ struct CredentialRecordEntry *cred_pointer;
+ struct DelegationSetQueueEntry *current_set;
+ struct DelegationSetQueueEntry *ds_entry;
+ struct DelegationSetQueueEntry *tmp_set;
+ struct DelegationQueueEntry *dq_entry;
+ char *expanded_attr;
+ char *lookup_attribute;
+ int i;
+ int j;
+
+
+ current_set = cls;
+ current_set->lookup_request = NULL;
+ vrh = current_set->handle;
+ vrh->pending_lookups--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got %d attrs\n", rd_count);
+
+ // Each OR
+ for (i=0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_TYPE_ATTRIBUTE != rd[i].record_type)
+ continue;
+
+ sets = rd[i].data;
+ struct GNUNET_CREDENTIAL_DelegationSet set[ntohl(sets->set_count)];
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found new attribute delegation with %d sets. Creating new Job...\n",
+ ntohl (sets->set_count));
+
+ if (GNUNET_OK !=GNUNET_CREDENTIAL_delegation_set_deserialize (GNUNET_ntohll(sets->data_size),
+ (const char*)&sets[1],
+ ntohl(sets->set_count),
+ set))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to deserialize!\n");
+ continue;
+ }
+ dq_entry = GNUNET_new (struct DelegationQueueEntry);
+ dq_entry->required_solutions = ntohl(sets->set_count);
+ dq_entry->parent_set = current_set;
+ GNUNET_CONTAINER_DLL_insert (current_set->queue_entries_head,
+ current_set->queue_entries_tail,
+ dq_entry);
+ // Each AND
+ for (j=0; j<ntohl(sets->set_count); j++)
+ {
+ ds_entry = GNUNET_new (struct DelegationSetQueueEntry);
+ if (NULL != current_set->attr_trailer)
+ {
+ if (0 == set[j].subject_attribute_len)
+ {
+ GNUNET_asprintf (&expanded_attr,
+ "%s",
+ current_set->attr_trailer);
+
+ } else {
+ GNUNET_asprintf (&expanded_attr,
+ "%s.%s",
+ set[j].subject_attribute,
+ current_set->attr_trailer);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Expanded to %s\n", expanded_attr);
+ ds_entry->unresolved_attribute_delegation = expanded_attr;
+ } else {
+ if (0 != set[j].subject_attribute_len)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not Expanding %s\n", set[j].subject_attribute);
+ ds_entry->unresolved_attribute_delegation = GNUNET_strdup (set[j].subject_attribute);
+ }
+ }
+
+ //Add a credential chain entry
+ ds_entry->delegation_chain_entry = GNUNET_new (struct DelegationChainEntry);
+ ds_entry->delegation_chain_entry->subject_key = set[j].subject_key;
+ ds_entry->issuer_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+ GNUNET_memcpy (ds_entry->issuer_key,
+ &set[j].subject_key,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ if (0 < set[j].subject_attribute_len)
+ ds_entry->delegation_chain_entry->subject_attribute = GNUNET_strdup (set[j].subject_attribute);
+ ds_entry->delegation_chain_entry->issuer_key = *current_set->issuer_key;
+ ds_entry->delegation_chain_entry->issuer_attribute = GNUNET_strdup (current_set->lookup_attribute);
+
+ ds_entry->parent_queue_entry = dq_entry; //current_delegation;
+ GNUNET_CONTAINER_DLL_insert (dq_entry->set_entries_head,
+ dq_entry->set_entries_tail,
+ ds_entry);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking for cred match\n");
+ /**
+ * Check if this delegation already matches one of our credentials
+ */
+ for(cred_pointer = vrh->cred_chain_head; cred_pointer != NULL;
+ cred_pointer = cred_pointer->next)
+ {
+ if(0 != memcmp (&set->subject_key,
+ &cred_pointer->credential->issuer_key,
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking if %s matches %s\n",
+ ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute);
+
+ if (0 != strcmp (ds_entry->unresolved_attribute_delegation,
+ cred_pointer->credential->issuer_attribute))
+ continue;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found issuer\n");
+ cred_pointer->refcount++;
+ //Backtrack
+ for (tmp_set = ds_entry;
+ NULL != tmp_set->parent_queue_entry;
+ tmp_set = tmp_set->parent_queue_entry->parent_set)
+ {
+ tmp_set->parent_queue_entry->required_solutions--;
+ if (NULL != tmp_set->delegation_chain_entry)
+ {
+ vrh->delegation_chain_size++;
+ GNUNET_CONTAINER_DLL_insert (vrh->delegation_chain_head,
+ vrh->delegation_chain_tail,
+ tmp_set->delegation_chain_entry);
+ }
+ if (0 < tmp_set->parent_queue_entry->required_solutions)
+ break;
+ }
+
+ if (NULL == tmp_set->parent_queue_entry)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All solutions found\n");
+ //Found match
+ send_lookup_response (vrh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not all solutions found yet.\n");
+ continue;
+
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Building new lookup request from %s\n",
+ ds_entry->unresolved_attribute_delegation);
+ //Continue with backward resolution
+ char issuer_attribute_name[strlen (ds_entry->unresolved_attribute_delegation)+1];
+ strcpy (issuer_attribute_name,
+ ds_entry->unresolved_attribute_delegation);
+ char *next_attr = strtok (issuer_attribute_name, ".");
+ GNUNET_asprintf (&lookup_attribute,
+ "%s.gnu",
+ next_attr);
+ GNUNET_asprintf (&ds_entry->lookup_attribute,
+ "%s",
+ next_attr);
+ if (strlen (next_attr) == strlen (ds_entry->unresolved_attribute_delegation))
+ {
+ ds_entry->attr_trailer = NULL;
+ } else {
+ next_attr += strlen (next_attr) + 1;
+ ds_entry->attr_trailer = GNUNET_strdup (next_attr);
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking up %s\n", ds_entry->lookup_attribute);
+ if (NULL != ds_entry->attr_trailer)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s still to go...\n", ds_entry->attr_trailer);
+
+ vrh->pending_lookups++;
+ ds_entry->handle = vrh;
+ ds_entry->lookup_request = GNUNET_GNS_lookup (gns,
+ lookup_attribute,
+ ds_entry->issuer_key, //issuer_key,
+ GNUNET_GNSRECORD_TYPE_ATTRIBUTE,
+ GNUNET_GNS_LO_DEFAULT,
+ &backward_resolution,
+ ds_entry);
+ GNUNET_free (lookup_attribute);
+ }
+ }
+
+ if(0 == vrh->pending_lookups)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We are all out of attributes...\n");
+ send_lookup_response (vrh);
+ return;
+
+ }
+}
+
+