2016-10-27 18:11:34 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2017-03-19 12:47:19 +00:00
|
|
|
#include "libp2p/utils/linked_list.h"
|
2016-11-07 21:29:30 +00:00
|
|
|
#include "ipfs/repo/config/config.h"
|
2017-04-06 14:33:28 +00:00
|
|
|
#include "libp2p/os/utils.h"
|
2016-11-02 18:09:38 +00:00
|
|
|
#include "ipfs/repo/config/bootstrap_peers.h"
|
|
|
|
#include "ipfs/repo/config/swarm.h"
|
2017-04-20 22:56:03 +00:00
|
|
|
#include "libp2p/db/filestore.h"
|
2017-04-27 16:35:26 +00:00
|
|
|
#include "multiaddr/multiaddr.h"
|
2016-10-27 18:11:34 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
* public
|
|
|
|
*/
|
|
|
|
|
|
|
|
/***
|
|
|
|
* gets the default path from the environment variable and/or the homedir struct
|
|
|
|
* NOTE: this allocates memory for result. Clean up after yourself.
|
|
|
|
* @param result where the result string will reside.
|
|
|
|
* @returns true(1) on success, or false(0)
|
|
|
|
*/
|
2016-12-14 11:25:09 +00:00
|
|
|
int config_get_default_path_root(char** result) {
|
2016-10-27 18:11:34 +00:00
|
|
|
char* root = os_utils_getenv("IPFS_PATH");
|
|
|
|
if (root == NULL) {
|
|
|
|
root = os_utils_getenv("HOME");
|
2016-12-14 11:25:09 +00:00
|
|
|
*result = malloc( strlen(root) + 7);
|
|
|
|
if (*result == NULL)
|
2016-10-27 18:11:34 +00:00
|
|
|
return 0;
|
2016-12-14 11:25:09 +00:00
|
|
|
strncpy(*result, root, strlen(root)+1);
|
|
|
|
strncat(*result, "/.ipfs", 7);
|
2016-10-27 18:11:34 +00:00
|
|
|
} else {
|
2016-12-14 11:25:09 +00:00
|
|
|
*result = malloc(strlen(root)+1);
|
|
|
|
if (*result == NULL)
|
2016-10-27 18:11:34 +00:00
|
|
|
return 0;
|
2016-12-14 11:25:09 +00:00
|
|
|
strncpy(*result, root, strlen(root)+1);
|
2016-10-27 18:11:34 +00:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Returns the path "extension" relative to the configuration root.
|
|
|
|
* If an empty string is provided for config_root, the default root
|
|
|
|
* is used. NOTE: be sure to dispose of the memory allocated for result.
|
|
|
|
* @param config_root the path to the root of the configuration
|
|
|
|
* @param extension the extension to add to the path
|
|
|
|
* @param result the result of config_root with extension appended
|
|
|
|
* @returns true(1) if everything went okay, false(0) otherwise
|
|
|
|
*/
|
|
|
|
int config_path(char* config_root, char* extension, char* result, int max_len) {
|
|
|
|
if (strlen(config_root) == 0) {
|
2016-12-14 11:25:09 +00:00
|
|
|
char* default_path = NULL;
|
|
|
|
int retVal = config_get_default_path_root(&default_path);
|
2016-10-27 18:11:34 +00:00
|
|
|
if (!retVal)
|
|
|
|
return retVal;
|
|
|
|
retVal = os_utils_filepath_join(default_path, extension, result, max_len);
|
|
|
|
free(default_path);
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
return os_utils_filepath_join(config_root, extension, result, max_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* provide the full path of the config file, given the directory.
|
|
|
|
* NOTE: This allocates memory for result. Make sure to clean up after yourself.
|
|
|
|
* @param path the path to the config file (without the actual file name)
|
|
|
|
* @param result the full filename including the path
|
|
|
|
* @returns true(1) on success, false(0) otherwise
|
|
|
|
*/
|
2016-11-03 04:05:29 +00:00
|
|
|
int repo_config_get_file_name(char* path, char** result) {
|
|
|
|
unsigned long max_len = strlen(path) + 8;
|
|
|
|
*result = malloc(sizeof(char) * max_len);
|
|
|
|
if (result == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2016-11-17 20:07:59 +00:00
|
|
|
return os_utils_filepath_join(path, "config", *result, max_len);
|
2016-10-27 18:11:34 +00:00
|
|
|
}
|
2016-10-31 16:13:42 +00:00
|
|
|
|
2017-04-17 16:58:47 +00:00
|
|
|
int ipfs_repo_config_is_valid_identity(struct Identity* identity) {
|
2017-07-31 17:50:12 +00:00
|
|
|
if (identity == NULL || identity->peer == NULL || identity->peer->id == NULL || identity->peer->id[0] != 'Q' || identity->peer->id[1] != 'm')
|
2017-04-17 16:58:47 +00:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-10-31 16:13:42 +00:00
|
|
|
/***
|
|
|
|
* create a configuration based on the passed in parameters
|
|
|
|
* @param config the configuration struct to be filled in
|
|
|
|
* @param num_bits_for_keypair number of bits for the key pair
|
2017-04-13 14:31:58 +00:00
|
|
|
* @param repo_path the path to the configuration
|
|
|
|
* @param swarm_port the port to run on
|
|
|
|
* @param bootstrap_peers vector of Multiaddresses of fellow peers
|
2016-10-31 16:13:42 +00:00
|
|
|
* @returns true(1) on success, otherwise 0
|
|
|
|
*/
|
2017-04-13 14:31:58 +00:00
|
|
|
int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, const char* repo_path, int swarm_port, struct Libp2pVector *bootstrap_peers) {
|
2016-11-02 18:09:38 +00:00
|
|
|
// identity
|
2017-04-27 16:35:26 +00:00
|
|
|
int counter = 0;
|
|
|
|
while (counter < 5) {
|
2017-05-11 18:53:52 +00:00
|
|
|
if (counter > 0) {
|
|
|
|
//TODO: This shouldn't be here, but it was the only way to cleanup. Need to find a better way...
|
2017-08-03 20:04:12 +00:00
|
|
|
if (config->identity->private_key.public_key_der != NULL) {
|
2017-05-11 18:53:52 +00:00
|
|
|
free(config->identity->private_key.public_key_der);
|
2017-08-03 20:04:12 +00:00
|
|
|
config->identity->private_key.public_key_der = NULL;
|
|
|
|
}
|
|
|
|
if (config->identity->private_key.der != NULL) {
|
2017-05-11 18:53:52 +00:00
|
|
|
free(config->identity->private_key.der);
|
2017-08-03 20:04:12 +00:00
|
|
|
config->identity->private_key.der = NULL;
|
|
|
|
}
|
|
|
|
if (config->identity->peer != NULL) {
|
2017-07-31 17:50:12 +00:00
|
|
|
libp2p_peer_free(config->identity->peer);
|
2017-08-03 20:04:12 +00:00
|
|
|
config->identity->peer = NULL;
|
|
|
|
}
|
2017-05-11 18:53:52 +00:00
|
|
|
}
|
2017-04-27 16:35:26 +00:00
|
|
|
if (!repo_config_identity_init(config->identity, num_bits_for_keypair))
|
|
|
|
return 0;
|
|
|
|
if (ipfs_repo_config_is_valid_identity(config->identity))
|
|
|
|
break;
|
2017-05-11 18:53:52 +00:00
|
|
|
// we didn't get it right, try again
|
2017-04-27 16:35:26 +00:00
|
|
|
counter++;
|
2017-04-17 16:58:47 +00:00
|
|
|
}
|
2017-04-27 16:35:26 +00:00
|
|
|
|
|
|
|
if (counter == 5)
|
|
|
|
return 0;
|
2016-10-31 16:13:42 +00:00
|
|
|
|
2016-11-02 18:09:38 +00:00
|
|
|
// bootstrap peers
|
2017-04-13 14:31:58 +00:00
|
|
|
if (bootstrap_peers != NULL) {
|
|
|
|
config->bootstrap_peers = libp2p_utils_vector_new(bootstrap_peers->total);
|
2017-04-27 16:35:26 +00:00
|
|
|
for(int i = 0; i < bootstrap_peers->total; i++) {
|
2017-07-26 12:38:47 +00:00
|
|
|
const struct MultiAddress* orig = (const struct MultiAddress*) libp2p_utils_vector_get(bootstrap_peers, i);
|
2017-04-27 16:35:26 +00:00
|
|
|
libp2p_utils_vector_add(config->bootstrap_peers, multiaddress_copy(orig));
|
|
|
|
}
|
2017-04-13 14:31:58 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!repo_config_bootstrap_peers_retrieve(&(config->bootstrap_peers)))
|
|
|
|
return 0;
|
|
|
|
}
|
2016-10-31 16:13:42 +00:00
|
|
|
|
2016-11-02 18:09:38 +00:00
|
|
|
// datastore
|
2017-04-27 16:35:26 +00:00
|
|
|
if (!libp2p_datastore_init(config->datastore, repo_path))
|
2016-11-02 18:09:38 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
// swarm addresses
|
2017-04-27 16:35:26 +00:00
|
|
|
char* addr1 = malloc(27);
|
2017-04-13 14:31:58 +00:00
|
|
|
sprintf(addr1, "/ip4/0.0.0.0/tcp/%d", swarm_port);
|
2017-03-19 12:47:19 +00:00
|
|
|
config->addresses->swarm_head = libp2p_utils_linked_list_new();
|
|
|
|
config->addresses->swarm_head->item = malloc(strlen(addr1) + 1);
|
|
|
|
strcpy(config->addresses->swarm_head->item, addr1);
|
2017-04-13 14:31:58 +00:00
|
|
|
|
|
|
|
sprintf(addr1, "/ip6/::/tcp/%d", swarm_port);
|
2017-03-19 12:47:19 +00:00
|
|
|
config->addresses->swarm_head->next = libp2p_utils_linked_list_new();
|
2017-04-13 14:31:58 +00:00
|
|
|
config->addresses->swarm_head->next->item = malloc(strlen(addr1) + 1);
|
|
|
|
strcpy(config->addresses->swarm_head->next->item, addr1);
|
2017-09-21 14:47:16 +00:00
|
|
|
|
|
|
|
strcpy(addr1, "/ip4/127.0.0.1/tcp/5001");
|
|
|
|
config->addresses->api = malloc(strlen(addr1)+1);
|
|
|
|
strcpy(config->addresses->api, addr1);
|
|
|
|
strcpy(addr1, "ip4/127.0.0.1/tcp/8080");
|
|
|
|
config->addresses->gateway = malloc(strlen(addr1+1));
|
|
|
|
strcpy(config->addresses->gateway, addr1);
|
2017-04-13 14:31:58 +00:00
|
|
|
free(addr1);
|
2017-09-21 14:47:16 +00:00
|
|
|
|
2016-11-02 18:09:38 +00:00
|
|
|
config->discovery.mdns.enabled = 1;
|
|
|
|
config->discovery.mdns.interval = 10;
|
|
|
|
|
|
|
|
config->mounts.ipfs = "/ipfs";
|
|
|
|
config->mounts.ipns = "/ipns";
|
|
|
|
|
|
|
|
config->ipns.resolve_cache_size = 128;
|
|
|
|
|
|
|
|
config->reprovider.interval = "12h";
|
|
|
|
|
2016-11-28 13:09:00 +00:00
|
|
|
config->gateway->root_redirect = "";
|
|
|
|
config->gateway->writable = 0;
|
2016-11-02 18:09:38 +00:00
|
|
|
|
2016-11-28 13:09:00 +00:00
|
|
|
config->gateway->path_prefixes.num_elements = 0;
|
2016-11-02 18:09:38 +00:00
|
|
|
|
|
|
|
// gateway http headers
|
|
|
|
char** header_array = (char * []) { "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", "Access-Control-Allow-Headers" };
|
|
|
|
char** header_values = (char*[]) { "*", "GET", "X-Requested-With" };
|
2017-04-27 16:35:26 +00:00
|
|
|
if (!repo_config_gateway_http_header_init(config->gateway->http_headers, header_array, header_values, 3))
|
2016-11-02 18:09:38 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
2016-10-31 16:13:42 +00:00
|
|
|
}
|
|
|
|
|
2016-11-17 20:07:59 +00:00
|
|
|
/***
|
|
|
|
* Initialize memory for a RepoConfig struct
|
|
|
|
* @param config the structure to initialize
|
|
|
|
* @returns true(1) on success
|
|
|
|
*/
|
|
|
|
int ipfs_repo_config_new(struct RepoConfig** config) {
|
|
|
|
*config = (struct RepoConfig*)malloc(sizeof(struct RepoConfig));
|
|
|
|
if (*config == NULL)
|
|
|
|
return 0;
|
2016-11-28 13:09:00 +00:00
|
|
|
|
|
|
|
// set initial values
|
2017-03-24 21:51:00 +00:00
|
|
|
(*config)->bootstrap_peers = NULL;
|
2016-11-28 13:09:00 +00:00
|
|
|
|
|
|
|
int retVal = 1;
|
|
|
|
retVal = repo_config_identity_new(&((*config)->identity));
|
|
|
|
if (retVal == 0)
|
|
|
|
return 0;
|
|
|
|
|
2017-04-06 14:33:28 +00:00
|
|
|
retVal = libp2p_datastore_new(&((*config)->datastore));
|
2016-11-28 13:09:00 +00:00
|
|
|
if (retVal == 0)
|
|
|
|
return 0;
|
|
|
|
|
2017-04-20 22:56:03 +00:00
|
|
|
(*config)->filestore = libp2p_filestore_new();
|
|
|
|
|
2017-04-17 16:58:47 +00:00
|
|
|
retVal = repo_config_addresses_new(&((*config)->addresses));
|
2016-11-28 13:09:00 +00:00
|
|
|
if (retVal == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
retVal = repo_config_gateway_new(&((*config)->gateway));
|
|
|
|
if (retVal == 0)
|
|
|
|
return 0;
|
|
|
|
|
2017-07-20 14:12:31 +00:00
|
|
|
if (!repo_config_replication_new(&((*config)->replication)))
|
|
|
|
return 0;
|
|
|
|
|
2016-11-17 20:07:59 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Free resources
|
|
|
|
* @param config the struct to be freed
|
|
|
|
* @returns true(1) on success
|
|
|
|
*/
|
|
|
|
int ipfs_repo_config_free(struct RepoConfig* config) {
|
|
|
|
if (config != NULL) {
|
2016-12-01 18:08:30 +00:00
|
|
|
if (config->identity != NULL)
|
|
|
|
repo_config_identity_free(config->identity);
|
2017-03-24 21:51:00 +00:00
|
|
|
if (&(config->bootstrap_peers) != NULL)
|
|
|
|
repo_config_bootstrap_peers_free(config->bootstrap_peers);
|
2016-12-01 18:08:30 +00:00
|
|
|
if (config->datastore != NULL)
|
2017-04-06 14:33:28 +00:00
|
|
|
libp2p_datastore_free(config->datastore);
|
2017-04-20 22:56:03 +00:00
|
|
|
if (config->filestore != NULL)
|
|
|
|
libp2p_filestore_free(config->filestore);
|
2016-12-01 18:08:30 +00:00
|
|
|
if (config->addresses != NULL)
|
|
|
|
repo_config_addresses_free(config->addresses);
|
|
|
|
if (config->gateway != NULL)
|
|
|
|
repo_config_gateway_free(config->gateway);
|
2017-07-20 14:12:31 +00:00
|
|
|
if (config->replication != NULL)
|
|
|
|
repo_config_replication_free(config->replication);
|
2016-11-17 20:07:59 +00:00
|
|
|
free(config);
|
|
|
|
}
|
2016-11-02 18:44:56 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int repo_config_martial_to_json(struct RepoConfig* config) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|