From 5bcd3a99f25ca2be1123de7dcf8267a310240677 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 25 Sep 2017 17:56:10 -0500 Subject: [PATCH] various fixes for object_get --- core/api.c | 36 +++++++++++++------------ core/http_request.c | 18 ++++++++++++- importer/exporter.c | 46 +++++++++++++++++++++++--------- include/ipfs/importer/exporter.h | 3 ++- main/main.c | 2 +- merkledag/node.c | 12 ++++++--- test/core/test_api.h | 17 ++++++++---- unixfs/unixfs.c | 3 ++- 8 files changed, 96 insertions(+), 41 deletions(-) diff --git a/core/api.c b/core/api.c index 083dd45..7807108 100644 --- a/core/api.c +++ b/core/api.c @@ -566,25 +566,27 @@ void *api_connection_thread (void *ptr) char* response_text = NULL; if (!ipfs_core_http_request_process(params->this_node, http_request, &response_text)) { libp2p_logger_error("api", "ipfs_core_http_request_process returned false.\n"); - // TODO: Handle this condition + // 404 + write_str(s, HTTP_404); + } else { + // now send the results + snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \ + "Content-Type: application/json\r\n" + "Server: c-ipfs/0.0.0-dev\r\n" + "X-Chunked-Output: 1\r\n" + "Connection: close\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "%x\r\n" + "%s\r\n" + "0\r\n\r\n" + ,req.buf + req.http_ver, strlen(response_text), response_text); + if (response_text != NULL) + free(response_text); + write_str (s, resp); + libp2p_logger_debug("api", "resp = {\n%s\n}\n", resp); } ipfs_core_http_request_free(http_request); - // now send the results - snprintf(resp, sizeof(resp), "%s 200 OK\r\n" \ - "Content-Type: application/json\r\n" - "Server: c-ipfs/0.0.0-dev\r\n" - "X-Chunked-Output: 1\r\n" - "Connection: close\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "%x\r\n" - "%s\r\n" - "0\r\n\r\n" - ,req.buf + req.http_ver, strlen(response_text), response_text); - if (response_text != NULL) - free(response_text); - write_str (s, resp); - libp2p_logger_debug("api", "resp = {\n%s\n}\n", resp); } else { // uh oh... something went wrong converting to the HttpRequest struct libp2p_logger_error("api", "Unable to build HttpRequest struct.\n"); diff --git a/core/http_request.c b/core/http_request.c index ec45332..f2cb18f 100644 --- a/core/http_request.c +++ b/core/http_request.c @@ -1,9 +1,12 @@ #include #include #include +#include "libp2p/os/memstream.h" #include "libp2p/utils/vector.h" #include "libp2p/utils/logger.h" +#include "ipfs/cid/cid.h" #include "ipfs/core/http_request.h" +#include "ipfs/importer/exporter.h" #include "ipfs/namesys/resolver.h" #include "ipfs/namesys/publisher.h" @@ -125,6 +128,16 @@ int ipfs_core_http_process_object(struct IpfsNode* local_node, struct HttpReques int retVal = 0; if (strcmp(request->sub_command, "get") == 0) { // do an object_get + if (request->arguments->total == 1) { + char* hash = (char*)libp2p_utils_vector_get(request->arguments, 0); + struct Cid* cid; + ipfs_cid_decode_hash_from_base58(hash, strlen(hash), &cid); + size_t size; + FILE* response_file = open_memstream(response, &size); + retVal = ipfs_exporter_object_cat_to_file(local_node, cid->hash, cid->hash_length, response_file); + ipfs_cid_free(cid); + fclose(response_file); + } } return retVal; } @@ -297,7 +310,10 @@ int ipfs_core_http_request_get(struct IpfsNode* local_node, struct HttpRequest* res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res == CURLE_OK) { - *result = s.ptr; + if (strcmp(s.ptr, "404 page not found") != 0) + *result = s.ptr; + else + res = -1; } else { libp2p_logger_error("http_request", "Results of [%s] returned failure. Return value: %d.\n", url, res); } diff --git a/importer/exporter.c b/importer/exporter.c index 8d5d4b9..c4b633a 100644 --- a/importer/exporter.c +++ b/importer/exporter.c @@ -3,6 +3,8 @@ #include #include "ipfs/cid/cid.h" +#include "ipfs/core/http_request.h" +#include "ipfs/importer/exporter.h" #include "ipfs/merkledag/merkledag.h" #include "ipfs/merkledag/node.h" #include "ipfs/repo/fsrepo/fs_repo.h" @@ -32,8 +34,9 @@ int ipfs_exporter_get_node(struct IpfsNode* local_node, const unsigned char* has if (local_node->routing->GetValue(local_node->routing, hash, hash_size, (void**)&buffer, &buffer_size)) { libp2p_logger_debug("exporter", "get_node got a value. Converting it to a HashtableNode\n"); // unprotobuf - if (ipfs_hashtable_node_protobuf_decode(buffer, buffer_size, result)) { - libp2p_logger_debug("exporter", "Conversion to HashtableNode successful\n"); + if (!ipfs_hashtable_node_protobuf_decode(buffer, buffer_size, result)) { + libp2p_logger_debug("exporter", "Conversion to HashtableNode not successful\n"); + goto exit; } } else { libp2p_logger_debug("exporter", "get_node got no value. Returning false.\n"); @@ -221,7 +224,9 @@ int ipfs_exporter_cat_node(struct HashtableNode* node, struct IpfsNode* local_no // build the unixfs struct UnixFS* unix_fs; - ipfs_unixfs_protobuf_decode(node->data, node->data_size, &unix_fs); + if (!ipfs_unixfs_protobuf_decode(node->data, node->data_size, &unix_fs)) { + return 0; + } for(size_t i = 0LU; i < unix_fs->bytes_size; i++) { fprintf(file, "%c", unix_fs->bytes[i]); } @@ -262,26 +267,43 @@ int ipfs_exporter_object_cat_to_file(struct IpfsNode *local_node, unsigned char* * @param argv arguments * @returns true(1) on success */ -int ipfs_exporter_object_cat(int argc, char** argv) { +int ipfs_exporter_object_cat(struct CliArguments* args) { struct IpfsNode *local_node = NULL; char* repo_dir = NULL; - if (!ipfs_repo_get_directory(argc, argv, &repo_dir)) { - fprintf(stderr, "Unable to open repo: %s\n", repo_dir); + if (!ipfs_repo_get_directory(args->argc, args->argv, &repo_dir)) { + libp2p_logger_error("exporter", "Unable to open repo: %s\n", repo_dir); return 0; } - if (!ipfs_node_offline_new(repo_dir, &local_node)) + if (!ipfs_node_offline_new(repo_dir, &local_node)) { + libp2p_logger_error("exporter", "Unable to create new offline node based on config at %s.\n", repo_dir); return 0; + } if (local_node->mode == MODE_API_AVAILABLE) { - // TODO: we should use the api for this - return 0; + char* hash = args->argv[args->verb_index + 1]; + libp2p_logger_debug("exporter", "We're attempting to use the API for this object get of %s.\n", hash); + struct HttpRequest* request = ipfs_core_http_request_new(); + char* response = NULL; + request->command = "object"; + request->sub_command = "get"; + request->arguments = libp2p_utils_vector_new(1); + libp2p_utils_vector_add(request->arguments, hash); + int retVal = ipfs_core_http_request_get(local_node, request, &response); + if (response != NULL && strlen(response) > 0) { + fprintf(stdout, "%s", response); + free(response); + } else { + retVal = 0; + } + ipfs_core_http_request_free(request); + return retVal; } else { - // find hash - // convert hash to cid + libp2p_logger_debug("exporter", "API not available, using direct access.\n"); struct Cid* cid = NULL; - if ( ipfs_cid_decode_hash_from_base58((unsigned char*)argv[2], strlen(argv[2]), &cid) == 0) { + if ( ipfs_cid_decode_hash_from_base58((unsigned char*)args->argv[args->verb_index+1], strlen(args->argv[args->verb_index+1]), &cid) == 0) { + libp2p_logger_error("exporter", "Unable to decode hash from base58 [%s]\n", args->argv[args->verb_index+1]); return 0; } diff --git a/include/ipfs/importer/exporter.h b/include/ipfs/importer/exporter.h index 8dfe4b2..3827c66 100644 --- a/include/ipfs/importer/exporter.h +++ b/include/ipfs/importer/exporter.h @@ -1,5 +1,6 @@ #pragma once +#include "ipfs/cmd/cli.h" #include "ipfs/core/ipfs_node.h" /** @@ -32,7 +33,7 @@ int ipfs_exporter_object_get(int argc, char** argv); * @param argv arguments * @returns true(1) on success */ -int ipfs_exporter_object_cat(int argc, char** argv); +int ipfs_exporter_object_cat(struct CliArguments* args); /** * Retrieves the object pointed to by hash and displays the raw data diff --git a/main/main.c b/main/main.c index cf4fa79..c6641ab 100644 --- a/main/main.c +++ b/main/main.c @@ -171,7 +171,7 @@ int main(int argc, char** argv) { //ipfs_exporter_get(argc, argv); //break; case (CAT): - ipfs_exporter_object_cat(argc, argv); + ipfs_exporter_object_cat(args); break; case (DNS): ipfs_dns(argc, argv); diff --git a/merkledag/node.c b/merkledag/node.c index d0eb697..f4ff9ff 100644 --- a/merkledag/node.c +++ b/merkledag/node.c @@ -187,6 +187,9 @@ int ipfs_node_link_protobuf_decode(unsigned char* buffer, size_t buffer_length, unsigned char* hash; if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&hash, &hash_size, &bytes_read) == 0) goto exit; + if (hash_size < 2) { + goto exit; + } link->hash_size = hash_size - 2; link->hash = (unsigned char*)malloc(link->hash_size); memcpy((char*)link->hash, (char*)&hash[2], link->hash_size); @@ -293,6 +296,9 @@ int ipfs_hashtable_node_protobuf_decode(unsigned char* buffer, size_t buffer_len size_t temp_size; struct NodeLink* temp_link = NULL; + if (buffer_length == 0) + goto exit; + if (ipfs_hashtable_node_new(node) == 0) goto exit; @@ -315,11 +321,11 @@ int ipfs_hashtable_node_protobuf_decode(unsigned char* buffer, size_t buffer_len if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&temp_buffer, &temp_size, &bytes_read) == 0) goto exit; pos += bytes_read; - if (ipfs_node_link_protobuf_decode(temp_buffer, temp_size, &temp_link) == 0) - goto exit; + if (ipfs_node_link_protobuf_decode(temp_buffer, temp_size, &temp_link)) { + ipfs_hashtable_node_add_link(*node, temp_link); + } free(temp_buffer); temp_buffer = NULL; - ipfs_hashtable_node_add_link(*node, temp_link); break; } } diff --git a/test/core/test_api.h b/test/core/test_api.h index 824e7fb..854bad6 100644 --- a/test/core/test_api.h +++ b/test/core/test_api.h @@ -2,6 +2,7 @@ #include "../test_helper.h" #include "libp2p/utils/logger.h" +#include "ipfs/cmd/cli.h" #include "ipfs/core/client_api.h" #include "ipfs/core/daemon.h" #include "ipfs/importer/exporter.h" @@ -56,15 +57,15 @@ int test_core_api_object_cat() { int thread_started1 = 0; int thread_started2 = 0; char* ipfs_path1 = "/tmp/ipfs_1"; - char* config_file1 = "config.test1"; + char* config_file1 = "config.test1.wo_journal"; char* ipfs_path2 = "/tmp/ipfs_2"; - char* config_file2 = "config.test2"; + char* config_file2 = "config.test2.wo_journal"; struct FSRepo* fs_repo = NULL; char hash[256] = ""; char* args[] = {"ipfs", "--config", ipfs_path2, "cat", hash }; // logging - libp2p_logger_add_class("test_journal"); + libp2p_logger_add_class("test_api"); libp2p_logger_add_class("journal"); libp2p_logger_add_class("daemon"); libp2p_logger_add_class("online"); @@ -82,6 +83,7 @@ int test_core_api_object_cat() { libp2p_logger_add_class("unixfs"); libp2p_logger_add_class("bitswap_engine"); libp2p_logger_add_class("bitswap_network"); + libp2p_logger_add_class("exporter"); // build 2 repos if (!drop_build_open_repo(ipfs_path1, &fs_repo, config_file1)) { @@ -99,7 +101,7 @@ int test_core_api_object_cat() { libp2p_logger_debug("test_api", "Changed the server id to %s.\n", fs_repo->config->identity->peer->id); ipfs_repo_fsrepo_free(fs_repo); - // add some files to the first repo + // add a file to the first repo uint8_t *bytes = (unsigned char*)"hello, world!\n"; char* filename = "test1.txt"; create_file(filename, bytes, strlen((char*)bytes)); @@ -110,19 +112,23 @@ int test_core_api_object_cat() { ipfs_import_file(NULL, filename, &node, local_node, &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(local_node); ipfs_hashtable_node_free(node); libp2p_logger_debug("test_api", "*** Firing up daemons ***\n"); pthread_create(&daemon_thread1, NULL, test_daemon_start, (void*)ipfs_path1); thread_started1 = 1; + sleep(3); pthread_create(&daemon_thread2, NULL, test_daemon_start, (void*)ipfs_path2); thread_started2 = 1; sleep(3); // use a client to ask for the file on server 1 - if (ipfs_exporter_object_cat(5, args) == 0) { + struct CliArguments* arguments = cli_arguments_new(5, args); + if (ipfs_exporter_object_cat(arguments) == 0) { + libp2p_logger_error("test_api", "ipfs_exporter_object_cat returned false.\n"); goto exit; } @@ -133,6 +139,7 @@ int test_core_api_object_cat() { pthread_join(daemon_thread1, NULL); if (thread_started2) pthread_join(daemon_thread2, NULL); + cli_arguments_free(arguments); return retVal; } diff --git a/unixfs/unixfs.c b/unixfs/unixfs.c index b8424b4..e0d9a31 100644 --- a/unixfs/unixfs.c +++ b/unixfs/unixfs.c @@ -249,12 +249,13 @@ int ipfs_unixfs_protobuf_encode(const struct UnixFS* incoming, unsigned char* ou * @param incoming the array of bytes * @param incoming_size the length of the array * @param outgoing the UnixFS object + * @returns true(1) on success, false(0) on error */ int ipfs_unixfs_protobuf_decode(unsigned char* incoming, size_t incoming_size, struct UnixFS** outgoing) { // short cut for nulls if (incoming_size == 0) { *outgoing = NULL; - return 1; + return 0; } size_t pos = 0;