From 378dd7c051aea610ab78cfc46cd96a13d4f1fe13 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Thu, 21 Sep 2017 11:21:01 -0500 Subject: [PATCH] beginning to resolve ipns addresses --- cid/cid.c | 20 ++++++++++- include/ipfs/cid/cid.h | 10 +++++- namesys/resolver.c | 80 ++++++++++++++++++++++++++++++++++++++++++ namesys/routing.c | 2 +- 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 namesys/resolver.c diff --git a/cid/cid.c b/cid/cid.c index 089d1d1..dcfd281 100644 --- a/cid/cid.c +++ b/cid/cid.c @@ -95,7 +95,7 @@ int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct * @param version the version * @param hash the multihash * @param hash_length the length of the multihash in bytes - * @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF) + * @param codec the codec to be used (NOTE: For version 0, this should be CID_DAG_PROTOBUF) * @returns the new Cid or NULL if there was a problem */ struct Cid* ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec) { @@ -152,6 +152,24 @@ struct Cid* ipfs_cid_copy(const struct Cid* original) { return copy; } +/*** + * Create a CID from an ipfs or ipns string (i.e. "/ipns/QmAb12CD..." + * @param incoming the incoming string + * @param cid the resultant Cid + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_cid_decode_hash_from_ipfs_ipns_string(const char* incoming, struct Cid** cid) { + if (incoming == NULL) + return 0; + if (strstr(incoming, "/ipfs/") != incoming && strstr(incoming, "/ipns/") != incoming) + return 0; + const char* base58 = &incoming[6]; + char* slash = strstr(incoming, "/"); + if (slash != NULL) + slash[0] = '\0'; + return ipfs_cid_decode_hash_from_base58((unsigned char*)base58, strlen(base58), cid); +} + /*** * Fill a Cid struct based on a base 58 encoded multihash * @param incoming the string diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h index 1990748..f98837e 100644 --- a/include/ipfs/cid/cid.h +++ b/include/ipfs/cid/cid.h @@ -78,7 +78,7 @@ size_t ipfs_cid_protobuf_encode_size(const struct Cid* incoming); * @param version the version * @param hash the multihash * @param hash_length the length of the multihash in bytes - * @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF) + * @param codec the codec to be used (NOTE: For version 0, this should be CID_DAG_PROTOBUF) * @returns the Cid, or NULL if there was a problem */ struct Cid* ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec); @@ -106,6 +106,14 @@ struct Cid* ipfs_cid_copy(const struct Cid* original); */ int ipfs_cid_decode_hash_from_base58(const unsigned char* incoming, size_t incoming_length, struct Cid** cid); +/*** + * Create a CID from an ipfs or ipns string (i.e. "/ipns/QmAb12CD..." + * @param incoming the incoming string + * @param cid the resultant Cid + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_cid_decode_hash_from_ipfs_ipns_string(const char* incoming, struct Cid** cid); + /** * Turn a cid into a base 58 of a multihash of the cid hash * @param cid the cid to work with diff --git a/namesys/resolver.c b/namesys/resolver.c new file mode 100644 index 0000000..463068b --- /dev/null +++ b/namesys/resolver.c @@ -0,0 +1,80 @@ +#include +/** + * The opposite of publisher.c + * + * These are the resources for resolving an IPNS name, turning it into an ipfs path + */ + +/** + * Determine if the incoming path is in ipns format + * @param path the path to check + * @returns true(1) if the path begins with "/ipns/" + */ +int is_ipns_string(char* path) { + if (path == NULL) + return 0; + if (strstr(path, "/ipns/") == path) + return 1; + return 0; +} + +/*** + * Resolve an IPNS name, only to its next step + * @param local_node the context + * @param path the ipns_path (i.e. "ipns/Qm12345...") + * @param results where to store the results (i.e. "ipns/Qm5678...") + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_namesys_resolver_resolve_once(struct IpfsNode* local_node, const char* path, char** results) { + struct Cid* cid = NULL; + if (!ipfs_cid_decode_hash_from_ipfs_ipns_string(path, &cid)) { + return 0; + } + + // look locally + struct DatastoreRecord* record; + if (local_node->repo->config->datastore->datastore_get(cid->hash, cid->hash_length, &record, local_node->repo->config->datastore)) { + // we are able to handle this locally... return the results + *results = (char*) malloc(record->value_size + 1); + memset(*results, 0, record->value_size + 1); + memcpy(*results, record->value, record->value_size); + ipfs_cid_free(cid); + return 1; + } + + //TODO: ask the network + ipfs_cid_free(cid); + return 0; +} + +/** + * Resolve an IPNS name. + * NOTE: if recursive is set to false, the result could be another ipns path + * @param local_node the context + * @param path the ipns path (i.e. "/ipns/Qm12345..") + * @param recursive true to resolve until the result is not ipns, false to simply get the next step in the path + * @param result the results (i.e. "/ipfs/QmAb12CD...") + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path, int recursive, char** results) { + char* result = NULL; + char* current_path = (char*) malloc(strlen(path) + 1); + strcpy(current_path, path); + + do { + // resolve the current path + if (!ipfs_namesys_resolver_resolve_once(local_node, current_path, &result)) { + libp2p_logger_error("resolver", "Resolver returned false searching for %s.\n", current_path); + free(current_path); + return 0; + } + // result will not be NULL + free(current_path); + current_path = (char*) malloc(strlen(result)+1); + strcpy(current_path, result); + free(result); + } while(recursive && is_ipns_string(current_path)); + + *results = current_path; + return 1; +} diff --git a/namesys/routing.c b/namesys/routing.c index ec088ec..9b61fd8 100644 --- a/namesys/routing.c +++ b/namesys/routing.c @@ -260,7 +260,7 @@ int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char } else { // Its an old style multihash record //log.Warning("Detected old style multihash record") - struct Cid *cid = ipfs_cid_new(0, multihash, multihash_size, CID_PROTOBUF); + struct Cid *cid = ipfs_cid_new(0, multihash, multihash_size, CID_DAG_PROTOBUF); if (cid == NULL) { free(multihash); return 0;