2017-04-20 22:56:03 +00:00
|
|
|
#include <stdlib.h>
|
2017-09-20 17:39:26 +00:00
|
|
|
#include <pthread.h>
|
2017-04-20 22:56:03 +00:00
|
|
|
|
2017-10-23 21:21:24 +00:00
|
|
|
#include "libp2p/conn/dialer.h"
|
2017-11-06 18:37:48 +00:00
|
|
|
#include "libp2p/identify/identify.h"
|
2017-08-31 21:41:10 +00:00
|
|
|
#include "libp2p/net/multistream.h"
|
2017-08-09 13:04:17 +00:00
|
|
|
#include "libp2p/utils/vector.h"
|
|
|
|
#include "libp2p/secio/secio.h"
|
|
|
|
#include "libp2p/routing/dht_protocol.h"
|
2017-10-11 16:23:49 +00:00
|
|
|
#include "libp2p/yamux/yamux.h"
|
2017-09-20 12:40:28 +00:00
|
|
|
#include "ipfs/core/api.h"
|
2017-09-20 14:11:01 +00:00
|
|
|
#include "ipfs/core/client_api.h"
|
2017-04-20 22:56:03 +00:00
|
|
|
#include "ipfs/core/ipfs_node.h"
|
2017-07-27 17:05:41 +00:00
|
|
|
#include "ipfs/exchange/bitswap/bitswap.h"
|
2017-08-24 15:08:27 +00:00
|
|
|
#include "ipfs/journal/journal.h"
|
2017-04-20 22:56:03 +00:00
|
|
|
|
2017-09-21 14:47:16 +00:00
|
|
|
struct IpfsNode* ipfs_node_new() {
|
|
|
|
struct IpfsNode* node = malloc(sizeof(struct IpfsNode));
|
|
|
|
if (node != NULL) {
|
|
|
|
node->blockstore = NULL;
|
|
|
|
node->exchange = NULL;
|
|
|
|
node->identity = NULL;
|
|
|
|
node->mode = MODE_OFFLINE;
|
|
|
|
node->peerstore = NULL;
|
|
|
|
node->protocol_handlers = NULL;
|
|
|
|
node->providerstore = NULL;
|
|
|
|
node->repo = NULL;
|
|
|
|
node->routing = NULL;
|
2017-09-25 14:20:51 +00:00
|
|
|
node->api_context = NULL;
|
2017-09-21 14:47:16 +00:00
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2017-08-09 13:04:17 +00:00
|
|
|
struct Libp2pVector* ipfs_node_online_build_protocol_handlers(struct IpfsNode* node) {
|
|
|
|
struct Libp2pVector* retVal = libp2p_utils_vector_new(1);
|
|
|
|
if (retVal != NULL) {
|
|
|
|
// secio
|
|
|
|
libp2p_utils_vector_add(retVal, libp2p_secio_build_protocol_handler(&node->identity->private_key, node->peerstore));
|
2017-08-24 15:08:27 +00:00
|
|
|
// journal
|
|
|
|
libp2p_utils_vector_add(retVal, ipfs_journal_build_protocol_handler(node));
|
2017-08-09 13:04:17 +00:00
|
|
|
// kademlia
|
2017-11-08 15:54:31 +00:00
|
|
|
libp2p_utils_vector_add(retVal, libp2p_routing_dht_build_protocol_handler(node->peerstore, node->providerstore, node->repo->config->datastore, node->repo->config->filestore));
|
2017-08-09 13:04:17 +00:00
|
|
|
// bitswap
|
|
|
|
libp2p_utils_vector_add(retVal, ipfs_bitswap_build_protocol_handler(node));
|
2017-08-31 21:41:10 +00:00
|
|
|
// multistream
|
2017-09-04 16:02:48 +00:00
|
|
|
libp2p_utils_vector_add(retVal, libp2p_net_multistream_build_protocol_handler(retVal));
|
2017-10-11 16:23:49 +00:00
|
|
|
// yamux
|
2017-11-08 15:54:31 +00:00
|
|
|
libp2p_utils_vector_add(retVal, libp2p_yamux_build_protocol_handler());
|
2017-11-06 18:37:48 +00:00
|
|
|
// identify
|
|
|
|
libp2p_utils_vector_add(retVal, libp2p_identify_build_protocol_handler(retVal));
|
2017-08-09 13:04:17 +00:00
|
|
|
}
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
2017-08-09 17:21:03 +00:00
|
|
|
int ipfs_node_online_protocol_handlers_free(struct Libp2pVector* handlers) {
|
|
|
|
for(int i = 0; i < handlers->total; i++) {
|
|
|
|
struct Libp2pProtocolHandler* current = (struct Libp2pProtocolHandler*) libp2p_utils_vector_get(handlers, i);
|
|
|
|
current->Shutdown(current->context);
|
2017-08-09 17:26:26 +00:00
|
|
|
free(current);
|
2017-08-09 17:21:03 +00:00
|
|
|
}
|
|
|
|
libp2p_utils_vector_free(handlers);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-20 22:56:03 +00:00
|
|
|
/***
|
|
|
|
* build an online IpfsNode
|
|
|
|
* @param repo_path where the IPFS repository directory is
|
|
|
|
* @param node the completed IpfsNode struct
|
|
|
|
* @returns true(1) on success
|
|
|
|
*/
|
2017-09-25 13:55:42 +00:00
|
|
|
int ipfs_node_online_new(const char* repo_path, struct IpfsNode** node) {
|
2017-04-20 22:56:03 +00:00
|
|
|
struct FSRepo* fs_repo = NULL;
|
|
|
|
|
2017-09-21 14:47:16 +00:00
|
|
|
*node = ipfs_node_new();
|
2017-04-20 22:56:03 +00:00
|
|
|
if(*node == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
struct IpfsNode* local_node = *node;
|
|
|
|
|
|
|
|
// build the struct
|
|
|
|
if (!ipfs_repo_fsrepo_new(repo_path, NULL, &fs_repo)) {
|
2017-09-25 13:55:42 +00:00
|
|
|
ipfs_node_free(local_node);
|
2017-04-27 16:35:26 +00:00
|
|
|
*node = NULL;
|
2017-04-20 22:56:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// open the repo
|
|
|
|
if (!ipfs_repo_fsrepo_open(fs_repo)) {
|
2017-09-25 13:55:42 +00:00
|
|
|
ipfs_node_free(local_node);
|
2017-04-27 16:35:26 +00:00
|
|
|
*node = NULL;
|
2017-04-20 22:56:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill in the node
|
|
|
|
local_node->repo = fs_repo;
|
|
|
|
local_node->identity = fs_repo->config->identity;
|
2017-07-31 17:50:12 +00:00
|
|
|
local_node->peerstore = libp2p_peerstore_new(local_node->identity->peer);
|
2017-10-25 17:29:20 +00:00
|
|
|
local_node->dialer = libp2p_conn_dialer_new(local_node->identity->peer, local_node->peerstore, &local_node->identity->private_key);
|
2017-07-31 17:50:12 +00:00
|
|
|
local_node->providerstore = libp2p_providerstore_new(fs_repo->config->datastore, local_node->identity->peer);
|
2017-07-24 19:56:30 +00:00
|
|
|
local_node->blockstore = ipfs_blockstore_new(fs_repo);
|
2017-08-09 13:14:15 +00:00
|
|
|
local_node->protocol_handlers = ipfs_node_online_build_protocol_handlers(local_node);
|
2017-04-20 22:56:03 +00:00
|
|
|
local_node->mode = MODE_OFFLINE;
|
2017-07-27 17:05:41 +00:00
|
|
|
local_node->routing = ipfs_routing_new_online(local_node, &fs_repo->config->identity->private_key);
|
|
|
|
local_node->exchange = ipfs_bitswap_new(local_node);
|
2017-04-20 22:56:03 +00:00
|
|
|
|
2017-09-20 12:32:12 +00:00
|
|
|
// fire up the API
|
2017-09-25 13:55:42 +00:00
|
|
|
api_start(local_node, 10, 5);
|
2017-09-20 12:32:12 +00:00
|
|
|
|
2017-04-20 22:56:03 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-08-30 16:10:14 +00:00
|
|
|
/***
|
|
|
|
* build an offline IpfsNode
|
|
|
|
* @param repo_path where the IPFS repository directory is
|
|
|
|
* @param node the completed IpfsNode struct
|
|
|
|
* @returns true(1) on success
|
|
|
|
*/
|
2017-09-21 12:51:18 +00:00
|
|
|
int ipfs_node_offline_new(const char* repo_path, struct IpfsNode** node) {
|
2017-08-30 16:10:14 +00:00
|
|
|
struct FSRepo* fs_repo = NULL;
|
|
|
|
|
2017-09-21 14:47:16 +00:00
|
|
|
*node = ipfs_node_new();
|
2017-08-30 16:10:14 +00:00
|
|
|
if(*node == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
struct IpfsNode* local_node = *node;
|
|
|
|
|
|
|
|
// build the struct
|
|
|
|
if (!ipfs_repo_fsrepo_new(repo_path, NULL, &fs_repo)) {
|
2017-09-25 13:55:42 +00:00
|
|
|
ipfs_node_free(local_node);
|
2017-08-30 16:10:14 +00:00
|
|
|
*node = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// open the repo
|
|
|
|
if (!ipfs_repo_fsrepo_open(fs_repo)) {
|
2017-09-25 13:55:42 +00:00
|
|
|
ipfs_node_free(local_node);
|
2017-08-30 16:10:14 +00:00
|
|
|
*node = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill in the node
|
|
|
|
local_node->repo = fs_repo;
|
|
|
|
local_node->identity = fs_repo->config->identity;
|
|
|
|
local_node->peerstore = libp2p_peerstore_new(local_node->identity->peer);
|
2017-10-25 17:29:20 +00:00
|
|
|
local_node->dialer = libp2p_conn_dialer_new(local_node->identity->peer, local_node->peerstore, &local_node->identity->private_key);
|
2017-08-30 16:10:14 +00:00
|
|
|
local_node->providerstore = libp2p_providerstore_new(fs_repo->config->datastore, local_node->identity->peer);
|
|
|
|
local_node->blockstore = ipfs_blockstore_new(fs_repo);
|
|
|
|
local_node->protocol_handlers = ipfs_node_online_build_protocol_handlers(local_node);
|
|
|
|
local_node->mode = MODE_OFFLINE;
|
|
|
|
local_node->routing = ipfs_routing_new_offline(local_node, &fs_repo->config->identity->private_key);
|
|
|
|
local_node->exchange = ipfs_bitswap_new(local_node);
|
|
|
|
|
2017-09-20 14:11:01 +00:00
|
|
|
if (api_running(local_node))
|
|
|
|
local_node->mode = MODE_API_AVAILABLE;
|
|
|
|
|
2017-08-30 16:10:14 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-20 22:56:03 +00:00
|
|
|
/***
|
|
|
|
* Free resources from the creation of an IpfsNode
|
|
|
|
* @param node the node to free
|
|
|
|
* @returns true(1)
|
|
|
|
*/
|
2017-09-25 13:55:42 +00:00
|
|
|
int ipfs_node_free(struct IpfsNode* node) {
|
2017-04-20 22:56:03 +00:00
|
|
|
if (node != NULL) {
|
2017-09-25 14:20:51 +00:00
|
|
|
if (node->api_context != NULL && node->api_context->api_thread != 0)
|
2017-09-25 13:55:42 +00:00
|
|
|
api_stop(node);
|
2017-08-09 01:40:35 +00:00
|
|
|
if (node->exchange != NULL) {
|
|
|
|
node->exchange->Close(node->exchange);
|
|
|
|
}
|
2017-04-20 22:56:03 +00:00
|
|
|
if (node->providerstore != NULL)
|
|
|
|
libp2p_providerstore_free(node->providerstore);
|
|
|
|
if (node->peerstore != NULL)
|
|
|
|
libp2p_peerstore_free(node->peerstore);
|
|
|
|
if (node->repo != NULL)
|
|
|
|
ipfs_repo_fsrepo_free(node->repo);
|
2017-08-09 17:21:03 +00:00
|
|
|
if (node->protocol_handlers != NULL)
|
|
|
|
ipfs_node_online_protocol_handlers_free(node->protocol_handlers);
|
2017-04-20 22:56:03 +00:00
|
|
|
if (node->mode == MODE_ONLINE) {
|
|
|
|
ipfs_routing_online_free(node->routing);
|
|
|
|
}
|
2017-09-20 14:11:01 +00:00
|
|
|
if (node->mode == MODE_OFFLINE || node->mode == MODE_API_AVAILABLE) {
|
2017-09-07 16:05:56 +00:00
|
|
|
ipfs_routing_offline_free(node->routing);
|
|
|
|
}
|
2017-07-26 14:48:04 +00:00
|
|
|
if (node->blockstore != NULL) {
|
|
|
|
ipfs_blockstore_free(node->blockstore);
|
|
|
|
}
|
2017-04-20 22:56:03 +00:00
|
|
|
free(node);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|