From 76b860c06f7955f47f0f0954b31a60a3be9654fb Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Wed, 27 Sep 2017 10:05:17 -0500 Subject: [PATCH] Attempting to bitswap from previously unknown node --- core/api.c | 58 ---------------------- core/http_request.c | 64 +++++++++++++++++++++++++ routing/offline.c | 35 +++++++++++++- test/routing/test_routing.h | 95 +++++++++++++++++++------------------ test/scripts/run_tests.sh | 1 + test/scripts/test_5.sh | 49 +++++++++++++++++++ test/testit.c | 11 +++-- 7 files changed, 203 insertions(+), 110 deletions(-) create mode 100755 test/scripts/test_5.sh diff --git a/core/api.c b/core/api.c index 7807108..00b2cdc 100644 --- a/core/api.c +++ b/core/api.c @@ -271,64 +271,6 @@ size_t boundary_size(char *str, char *boundary, size_t limit) return 0; } -/** - * function to find and read the object. - * @param path is the ipfs address, obj is a pointer to be allocated and will be the return of the data, size is a pointer to return the data length. - * @returns 1 when success is 0 when failure. - */ -int get_object(struct IpfsNode* local_node, char *path, unsigned char **obj, size_t *size) -{ - FILE* memstream_file = NULL; - char* memstream_char = NULL; - size_t memstream_size = 0; - struct Cid* cid = NULL; - - // convert hash to cid - if ( ipfs_cid_decode_hash_from_base58((unsigned char*)path, strlen(path), &cid) == 0) { - return 0; - } - - // find block - struct HashtableNode* read_node = NULL; - if (!ipfs_exporter_get_node(local_node, cid->hash, cid->hash_length, &read_node)) { - ipfs_cid_free(cid); - return 0; - } - - // open a memory stream - memstream_file = open_memstream(&memstream_char, &memstream_size); - if (memstream_file == NULL) { - libp2p_logger_error("api", "get_object: Unable to open a memory stream.\n"); - ipfs_cid_free(cid); - return 0; - } - - // throw everything (including links) into the memory stream - ipfs_exporter_cat_node(read_node, local_node, memstream_file); - - fclose(memstream_file); - - // no longer need these - ipfs_cid_free(cid); - ipfs_hashtable_node_free(read_node); - - *size = memstream_size; - *obj = (unsigned char*)memstream_char; - - return 1; -} - -/** - * send object data as an http response. - * @param socket, object pointer and size. - * @returns 1 when success is 0 when failure. - */ -int send_object(int socket, unsigned char *obj, size_t size) -{ - // TODO: implement. - return 0; // fail. -} - struct ApiConnectionParam { int index; struct IpfsNode* this_node; diff --git a/core/http_request.c b/core/http_request.c index f2cb18f..2686777 100644 --- a/core/http_request.c +++ b/core/http_request.c @@ -142,6 +142,68 @@ int ipfs_core_http_process_object(struct IpfsNode* local_node, struct HttpReques return retVal; } +/*** + * process dht commands + * @param local_node the context + * @param request the request + * @param response where to put the results + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_core_http_process_dht(struct IpfsNode* local_node, struct HttpRequest* request, char** response) { + int failedCount = 0; + if (strcmp(request->sub_command, "provide") == 0) { + // do a dht provide + for (int i = 0; i < request->arguments->total; i++) { + char* hash = (char*)libp2p_utils_vector_get(request->arguments, i); + struct Cid* cid; + if (!ipfs_cid_decode_hash_from_base58(hash, strlen(hash), &cid)) { + failedCount++; + continue; + } + if (!ipfs_routing_online_provide(local_node->routing, cid->hash, cid->hash_length)) { + failedCount++; + continue; + } + } + if (!failedCount) { + // complete success + // TODO: do the right thing + *response = (char*) malloc(1024); + snprintf(*response, 1024, "{\n\t\"ID\": \"\"\n" \ + "\t\"Type\": \"\"\n" + "\t\"Responses\": [\n" + "\t\t{\n" + "\t\t\t\"ID\": \"\"\n" + "\t\t\t\"Addrs\": [\n" + "\t\t\t\t\"\"\n" + "\t\t\t]\n" + "\t\t}\n" + "\t]\n" + "\t\"Extra\": \"\"\n" + "}\n" + ); + } else { + // at least some failed + // TODO: do the right thing + *response = (char*) malloc(1024); + snprintf(*response, 1024, "{\n\t\"ID\": \"\",\n" \ + "\t\"Type\": \"\",\n" + "\t\"Responses\": [\n" + "\t\t{\n" + "\t\t\t\"ID\": \"\",\n" + "\t\t\t\"Addrs\": [\n" + "\t\t\t\t\"\"\n" + "\t\t\t]\n" + "\t\t}\n" + "\t],\n" + "\t\"Extra\": \"\"\n" + "}\n" + ); + } + } + return failedCount < request->arguments->total; +} + /*** * Process the parameters passed in from an http request * @param local_node the context @@ -158,6 +220,8 @@ int ipfs_core_http_request_process(struct IpfsNode* local_node, struct HttpReque retVal = ipfs_core_http_process_name(local_node, request, response); } else if (strcmp(request->command, "object") == 0) { retVal = ipfs_core_http_process_object(local_node, request, response); + } else if (strcmp(request->command, "dht") == 0) { + retVal = ipfs_core_http_process_dht(local_node, request, response); } return retVal; } diff --git a/routing/offline.c b/routing/offline.c index 3ae8ab0..6207cc3 100644 --- a/routing/offline.c +++ b/routing/offline.c @@ -3,7 +3,9 @@ #include #include #include "libp2p/crypto/rsa.h" +#include "libp2p/utils/logger.h" #include "libp2p/record/record.h" +#include "ipfs/core/http_request.h" #include "ipfs/datastore/ds_helper.h" #include "ipfs/merkledag/merkledag.h" #include "ipfs/routing/routing.h" @@ -86,9 +88,38 @@ int ipfs_routing_offline_find_peer (ipfs_routing* offlineRouting, const unsigned return ErrOffline; } -int ipfs_routing_offline_provide (ipfs_routing* offlineRouting, const unsigned char *cid, size_t cid_size) +/** + * Attempt to publish that this node can provide a value + * @param offlineRouting the context + * @param incoming_hash the hash (in binary form) + * @param incoming_hash_size the length of the hash array + * @returns true(1) on success, false(0) otherwise + */ +int ipfs_routing_offline_provide (ipfs_routing* offlineRouting, const unsigned char *incoming_hash, size_t incoming_hash_size) { - return ErrOffline; + if (offlineRouting->local_node->mode == MODE_API_AVAILABLE) { + //TODO: publish this through the api + unsigned char buffer[256]; + if (!ipfs_cid_hash_to_base58(incoming_hash, incoming_hash_size, &buffer[0], 256)) { + libp2p_logger_error("offline", "Unable to convert hash to its Base58 representation.\n"); + return 0; + } + + char* response; + struct HttpRequest* request = ipfs_core_http_request_new(); + request->command = "dht"; + request->sub_command = "provide"; + request->arguments = libp2p_utils_vector_new(1); + libp2p_utils_vector_add(request->arguments, buffer); + if (!ipfs_core_http_request_get(offlineRouting->local_node, request, &response)) { + libp2p_logger_error("offline", "Unable to call API for dht publish.\n"); + return 0; + } + fprintf(stdout, "%s", response); + return 1; + } + + return 0; } int ipfs_routing_offline_ping (ipfs_routing* offlineRouting, struct Libp2pPeer* peer) diff --git a/test/routing/test_routing.h b/test/routing/test_routing.h index 7d284a6..7ed2eb7 100644 --- a/test/routing/test_routing.h +++ b/test/routing/test_routing.h @@ -448,8 +448,17 @@ int test_routing_provide() { */ int test_routing_retrieve_file_third_party() { int retVal = 0; + char* ipfs_path_1 = "/tmp/ipfs_1", *ipfs_path_2 = "/tmp/ipfs_2", *ipfs_path_3 = "/tmp/ipfs_3"; + char* peer_id_1 = NULL, *peer_id_2 = NULL, *peer_id_3 = NULL; + struct IpfsNode* ipfs_node2 = NULL, *ipfs_node3 = NULL; + pthread_t thread1, thread2, thread3; + int thread1_started = 0, thread2_started = 0, thread3_started = 0; + struct MultiAddress* ma_peer1 = NULL; + struct Libp2pVector* ma_vector2 = NULL, *ma_vector3 = NULL; + struct HashtableNode* node = NULL, *result_node = NULL; + char multiaddress_string[255] = ""; + char hash[256] = ""; - /* libp2p_logger_add_class("online"); libp2p_logger_add_class("multistream"); libp2p_logger_add_class("null"); @@ -459,88 +468,84 @@ int test_routing_retrieve_file_third_party() { libp2p_logger_add_class("exporter"); libp2p_logger_add_class("peer"); libp2p_logger_add_class("test_routing"); - */ // clean out repository - char* ipfs_path = "/tmp/test1"; - char* peer_id_1 = NULL, *peer_id_2 = NULL, *peer_id_3 = NULL; - struct IpfsNode* ipfs_node2 = NULL, *ipfs_node3 = NULL; - pthread_t thread1, thread2; - int thread1_started = 0, thread2_started = 0; - struct MultiAddress* ma_peer1 = NULL; - struct Libp2pVector* ma_vector2 = NULL, *ma_vector3 = NULL; - struct HashtableNode* node = NULL, *result_node = NULL; // create peer 1 - drop_and_build_repository(ipfs_path, 4001, NULL, &peer_id_1); - char multiaddress_string[255]; + if (!drop_and_build_repository(ipfs_path_1, 4001, NULL, &peer_id_1)) + goto exit; sprintf(multiaddress_string, "/ip4/127.0.0.1/tcp/4001/ipfs/%s", peer_id_1); ma_peer1 = multiaddress_new_from_string(multiaddress_string); // start the daemon in a separate thread libp2p_logger_debug("test_routing", "Firing up daemon 1.\n"); - if (pthread_create(&thread1, NULL, test_daemon_start, (void*)ipfs_path) < 0) { - fprintf(stderr, "Unable to start thread 1\n"); + if (pthread_create(&thread1, NULL, test_daemon_start, (void*)ipfs_path_1) < 0) { + libp2p_logger_error("test_routing", "Unable to start thread 1\n"); goto exit; } thread1_started = 1; // wait for everything to start up - // JMJ debugging = sleep(3); - // create peer 2 - ipfs_path = "/tmp/test2"; + // create peer 2, that will host the file // create a vector to hold peer1's multiaddress so we can connect as a peer ma_vector2 = libp2p_utils_vector_new(1); libp2p_utils_vector_add(ma_vector2, ma_peer1); - // note: this destroys some things, as it frees the fs_repo_3: - drop_and_build_repository(ipfs_path, 4002, ma_vector2, &peer_id_2); + // note: this destroys some things, as it frees the fs_repo: + drop_and_build_repository(ipfs_path_2, 4002, ma_vector2, &peer_id_2); multiaddress_free(ma_peer1); - // add a file, to prime the connection to peer 1 - //TODO: Find a better way to do this... - size_t bytes_written = 0; - if (!ipfs_node_online_new(ipfs_path, &ipfs_node2)) - goto exit; - ipfs_node2->routing->Bootstrap(ipfs_node2->routing); - ipfs_import_file(NULL, "/home/parallels/ipfstest/hello_world.txt", &node, ipfs_node2, &bytes_written, 0); - ipfs_node_free(ipfs_node2); // start the daemon in a separate thread libp2p_logger_debug("test_routing", "Firing up daemon 2.\n"); - if (pthread_create(&thread2, NULL, test_daemon_start, (void*)ipfs_path) < 0) { - fprintf(stderr, "Unable to start thread 2\n"); + if (pthread_create(&thread2, NULL, test_daemon_start, (void*)ipfs_path_2) < 0) { + libp2p_logger_error("test_routing", "Unable to start thread 2.\n"); goto exit; } thread2_started = 1; + //TODO: add a file to server 2 + uint8_t *bytes = (unsigned char*)"hello, world!\n"; + char* filename = "test1.txt"; + create_file(filename, bytes, strlen((char*)bytes)); + size_t bytes_written; + ipfs_node_offline_new(ipfs_path_2, &ipfs_node2); + ipfs_import_file(NULL, filename, &node, ipfs_node2, &bytes_written, 0); + memset(hash, 0, 256); + ipfs_cid_hash_to_base58(node->hash, node->hash_size, (unsigned char*)hash, 256); + libp2p_logger_debug("test_api", "Inserted file with hash %s.\n", hash); + ipfs_node_free(ipfs_node2); + // wait for everything to start up - // JMJ debugging = sleep(3); - libp2p_logger_debug("test_routing", "Firing up the 3rd client\n"); // create my peer, peer 3 - ipfs_path = "/tmp/test3"; ma_peer1 = multiaddress_new_from_string(multiaddress_string); ma_vector3 = libp2p_utils_vector_new(1); libp2p_utils_vector_add(ma_vector3, ma_peer1); - drop_and_build_repository(ipfs_path, 4003, ma_vector3, &peer_id_3); + drop_and_build_repository(ipfs_path_3, 4003, ma_vector3, &peer_id_3); multiaddress_free(ma_peer1); - ipfs_node_online_new(ipfs_path, &ipfs_node3); + libp2p_logger_debug("test_routing", "Firing up daemon 2.\n"); + if (pthread_create(&thread3, NULL, test_daemon_start, (void*)ipfs_path_3) < 0) { + libp2p_logger_error("test_routing", "Unable to start thread 3.\n"); + goto exit; + } + thread3_started = 1; - ipfs_node3->routing->Bootstrap(ipfs_node3->routing); + //now have peer 3 ask for a file that is on peer 2, but peer 3 only knows of peer 1 + ipfs_node_offline_new(ipfs_path_3, &ipfs_node3); if (!ipfs_exporter_get_node(ipfs_node3, node->hash, node->hash_size, &result_node)) { - fprintf(stderr, "Get_Node returned false\n"); - goto exit; + fprintf(stderr, "Get_Node returned false\n"); + goto exit; } if (node->hash_size != result_node->hash_size) { - fprintf(stderr, "Node hash sizes do not match. Should be %lu but is %lu\n", node->hash_size, result_node->hash_size); - goto exit; + fprintf(stderr, "Node hash sizes do not match. Should be %lu but is %lu\n", node->hash_size, result_node->hash_size); + goto exit; } if (node->data_size != result_node->data_size) { - fprintf(stderr, "Result sizes do not match. Should be %lu but is %lu\n", node->data_size, result_node->data_size); - goto exit; + fprintf(stderr, "Result sizes do not match. Should be %lu but is %lu\n", node->data_size, result_node->data_size); + goto exit; } retVal = 1; @@ -550,6 +555,8 @@ int test_routing_retrieve_file_third_party() { pthread_join(thread1, NULL); if (thread2_started) pthread_join(thread2, NULL); + if (thread3_started) + pthread_join(thread3, NULL); if (ipfs_node3 != NULL) ipfs_node_free(ipfs_node3); if (peer_id_1 != NULL) @@ -558,12 +565,10 @@ int test_routing_retrieve_file_third_party() { free(peer_id_2); if (peer_id_3 != NULL) free(peer_id_3); - if (ma_vector2 != NULL) { + if (ma_vector2 != NULL) libp2p_utils_vector_free(ma_vector2); - } - if (ma_vector3 != NULL) { + if (ma_vector3 != NULL) libp2p_utils_vector_free(ma_vector3); - } if (node != NULL) ipfs_hashtable_node_free(node); if (result_node != NULL) diff --git a/test/scripts/run_tests.sh b/test/scripts/run_tests.sh index a114a40..305c737 100755 --- a/test/scripts/run_tests.sh +++ b/test/scripts/run_tests.sh @@ -4,3 +4,4 @@ ./run_test.sh test_2.sh ./run_test.sh test_3.sh ./run_test.sh test_4.sh +./run_test.sh test_5.sh \ No newline at end of file diff --git a/test/scripts/test_5.sh b/test/scripts/test_5.sh new file mode 100755 index 0000000..291d3f3 --- /dev/null +++ b/test/scripts/test_5.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +#### +# Attempt to start 2 deamons and have an api client of server A ask for a file from server B +#### + +source ./test_helpers.sh + +IPFS1="../../main/ipfs --config /tmp/ipfs_1" +IPFS2="../../main/ipfs --config /tmp/ipfs_2" + +function pre { + post + eval "$IPFS1" init; + check_failure "pre" $? + cp ../config.test1.wo_journal /tmp/ipfs_1/config + + eval "$IPFS2" init; + check_failure "pre ipfs2" $? + cp ../config.test2.wo_journal /tmp/ipfs_2/config +} + +function post { + rm -Rf /tmp/ipfs_1; + rm -Rf /tmp/ipfs_2; + rm hello.txt; +} + +function body { + create_hello_world; + eval "$IPFS1" add hello.txt + check_failure "add hello.txt" $? + + #start the daemons + eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" + daemon_id_1=$! + eval "../../main/ipfs --config /tmp/ipfs_2 daemon &" + daemon_id_2=$! + sleep 5 + + #A client of server 2 wants the file at server 1 + eval "$IPFS2" cat QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH + check_failure "cat" $? + + kill -9 $daemon_id_1 + kill -9 $daemon_id_2 +} + + diff --git a/test/testit.c b/test/testit.c index c2f1580..2670168 100644 --- a/test/testit.c +++ b/test/testit.c @@ -88,23 +88,24 @@ const char* names[] = { "test_merkledag_get_data", "test_merkledag_add_node", "test_merkledag_add_node_with_links", + // 50 below "test_namesys_publisher_publish", "test_namesys_resolver_resolve", "test_resolver_get", "test_routing_find_peer", - "test_routing_provide" /*, + "test_routing_provide", "test_routing_find_providers", "test_routing_supernode_get_value", "test_routing_supernode_get_remote_value", "test_routing_retrieve_file_third_party", "test_routing_retrieve_large_file", + // 60 below "test_unixfs_encode_decode", "test_unixfs_encode_smallfile", "test_ping", "test_ping_remote", "test_null_add_provider", "test_resolver_remote_get" - */ }; int (*funcs[])(void) = { @@ -157,24 +158,24 @@ int (*funcs[])(void) = { test_merkledag_get_data, test_merkledag_add_node, test_merkledag_add_node_with_links, + // 50 below test_namesys_publisher_publish, test_namesys_resolver_resolve, test_resolver_get, test_routing_find_peer, - test_routing_provide /*, - test_routing_find_providers, test_routing_provide, + test_routing_find_providers, test_routing_supernode_get_value, test_routing_supernode_get_remote_value, test_routing_retrieve_file_third_party, test_routing_retrieve_large_file, + // 60 below test_unixfs_encode_decode, test_unixfs_encode_smallfile, test_ping, test_ping_remote, test_null_add_provider, test_resolver_remote_get - */ }; /**