From 9425e2fee33c6ab6813e49ff404bf3aa4ae8ae92 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Thu, 21 Sep 2017 13:59:06 -0500 Subject: [PATCH] More work on ipns publisher and resolver --- include/ipfs/namesys/publisher.h | 4 +- include/ipfs/namesys/resolver.h | 14 ++++++ namesys/Makefile | 2 +- namesys/publisher.c | 43 ++++++++++++----- namesys/resolver.c | 14 ++++++ repo/fsrepo/lmdb_datastore.c | 2 +- repo/fsrepo/lmdb_journalstore.c | 19 +++++++- test/Makefile | 1 + test/namesys/test_namesys.h | 79 ++++++++++++++++++++++++++++++++ test/namesys/test_publisher.h | 39 ---------------- test/testit.c | 4 +- 11 files changed, 165 insertions(+), 56 deletions(-) create mode 100644 include/ipfs/namesys/resolver.h create mode 100644 test/namesys/test_namesys.h delete mode 100644 test/namesys/test_publisher.h diff --git a/include/ipfs/namesys/publisher.h b/include/ipfs/namesys/publisher.h index bb8d236..8e297b3 100644 --- a/include/ipfs/namesys/publisher.h +++ b/include/ipfs/namesys/publisher.h @@ -15,7 +15,7 @@ int ipns_validate_ipns_record (char *k, char *val); * Store the hash locally, and notify the network * * @param local_node the context - * @param cid the hash + * @param path the "/ipfs/" or "/ipns" path * @returns true(1) on success, false(0) otherwise */ -int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid); +int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, char* path); diff --git a/include/ipfs/namesys/resolver.h b/include/ipfs/namesys/resolver.h new file mode 100644 index 0000000..ee0110b --- /dev/null +++ b/include/ipfs/namesys/resolver.h @@ -0,0 +1,14 @@ +#pragma once + +#include "ipfs/core/ipfs_node.h" + +/** + * 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); diff --git a/namesys/Makefile b/namesys/Makefile index d42674d..6dcef89 100644 --- a/namesys/Makefile +++ b/namesys/Makefile @@ -7,7 +7,7 @@ endif LFLAGS = DEPS = -OBJS = base.o dns.o isdomain.o namesys.o proquint.o publisher.o pb.o name.o +OBJS = base.o dns.o isdomain.o namesys.o proquint.o publisher.o pb.o name.o resolver.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/namesys/publisher.c b/namesys/publisher.c index aa80345..4bd6260 100644 --- a/namesys/publisher.c +++ b/namesys/publisher.c @@ -174,32 +174,48 @@ int ipfs_namesys_copy_bytes(uint8_t* from, size_t from_size, uint8_t** to, size_ * Store the hash locally, and notify the network * * @param local_node the context - * @param cid the hash + * @param path the path (could be "/ipns" or "/ipfs") * @returns true(1) on success, false(0) otherwise */ -int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid) { +int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, char* path) { + int retVal = 0; + // store locally struct DatastoreRecord* record = libp2p_datastore_record_new(); if (record == NULL) return 0; - // key - if (!ipfs_namesys_copy_bytes(cid->hash, cid->hash_length, &record->key, &record->key_size)) { + // convert this peer id into a cid + struct Cid* local_peer = NULL; + + if (!ipfs_cid_decode_hash_from_base58((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &local_peer)) { libp2p_datastore_record_free(record); return 0; } - // value - if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &record->value, &record->value_size)) { + + // key, which is the peer id + if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, &record->key, &record->key_size)) { + ipfs_cid_free(local_peer); + libp2p_datastore_record_free(record); + return 0; + } + // value, which is what it should resolve to (a mutable key) + if (!ipfs_namesys_copy_bytes((uint8_t*)path, strlen(path), &record->value, &record->value_size)) { + ipfs_cid_free(local_peer); libp2p_datastore_record_free(record); return 0; } if (!local_node->repo->config->datastore->datastore_put(record, local_node->repo->config->datastore)) { + ipfs_cid_free(local_peer); libp2p_datastore_record_free(record); return 0; } libp2p_datastore_record_free(record); + // for now, even if what is below fails because of not being connected, return TRUE + retVal = 1; + // propagate to network // build the KademliaMessage struct KademliaMessage* msg = libp2p_message_new(); @@ -208,31 +224,36 @@ int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid) return 0; } msg->provider_peer_head = libp2p_utils_linked_list_new(); - msg->provider_peer_head->item = local_node->identity->peer; + msg->provider_peer_head->item = libp2p_peer_copy(local_node->identity->peer); // msg->Libp2pRecord msg->record = libp2p_record_new(); if (msg->record == NULL) { libp2p_message_free(msg); + ipfs_cid_free(local_peer); return 0; } // KademliaMessage->Libp2pRecord->author - if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, (unsigned char**)&msg->record->author, &msg->record->author_size)) { + if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, (unsigned char**)&msg->record->author, &msg->record->author_size)) { libp2p_message_free(msg); + ipfs_cid_free(local_peer); return 0; } // KademliaMessage->Libp2pRecord->key - if (!ipfs_namesys_copy_bytes(cid->hash, cid->hash_length, (unsigned char**)&msg->record->key, &msg->record->key_size)) { + if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, (unsigned char**)&msg->record->key, &msg->record->key_size)) { libp2p_message_free(msg); + ipfs_cid_free(local_peer); return 0; } // KademliaMessage->Libp2pRecord->value - if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &msg->record->value, &msg->record->value_size)) { + if (!ipfs_namesys_copy_bytes((uint8_t*)path, strlen(path), &msg->record->value, &msg->record->value_size)) { libp2p_message_free(msg); + ipfs_cid_free(local_peer); return 0; } - int retVal = libp2p_routing_dht_send_message_nearest_x(&local_node->identity->private_key, local_node->peerstore, local_node->repo->config->datastore, msg, 10); + libp2p_routing_dht_send_message_nearest_x(&local_node->identity->private_key, local_node->peerstore, local_node->repo->config->datastore, msg, 10); libp2p_message_free(msg); + ipfs_cid_free(local_peer); return retVal; } diff --git a/namesys/resolver.c b/namesys/resolver.c index 463068b..5f908cf 100644 --- a/namesys/resolver.c +++ b/namesys/resolver.c @@ -1,4 +1,9 @@ #include +#include + +#include "libp2p/utils/logger.h" +#include "ipfs/namesys/resolver.h" + /** * The opposite of publisher.c * @@ -61,7 +66,15 @@ int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path, char* current_path = (char*) malloc(strlen(path) + 1); strcpy(current_path, path); + // if we go more than 10 deep, bail + int counter = 0; + do { + if (counter > 10) { + libp2p_logger_error("resolver", "Resolver looped %d times. Infinite loop? Last result: %s.\n", counter, current_path); + free(current_path); + return 0; + } // 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); @@ -73,6 +86,7 @@ int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path, current_path = (char*) malloc(strlen(result)+1); strcpy(current_path, result); free(result); + counter++; } while(recursive && is_ipns_string(current_path)); *results = current_path; diff --git a/repo/fsrepo/lmdb_datastore.c b/repo/fsrepo/lmdb_datastore.c index 441a966..ff55764 100644 --- a/repo/fsrepo/lmdb_datastore.c +++ b/repo/fsrepo/lmdb_datastore.c @@ -253,7 +253,7 @@ int repo_fsrepo_lmdb_put(struct DatastoreRecord* datastore_record, const struct if (journalstore_record->timestamp != datastore_record->timestamp) { // we need to update journalstore_record->timestamp = datastore_record->timestamp; - lmdb_journalstore_cursor_put(journalstore_cursor, journalstore_record); + retVal = lmdb_journalstore_cursor_put(journalstore_cursor, journalstore_record); lmdb_journalstore_cursor_close(journalstore_cursor, 0); lmdb_journal_record_free(journalstore_record); } diff --git a/repo/fsrepo/lmdb_journalstore.c b/repo/fsrepo/lmdb_journalstore.c index eaa29fa..7eba1f1 100644 --- a/repo/fsrepo/lmdb_journalstore.c +++ b/repo/fsrepo/lmdb_journalstore.c @@ -358,7 +358,24 @@ int lmdb_journalstore_cursor_put(struct lmdb_trans_cursor *crsr, struct JournalR libp2p_logger_error("lmdb_journalstore", "Unable to create journalstore record.\n"); return 0; } - if (mdb_cursor_put(cursor, &db_key, &db_value, 0) == 0) { + int retVal = mdb_cursor_put(cursor, &db_key, &db_value, 0); + if (retVal != 0) { + char* result = ""; + switch (retVal) { + case(MDB_MAP_FULL): + result = "Database Full"; + break; + case (MDB_TXN_FULL): + result = "Transaction has too many dirty pages"; + break; + case (EACCES) : + result = "Attempt was made to write in a read only transaction"; + break; + case (EINVAL) : + result = "An invalid parameter was specified"; + break; + } + libp2p_logger_error("lmdb_journalstore", "Put failed with error message %d [%s].\n", retVal, result); return 0; } diff --git a/test/Makefile b/test/Makefile index 6cfe7a7..b946c2b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -17,6 +17,7 @@ OBJS = testit.o test_helper.o \ ../multibase/multibase.o \ ../namesys/pb.o \ ../namesys/publisher.o \ + ../namesys/resolver.o \ ../repo/init.o \ ../repo/fsrepo/*.o \ ../repo/config/*.o \ diff --git a/test/namesys/test_namesys.h b/test/namesys/test_namesys.h new file mode 100644 index 0000000..cf2053d --- /dev/null +++ b/test/namesys/test_namesys.h @@ -0,0 +1,79 @@ +#include +#include + +#include "../test_helper.h" +#include "ipfs/cid/cid.h" +#include "ipfs/core/ipfs_node.h" +#include "ipfs/namesys/publisher.h" +#include "ipfs/namesys/resolver.h" + +int test_namesys_publisher_publish() { + int retVal = 0; + struct IpfsNode* local_node = NULL; + char* hash_text = "/ipns/QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; + char* repo_path = "/tmp/ipfs_1"; + + // get a local node + if (!ipfs_node_offline_new(repo_path, &local_node)) { + libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n"); + goto exit; + } + + // attempt to publish + if (!ipfs_namesys_publisher_publish(local_node, hash_text)) { + libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text); + goto exit; + } + + retVal = 1; + exit: + ipfs_node_free(NULL, local_node); + return retVal; +} + +int test_namesys_resolver_resolve() { + int retVal = 0; + struct IpfsNode* local_node = NULL; + char* hash_text = "QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; // the hash of a hello, world file + char ipns_path[512] = ""; // the Peer ID of config.test1 + char* repo_path = "/tmp/ipfs_1"; + char* peer_id = NULL; + char* result = NULL; + + drop_and_build_repository(repo_path, 4001, NULL, &peer_id); + + // get a local node + if (!ipfs_node_offline_new(repo_path, &local_node)) { + libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n"); + goto exit; + } + + // set ipns_path + sprintf(ipns_path, "/ipfs/%s", peer_id); + + // attempt to publish + if (!ipfs_namesys_publisher_publish(local_node, hash_text)) { + libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text); + goto exit; + } + + // attempt to retrieve + if (!ipfs_namesys_resolver_resolve(local_node, ipns_path, 1, &result)) { + libp2p_logger_error("test_namesys", "Could not resolve %s.\n", hash_text); + goto exit; + } + + if (strcmp(result, hash_text) != 0) { + libp2p_logger_error("test_namesys", "Retrieve wrong result. %s should be %s.\n", result, hash_text); + goto exit; + } + + libp2p_logger_error("test_namesys", "Asked for %s and received %s. Success!\n", ipns_path, result); + + retVal = 1; + exit: + ipfs_node_free(NULL, local_node); + if (result != NULL) + free(result); + return retVal; +} diff --git a/test/namesys/test_publisher.h b/test/namesys/test_publisher.h deleted file mode 100644 index 39d8e68..0000000 --- a/test/namesys/test_publisher.h +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#include "ipfs/cid/cid.h" -#include "ipfs/core/ipfs_node.h" -#include "ipfs/namesys/publisher.h" - -int test_namesys_publisher_publish() { - int retVal = 0; - struct IpfsNode* local_node = NULL; - struct Cid* cid = NULL; - char* hash_text = "QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; - char* repo_path = "/tmp/ipfs_1/.ipfs"; - pthread_t api_pth = 0; - - // get a local node - if (!ipfs_node_offline_new(repo_path, &local_node)) { - libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n"); - goto exit; - } - - // get a cid - if (!ipfs_cid_decode_hash_from_base58((unsigned char*)hash_text, strlen(hash_text), &cid)) { - libp2p_logger_error("test_publisher", "publish: Unable to convert hash from base58.\n"); - goto exit; - } - - // attempt to publish - if (!ipfs_namesys_publisher_publish(local_node, cid)) { - libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text); - goto exit; - } - - retVal = 1; - exit: - ipfs_node_free(&api_pth, local_node); - ipfs_cid_free(cid); - return retVal; -} diff --git a/test/testit.c b/test/testit.c index cfb6378..369140b 100644 --- a/test/testit.c +++ b/test/testit.c @@ -12,7 +12,6 @@ #include "flatfs/test_flatfs.h" #include "journal/test_journal.h" #include "merkledag/test_merkledag.h" -#include "namesys/test_publisher.h" #include "node/test_node.h" #include "node/test_importer.h" #include "node/test_resolver.h" @@ -27,6 +26,7 @@ #include "storage/test_blocks.h" #include "storage/test_unixfs.h" #include "libp2p/utils/logger.h" +#include "namesys/test_namesys.h" int testit(const char* name, int (*func)(void)) { printf("TESTING %s...\n", name); @@ -85,6 +85,7 @@ const char* names[] = { "test_merkledag_add_node", "test_merkledag_add_node_with_links", "test_namesys_publisher_publish", + "test_namesys_resolver_resolve", "test_resolver_get", "test_routing_find_peer", "test_routing_provide" /*, @@ -149,6 +150,7 @@ int (*funcs[])(void) = { test_merkledag_add_node, test_merkledag_add_node_with_links, test_namesys_publisher_publish, + test_namesys_resolver_resolve, test_resolver_get, test_routing_find_peer, test_routing_provide /*,