diff --git a/core/daemon.c b/core/daemon.c index ff7cd00..c0a00ad 100644 --- a/core/daemon.c +++ b/core/daemon.c @@ -47,8 +47,8 @@ int ipfs_daemon_start(char* repo_path) { return 1; } + ipfs_bootstrap_routing(&local_node); /* - //ipfs_bootstrap_routing(&local_node); if (pthread_create(&work_pths[count_pths++], NULL, ipfs_bootstrap_routing, &local_node)) { fprintf(stderr, "Error creating thread for routing\n"); } diff --git a/core/null.c b/core/null.c index 73d4aa9..6f42253 100644 --- a/core/null.c +++ b/core/null.c @@ -38,11 +38,9 @@ int protocol_compare(unsigned char* incoming, size_t incoming_size, const char* void *ipfs_null_connection (void *ptr) { struct null_connection_params *connection_param = NULL; - //struct s_ipfs_routing* routing = NULL; connection_param = (struct null_connection_params*) ptr; - // TODO: multistream + secio + message. // TODO: when should we exit the for loop and disconnect? struct SessionContext session; @@ -52,7 +50,6 @@ void *ipfs_null_connection (void *ptr) fprintf(stderr, "Connection %d, count %d\n", connection_param->socket, *(connection_param->count)); if (libp2p_net_multistream_negotiate(session.insecure_stream)) { - //routing = ipfs_routing_new_online(connection_param->local_node, &connection_param->local_node->identity->private_key, session.insecure_stream); for(;;) { // check if they're looking for an upgrade (i.e. secio) @@ -103,49 +100,9 @@ void *ipfs_null_connection (void *ptr) else { // oops there was a problem //TODO: Handle this - /* - struct Libp2pMessage* msg = NULL; - libp2p_message_protobuf_decode(results, bytes_read, &msg); - if (msg != NULL) { - switch(msg->message_type) { - case (MESSAGE_TYPE_PING): - routing->Ping(routing, msg); - break; - case (MESSAGE_TYPE_GET_VALUE): { - unsigned char* val; - size_t val_size = 0; - routing->GetValue(routing, msg->key, msg->key_size, (void**)&val, &val_size); - if (val == NULL) { - // write a 0 to the stream to tell the client we couldn't find it. - session.default_stream->write(&session, 0, 1); - } else { - session.default_stream->write(&session, val, val_size); - } - break; - } - default: - break; - } - } else { - break; - } - */ } } } - /* - len = socket_read(connection_param->socket, b, sizeof(b)-1, 0); - if (len > 0) { - while (b[len-1] == '\r' || b[len-1] == '\n') len--; - b[len] = '\0'; - fprintf(stderr, "Recv: '%s'\n", b); - if (strcmp (b, "ping") == 0) { - socket_write(connection_param->socket, "pong", 4, 0); - } - } else if(len < 0) { - break; - } - */ if (session.default_stream != NULL) { session.default_stream->close(&session); diff --git a/core/ping.c b/core/ping.c index 4daa974..f75d86b 100644 --- a/core/ping.c +++ b/core/ping.c @@ -9,6 +9,10 @@ #include "libp2p/record/message.h" #include "libp2p/secio/secio.h" #include "ipfs/repo/fsrepo/fs_repo.h" +#include "ipfs/core/ipfs_node.h" +#include "ipfs/routing/routing.h" +#include "ipfs/importer/resolver.h" +#include "multiaddr/multiaddr.h" #define BUF_SIZE 4096 @@ -19,32 +23,78 @@ int ipfs_ping (int argc, char **argv) int port = 0; char* ip = NULL; struct SessionContext session; + struct MultiAddress* address; + int addressAllocated = 0; + int retVal = 0; + struct Libp2pMessage *msg = NULL, *msg_returned = NULL; + struct IpfsNode local_node; + unsigned char* protobuf = NULL; + size_t protobuf_size = 0; + struct Stream* stream = NULL; + + // sanity check + if (argc < 3) + return 0; // read the configuration struct FSRepo* fs_repo; if (!ipfs_repo_fsrepo_new(NULL, NULL, &fs_repo)) - return 0; + goto exit; // open the repository and read the file - if (!ipfs_repo_fsrepo_open(fs_repo)) { - ipfs_repo_fsrepo_free(fs_repo); - return 0; + if (!ipfs_repo_fsrepo_open(fs_repo)) + goto exit; + + local_node.identity = fs_repo->config->identity; + local_node.repo = fs_repo; + local_node.mode = MODE_ONLINE; + local_node.routing = ipfs_routing_new_online(&local_node, &fs_repo->config->identity->private_key, stream); + local_node.peerstore = libp2p_peerstore_new(); + local_node.providerstore = libp2p_providerstore_new(); + + if (local_node.routing->Bootstrap(local_node.routing) != 0) + goto exit; + + if (strstr(argv[2], "/ipfs/") != NULL) { + // resolve the peer id + struct Libp2pPeer *peer = ipfs_resolver_find_peer(argv[2], &local_node); + struct Libp2pLinkedList* current = peer->addr_head; + // try to find an IP version of the multiaddress + while (current != NULL) { + address = (struct MultiAddress*)current->item; + if (multiaddress_is_ip(address)) + break; + address = NULL; + } + } else { + // perhaps they passed an IP and port + if (argc >= 3) { + char* str = malloc(strlen(argv[2]) + strlen(argv[3]) + 100); + sprintf(str, "/ip4/%s/tcp/%s", argv[2], argv[3]); + address = multiaddress_new_from_string(str); + free(str); + if (address != NULL) + addressAllocated = 1; + } + //TODO: Error checking } - //TODO: handle multiaddress - if (strstr(argv[2], "/ipfs/") != NULL) { - // look in peerstore - } else { - // the way using multistream - //TODO: Error checking - ip = argv[2]; - port = atoi(argv[3]); + if (address == NULL || !multiaddress_is_ip(address)) { + fprintf(stderr, "Unable to find address\n"); + goto exit; } + if (!multiaddress_get_ip_address(address, &ip)) { + fprintf(stderr, "Could not convert IP address %s\n", address->string); + goto exit; + } + port = multiaddress_get_ip_port(address); + session.insecure_stream = libp2p_net_multistream_connect(ip, port); session.default_stream = session.insecure_stream; if (session.insecure_stream == NULL) { - fprintf(stderr, "Unable to connect to %s on port %s", ip, argv[3]); + fprintf(stderr, "Unable to connect to %s on port %d", ip, port); + goto exit; } // try to switch to secio @@ -53,90 +103,48 @@ int ipfs_ping (int argc, char **argv) } // prepare the PING message - struct Libp2pMessage* msg = libp2p_message_new(); + msg = libp2p_message_new(); msg->message_type = MESSAGE_TYPE_PING; - size_t protobuf_size = libp2p_message_protobuf_encode_size(msg); - unsigned char protobuf[protobuf_size]; + protobuf_size = libp2p_message_protobuf_encode_size(msg); + protobuf = (unsigned char*)malloc(protobuf_size); libp2p_message_protobuf_encode(msg, &protobuf[0], protobuf_size, &protobuf_size); session.default_stream->write(&session, protobuf, protobuf_size); session.default_stream->read(&session, &results, &results_size); // see if we can unprotobuf - struct Libp2pMessage* msg_returned = NULL; libp2p_message_protobuf_decode(results, results_size, &msg_returned); if (msg_returned->message_type != MESSAGE_TYPE_PING) { fprintf(stderr, "Ping unsuccessful. Returned message was not a PING"); - return 0; + goto exit; } if (results_size != protobuf_size) { fprintf(stderr, "PING unsuccessful. Original size: %lu, returned size: %lu\n", protobuf_size, results_size); - return 0; + goto exit; } if (memcmp(results, protobuf, protobuf_size) != 0) { fprintf(stderr, "PING unsuccessful. Results do not match.\n"); - return 0; + goto exit; } + fprintf(stdout, "Ping of %s:%d successful.\n", ip, port); + + retVal = 1; + exit: + if (fs_repo != NULL) + ipfs_repo_fsrepo_free(fs_repo); + if (addressAllocated) + multiaddress_free(address); + if (ip != NULL) + free(ip); if (msg != NULL) libp2p_message_free(msg); + if (msg_returned != NULL) + libp2p_message_free(msg_returned); + if (protobuf != NULL) + free(protobuf); - fprintf(stdout, "Ping of %s:%s successful.\n", ip, argv[3]); + return retVal; - return 0; - - // the old way - /* - int socketfd, i, count=10, tcount = 0; - uint32_t ipv4; - uint16_t port; - char b[BUF_SIZE]; - size_t len; - struct timeval time; - long cur_time, old_time; - double ms, total = 0; - - if (inet_pton (AF_INET, argv[2], &ipv4) == 0) { - fprintf(stderr, "Unable to use '%s' as an IP address.\n", argv[1]); - return 1; - } - - if ((port = atoi(argv[3])) == 0) { - fprintf(stderr, "Unable to use '%s' port.\n", argv[2]); - return 1; - } - - if ((socketfd = socket_tcp4()) <= 0) { - perror("can't create socket"); - return 1; - } - - if (socket_connect4(socketfd, ipv4, port) < 0) { - perror("fail to connect"); - return 1; - } - - fprintf(stderr, "PING %s.\n", argv[2]); - - for (i=0 ; i < count ; i++) { - if (gettimeofday (&time, 0)) return -1; - old_time = 1000000 * time.tv_sec + time.tv_usec; - - socket_write(socketfd, "ping", 4, 0); - len = socket_read(socketfd, b, sizeof(b), 0); - - if (len == 4 && memcmp(b, "pong", 4) == 0) { - if (gettimeofday (&time, 0)) return -1; - cur_time = 1000000 * time.tv_sec + time.tv_usec; - ms = (cur_time - old_time) / 1000.0; - total += ms; tcount++; - fprintf(stderr, "Pong received: time=%.2f ms\n", ms); - } - sleep (1); - } - fprintf(stderr, "Average latency: %.2fms\n", total / tcount); - - return 0; - */ } diff --git a/importer/resolver.c b/importer/resolver.c index e35a71c..36273e3 100644 --- a/importer/resolver.c +++ b/importer/resolver.c @@ -10,6 +10,7 @@ #include "libp2p/net/multistream.h" #include "libp2p/record/message.h" #include "multiaddr/multiaddr.h" +#include "libp2p/record/message.h" /** * return the next chunk of a path @@ -122,8 +123,10 @@ struct Node* ipfs_resolver_remote_get(const char* path, struct Node* from, const pos[0] = '\0'; // get the multiaddress for this struct Libp2pPeer* peer = libp2p_peerstore_get_peer(ipfs_node->peerstore, (unsigned char*)id, id_size); - if (peer == NULL) + if (peer == NULL) { + //TODO: We don't have the peer address. Ask the swarm for the data related to the hash return NULL; + } // connect to the peer struct MultiAddress* address = peer->addr_head->item; char* ip; @@ -254,3 +257,55 @@ struct Node* ipfs_resolver_get(const char* path, struct Node* from, const struct ipfs_node_free(from); return NULL; } + +/** + * Interrogate the path, looking for the peer. + * NOTE: only called locally. Not for remote callers + * @param path the peer path to search for in the form like "/ipfs/QmKioji..." + * @param ipfs_node the context + * @returns a peer struct, or NULL if not found + */ +struct Libp2pPeer* ipfs_resolver_find_peer(const char* path, const struct IpfsNode* ipfs_node) { + struct FSRepo* fs_repo = ipfs_node->repo; + unsigned char* results = NULL; + size_t results_size = 0; + struct Libp2pLinkedList *addresses = NULL; + struct Libp2pPeer* peer = NULL; + + // shortcut for if this node is the node we're looking for + if (!ipfs_resolver_is_remote(path, fs_repo)) { + // turn the string list into a multiaddress list + struct Libp2pLinkedList* current_list_string = fs_repo->config->addresses->swarm_head; + struct Libp2pLinkedList* current_list_ma = addresses; + while(current_list_string != NULL) { + struct Libp2pLinkedList* item = libp2p_utils_linked_list_new(); + item->item = multiaddress_new_from_string(current_list_string->item); + if (addresses == NULL) { + addresses = item; + } else { + current_list_ma->next = item; + } + current_list_ma = item; + current_list_string = current_list_string->next; + } + } + + // ask the swarm for the peer + const char* address_string = ipfs_resolver_remove_path_prefix(path, fs_repo); + if (ipfs_node->routing->FindPeer(ipfs_node->routing, address_string, strlen(address_string), (void**)&results, &results_size) != 0) + goto exit; + + // we should have gotten a protobuf'd peer + if (!libp2p_peer_protobuf_decode(results, results_size, &peer)) + goto exit; + + if (peer == NULL) + goto exit; + + + exit: + if (results != NULL) + free(results); + return peer; +} + diff --git a/include/ipfs/core/ipfs_node.h b/include/ipfs/core/ipfs_node.h index 6255234..ece1e5e 100644 --- a/include/ipfs/core/ipfs_node.h +++ b/include/ipfs/core/ipfs_node.h @@ -2,6 +2,7 @@ #include "ipfs/repo/config/identity.h" #include "ipfs/repo/fsrepo/fs_repo.h" +#include "ipfs/routing/routing.h" #include "libp2p/peer/peerstore.h" #include "libp2p/peer/providerstore.h" @@ -13,7 +14,7 @@ struct IpfsNode { struct FSRepo* repo; struct Peerstore* peerstore; struct ProviderStore* providerstore; - struct s_ipfs_routing* routing; + struct IpfsRouting* routing; //struct Pinner pinning; // an interface //struct Mount** mounts; // TODO: Add more here diff --git a/include/ipfs/importer/resolver.h b/include/ipfs/importer/resolver.h index 0411dba..1c7d568 100644 --- a/include/ipfs/importer/resolver.h +++ b/include/ipfs/importer/resolver.h @@ -3,6 +3,10 @@ #include "ipfs/merkledag/node.h" #include "ipfs/core/ipfs_node.h" +/** + * Implements a resover. EOM + */ + /** * Interogate the path and the current node, looking * for the desired node. @@ -11,3 +15,11 @@ * @returns what we are looking for, or NULL if it wasn't found */ struct Node* ipfs_resolver_get(const char* path, struct Node* from, const struct IpfsNode* ipfs_node); + +/** + * Interrogate the path, looking for the peer + * @param path the peer path to search for + * @param ipfs_node the context + * @returns the MultiAddress that relates to the path, or NULL if not found + */ +struct Libp2pPeer* ipfs_resolver_find_peer(const char* path, const struct IpfsNode* ipfs_node); diff --git a/include/ipfs/repo/config/addresses.h b/include/ipfs/repo/config/addresses.h index 58d83a3..abc5c0b 100644 --- a/include/ipfs/repo/config/addresses.h +++ b/include/ipfs/repo/config/addresses.h @@ -5,8 +5,11 @@ #include "swarm.h" struct Addresses { + // list of strings in format "/family/address/type/port" struct Libp2pLinkedList* swarm_head; + // info for api connection char* api; + // info for http gateway char* gateway; }; diff --git a/include/ipfs/routing/routing.h b/include/ipfs/routing/routing.h index cf848bc..527a422 100644 --- a/include/ipfs/routing/routing.h +++ b/include/ipfs/routing/routing.h @@ -7,7 +7,7 @@ // offlineRouting implements the IpfsRouting interface, // but only provides the capability to Put and Get signed dht // records to and from the local datastore. -struct s_ipfs_routing { +struct IpfsRouting { struct IpfsNode* local_node; size_t ds_len; struct RsaPrivateKey* sk; @@ -22,7 +22,7 @@ struct s_ipfs_routing { * @param 5 the size of the value * @returns 0 on success, otherwise -1 */ - int (*PutValue) (struct s_ipfs_routing*, char*, size_t, void*, size_t); + int (*PutValue) (struct IpfsRouting*, char*, size_t, void*, size_t); /** * Get a value from the datastore * @param 1 the struct that contains the connection information @@ -31,7 +31,7 @@ struct s_ipfs_routing { * @param 4 a place to store the value * @param 5 the size of the value */ - int (*GetValue) (struct s_ipfs_routing*, char*, size_t, void**, size_t*); + int (*GetValue) (struct IpfsRouting*, char*, size_t, void**, size_t*); /** * Find a provider * @param 1 the context @@ -40,7 +40,7 @@ struct s_ipfs_routing { * @param 4 the information found * @param 5 the size of the information found */ - int (*FindProviders) (struct s_ipfs_routing*, char*, size_t, struct Libp2pVector** multiaddresses); + int (*FindProviders) (struct IpfsRouting*, char*, size_t, struct Libp2pVector** multiaddresses); /** * Find a peer * @param 1 the context @@ -48,8 +48,9 @@ struct s_ipfs_routing { * @param 3 the size of the peer char array * @param 4 the results * @param 5 the size of the results + * @returns 0 or error code */ - int (*FindPeer) (struct s_ipfs_routing*, char*, size_t, void*, size_t*); + int (*FindPeer) (struct IpfsRouting*, const char*, size_t, void**, size_t*); /** * Announce to the network that this host can provide this key * @param 1 the context @@ -57,22 +58,22 @@ struct s_ipfs_routing { * @param 3 the key size * @returns true(1) on success, otherwise false(0) */ - int (*Provide) (struct s_ipfs_routing*, char*, size_t); + int (*Provide) (struct IpfsRouting*, char*, size_t); /** * Ping * @param routing the context * @param message the message * @returns true(1) on success, otherwise false(0) */ - int (*Ping) (struct s_ipfs_routing*, struct Libp2pMessage*); + int (*Ping) (struct IpfsRouting*, struct Libp2pMessage*); /** * Get everything going * @param routing the context * @returns true(1) on success, otherwise false(0) */ - int (*Bootstrap) (struct s_ipfs_routing*); + int (*Bootstrap) (struct IpfsRouting*); }; -typedef struct s_ipfs_routing ipfs_routing; +typedef struct IpfsRouting ipfs_routing; // offline routing routines. ipfs_routing* ipfs_routing_new_offline (struct IpfsNode* local_node, struct RsaPrivateKey *private_key); diff --git a/repo/fsrepo/Makefile b/repo/fsrepo/Makefile index 3914034..4b9e7d2 100644 --- a/repo/fsrepo/Makefile +++ b/repo/fsrepo/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../lmdb/libraries/liblmdb -I../../../c-protobuf -Wall -std=c99 +CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../lmdb/libraries/liblmdb -I../../../c-protobuf -I../../../c-multiaddr/include -Wall -std=c99 ifdef DEBUG CFLAGS += -g3 diff --git a/repo/fsrepo/fs_repo.c b/repo/fsrepo/fs_repo.c index 9c63008..9f79deb 100644 --- a/repo/fsrepo/fs_repo.c +++ b/repo/fsrepo/fs_repo.c @@ -10,6 +10,7 @@ #include "ipfs/os/utils.h" #include "ipfs/repo/fsrepo/lmdb_datastore.h" #include "jsmn.h" +#include "multiaddr/multiaddr.h" /** * private methods @@ -444,8 +445,27 @@ int fs_repo_open_config(struct FSRepo* repo) { _get_json_string_value(data, tokens, num_tokens, curr_pos, "Gateway", &repo->config->addresses->gateway); // bootstrap peers - repo->config->bootstrap_peers = libp2p_utils_vector_new(1); - // TODO: Implement bootstrap peers + swarm_pos = _find_token(data, tokens, num_tokens, curr_pos, "Bootstrap"); + if (swarm_pos >= 0) { + swarm_pos++; + if (tokens[swarm_pos].type != JSMN_ARRAY) { + free(data); + return 0; + } + swarm_size = tokens[swarm_pos].size; + repo->config->bootstrap_peers = libp2p_utils_vector_new(swarm_size); + swarm_pos++; + for(int i = 0; i < swarm_size; i++) { + char* val = NULL; + if (!_get_json_string_value(data, tokens, num_tokens, swarm_pos + i, NULL, &val)) + break; + struct MultiAddress* cur = multiaddress_new_from_string(val); + if (cur == NULL) + continue; + libp2p_utils_vector_add(repo->config->bootstrap_peers, cur); + free(val); + } + } // free the memory used reading the json file free(data); free(priv_key_base64); diff --git a/routing/k_routing.c b/routing/k_routing.c index 9acdc6d..f0e808d 100644 --- a/routing/k_routing.c +++ b/routing/k_routing.c @@ -18,7 +18,7 @@ * @param value_size the size of the value * @returns 0 on success, otherwise -1 */ -int ipfs_routing_kademlia_put_value(struct s_ipfs_routing* routing, char* key, size_t key_size, void* value, size_t value_size) { +int ipfs_routing_kademlia_put_value(struct IpfsRouting* routing, char* key, size_t key_size, void* value, size_t value_size) { return 0; } @@ -30,7 +30,7 @@ int ipfs_routing_kademlia_put_value(struct s_ipfs_routing* routing, char* key, s * @param 4 a place to store the value * @param 5 the size of the value */ -int ipfs_routing_kademlia_get_value(struct s_ipfs_routing* routing, char* key, size_t key_size, void** value, size_t* value_size) { +int ipfs_routing_kademlia_get_value(struct IpfsRouting* routing, char* key, size_t key_size, void** value, size_t* value_size) { return 0; } @@ -46,7 +46,7 @@ int ipfs_routing_kademlia_get_value(struct s_ipfs_routing* routing, char* key, s * @param results_size the size of the results buffer * @returns true(1) on success, otherwise false(0) */ -int ipfs_routing_kademlia_find_providers(struct s_ipfs_routing* routing, char* key, size_t key_size, struct Libp2pVector** results) { +int ipfs_routing_kademlia_find_providers(struct IpfsRouting* routing, char* key, size_t key_size, struct Libp2pVector** results) { *results = libp2p_utils_vector_new(1); struct Libp2pVector* vector = *results; // see if I can provide it @@ -92,7 +92,7 @@ int ipfs_routing_kademlia_find_providers(struct s_ipfs_routing* routing, char* k /** * Find a peer */ -int ipfs_routing_kademlia_find_peer(struct s_ipfs_routing* routing, char* param1, size_t param2, void* param3, size_t* param4) { +int ipfs_routing_kademlia_find_peer(struct IpfsRouting* routing, const char* param1, size_t param2, void** param3, size_t* param4) { return 0; } @@ -103,7 +103,7 @@ int ipfs_routing_kademlia_find_peer(struct s_ipfs_routing* routing, char* param1 * @param key_size the size of the key * @returns true(1) on success, otherwise false(0) */ -int ipfs_routing_kademlia_provide(struct s_ipfs_routing* routing, char* key, size_t key_size) { +int ipfs_routing_kademlia_provide(struct IpfsRouting* routing, char* key, size_t key_size) { //TODO: Announce to the network that I can provide this file // save in a cache // store key and address in cache. Key is the hash, peer id is the value @@ -113,19 +113,19 @@ int ipfs_routing_kademlia_provide(struct s_ipfs_routing* routing, char* key, siz } // declared here so as to have the code in 1 place -int ipfs_routing_online_ping(struct s_ipfs_routing*, struct Libp2pMessage*); +int ipfs_routing_online_ping(struct IpfsRouting*, struct Libp2pMessage*); /** * Ping this instance */ -int ipfs_routing_kademlia_ping(struct s_ipfs_routing* routing, struct Libp2pMessage* message) { +int ipfs_routing_kademlia_ping(struct IpfsRouting* routing, struct Libp2pMessage* message) { return ipfs_routing_online_ping(routing, message); } -int ipfs_routing_kademlia_bootstrap(struct s_ipfs_routing* routing) { +int ipfs_routing_kademlia_bootstrap(struct IpfsRouting* routing) { return 0; } -struct s_ipfs_routing* ipfs_routing_new_kademlia(struct IpfsNode* local_node, struct RsaPrivateKey* private_key, struct Stream* stream) { +struct IpfsRouting* ipfs_routing_new_kademlia(struct IpfsNode* local_node, struct RsaPrivateKey* private_key, struct Stream* stream) { char kademlia_id[21]; // generate kademlia compatible id by getting first 20 chars of peer id if (local_node->identity->peer_id == NULL || strlen(local_node->identity->peer_id) < 20) { @@ -133,7 +133,7 @@ struct s_ipfs_routing* ipfs_routing_new_kademlia(struct IpfsNode* local_node, st } strncpy(kademlia_id, local_node->identity->peer_id, 20); kademlia_id[20] = 0; - struct s_ipfs_routing* routing = (struct s_ipfs_routing*)malloc(sizeof(struct s_ipfs_routing)); + struct IpfsRouting* routing = (struct IpfsRouting*)malloc(sizeof(struct IpfsRouting)); if (routing != NULL) { routing->local_node = local_node; routing->sk = private_key; diff --git a/routing/offline.c b/routing/offline.c index a98626f..cb05a70 100644 --- a/routing/offline.c +++ b/routing/offline.c @@ -59,7 +59,7 @@ int ipfs_routing_offline_find_providers (ipfs_routing* offlineRouting, char *key return ErrOffline; } -int ipfs_routing_offline_find_peer (ipfs_routing* offlineRouting, char *peer_id, size_t pid_size, void *ret, size_t *rlen) +int ipfs_routing_offline_find_peer (ipfs_routing* offlineRouting, const char *peer_id, size_t pid_size, void **ret, size_t *rlen) { return ErrOffline; } @@ -74,14 +74,19 @@ int ipfs_routing_offline_ping (ipfs_routing* offlineRouting, struct Libp2pMessag return ErrOffline; } +/** + * For offline, this does nothing + * @param offlineRouting the interface + * @returns 0 + */ int ipfs_routing_offline_bootstrap (ipfs_routing* offlineRouting) { - return ErrOffline; + return 0; } -ipfs_routing* ipfs_routing_new_offline (struct IpfsNode* local_node, struct RsaPrivateKey *private_key) +struct IpfsRouting* ipfs_routing_new_offline (struct IpfsNode* local_node, struct RsaPrivateKey *private_key) { - ipfs_routing *offlineRouting = malloc (sizeof(ipfs_routing)); + struct IpfsRouting *offlineRouting = malloc (sizeof(struct IpfsRouting)); if (offlineRouting) { offlineRouting->local_node = local_node; diff --git a/routing/online.c b/routing/online.c index 6ae24df..efaef80 100644 --- a/routing/online.c +++ b/routing/online.c @@ -5,14 +5,40 @@ #include "libp2p/net/stream.h" /** - * Implements the routing interface for network clients + * Implements the routing interface for communicating with network clients */ -int ipfs_routing_online_find_providers(struct s_ipfs_routing* routing, char* val1, size_t val2, struct Libp2pVector** multiaddresses) { +int ipfs_routing_online_find_providers(struct IpfsRouting* routing, char* val1, size_t val2, struct Libp2pVector** multiaddresses) { return 0; } -int ipfs_routing_online_find_peer(struct s_ipfs_routing* routing, char* val1, size_t val2, void* val3, size_t* val4) { - return 0; + +/** + * Find a peer + * @param routing the context + * @param peer_id the id to look for + * @param peer_id_size the size of the id + * @param results the results of the search + * @param results_size the size of results + * @returns 0 on success, otherwise -1 + */ +int ipfs_routing_online_find_peer(struct IpfsRouting* routing, const char* peer_id, size_t peer_id_size, void** results, size_t* results_size) { + // first look to see if we have it in the peerstore + struct Peerstore* peerstore = routing->local_node->peerstore; + struct Libp2pPeer* peer = libp2p_peerstore_get_peer(peerstore, (unsigned char*)peer_id, peer_id_size); + if (peer != NULL) { + //we found it. Return it + *results_size = libp2p_peer_protobuf_encode_size(peer); + *results = malloc(*results_size); + if (!libp2p_peer_protobuf_encode(peer, *results, *results_size, results_size)) { + free(results); + *results = NULL; + *results_size = 0; + return -1; + } + return 0; + } + //TODO: ask the swarm to find the peer + return -1; } /** @@ -21,10 +47,10 @@ int ipfs_routing_online_find_peer(struct s_ipfs_routing* routing, char* val1, si * @param val1 the key (hash) of the data * @returns true(1) on success, otherwise false */ -int ipfs_routing_online_provide(struct s_ipfs_routing* routing, char* val1, size_t val2) { +int ipfs_routing_online_provide(struct IpfsRouting* routing, char* val1, size_t val2) { return 0; } -int ipfs_routing_online_ping(struct s_ipfs_routing* routing, struct Libp2pMessage* message) { +int ipfs_routing_online_ping(struct IpfsRouting* routing, struct Libp2pMessage* message) { // send the same stuff back size_t protobuf_size = libp2p_message_protobuf_encode_size(message); unsigned char protobuf[protobuf_size]; @@ -38,7 +64,39 @@ int ipfs_routing_online_ping(struct s_ipfs_routing* routing, struct Libp2pMessag retVal = -1; return retVal; } -int ipfs_routing_online_bootstrap(struct s_ipfs_routing* routing) { + +/** + * Connects to swarm + * @param routing the routing struct + * @returns 0 on success, otherwise error code + */ +int ipfs_routing_online_bootstrap(struct IpfsRouting* routing) { + // for each address in our bootstrap list, add info into the peerstore + struct Libp2pVector* bootstrap_peers = routing->local_node->repo->config->bootstrap_peers; + for(int i = 0; i < bootstrap_peers->total; i++) { + struct MultiAddress* address = (struct MultiAddress*)libp2p_utils_vector_get(bootstrap_peers, i); + // attempt to get the peer ID + const char* peer_id = multiaddress_get_peer_id(address); + if (peer_id != NULL) { + struct Libp2pPeer* peer = libp2p_peer_new(); + peer->id_size = strlen(peer_id); + peer->id = malloc(peer->id_size); + if (peer->id == NULL) { // out of memory? + libp2p_peer_free(peer); + return -1; + } + memcpy(peer->id, peer_id, peer->id_size); + peer->addr_head = libp2p_utils_linked_list_new(); + if (peer->addr_head == NULL) { // out of memory? + libp2p_peer_free(peer); + return -1; + } + peer->addr_head->item = address; + libp2p_peerstore_add_peer(routing->local_node->peerstore, peer); + libp2p_peer_free(peer); + } + } + return 0; } @@ -46,6 +104,7 @@ int ipfs_routing_online_bootstrap(struct s_ipfs_routing* routing) { * Create a new ipfs_routing struct for online clients * @param fs_repo the repo * @param private_key the local private key + * @param stream the stream to put in the struct * @reurns the ipfs_routing struct that handles messages */ ipfs_routing* ipfs_routing_new_online (struct IpfsNode* local_node, struct RsaPrivateKey *private_key, struct Stream* stream) { diff --git a/test/Makefile b/test/Makefile index 776464a..8fa7ae2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -11,6 +11,7 @@ OBJS = testit.o test_helper.o \ ../core/daemon.o \ ../core/null.o \ ../core/bootstrap.o \ + ../core/ping.o \ ../datastore/ds_helper.o \ ../flatfs/flatfs.o \ ../importer/importer.o ../importer/exporter.o ../importer/resolver.o \ diff --git a/test/core/test_ping.h b/test/core/test_ping.h index 5ef0af3..97ffdc2 100644 --- a/test/core/test_ping.h +++ b/test/core/test_ping.h @@ -10,6 +10,7 @@ #include "ipfs/core/ipfs_node.h" #include "ipfs/repo/fsrepo/fs_repo.h" #include "libp2p/conn/dialer.h" +#include "ipfs/core/daemon.h" /** * Testing connectivity with other nodes @@ -75,3 +76,10 @@ int test_ping() { ipfs_repo_fsrepo_free(fs_repo); return retVal; } + +int test_ping_remote() { + char* argv[] = { "ipfs", "ping", "/ipfs/QmTjg669YQemhffXLrkA3as9jT8SzyRtWaLXHKwYN6wCBd" }; + int argc = 3; + + return ipfs_ping(argc, argv); +} diff --git a/test/testit.c b/test/testit.c index 877ddab..66aab17 100644 --- a/test/testit.c +++ b/test/testit.c @@ -62,6 +62,7 @@ const char* names[] = { "test_unixfs_encode_decode", "test_unixfs_encode_smallfile", "test_ping", + "test_ping_remote", "test_resolver_remote_get" }; @@ -101,6 +102,7 @@ int (*funcs[])(void) = { test_unixfs_encode_decode, test_unixfs_encode_smallfile, test_ping, + test_ping_remote, test_resolver_remote_get };