├── .cproject ├── .gitignore ├── .project ├── LICENSE ├── Makefile ├── README.md ├── blocks ├── Makefile ├── block.c └── blockstore.c ├── cid ├── Makefile └── cid.c ├── cmd ├── Makefile └── ipfs │ ├── Makefile │ ├── init.c │ └── main.c ├── commands ├── Makefile ├── argument.c ├── cli │ ├── Makefile │ └── parse.c ├── command.c └── command_option.c ├── core ├── Makefile └── builder.c ├── datastore ├── Makefile ├── ds_helper.c └── key.c ├── flatfs ├── Makefile └── flatfs.c ├── include └── ipfs │ ├── blocks │ ├── block.h │ └── blockstore.h │ ├── cid │ └── cid.h │ ├── cmd │ └── ipfs │ │ └── init.h │ ├── commands │ ├── argument.h │ ├── cli │ │ └── parse.h │ ├── command.h │ ├── command_option.h │ ├── context.h │ ├── req_log.h │ └── request.h │ ├── core │ ├── builder.h │ └── ipfs_node.h │ ├── datastore │ ├── ds_helper.h │ └── key.h │ ├── flatfs │ └── flatfs.h │ ├── multibase │ └── multibase.h │ ├── namesys │ ├── isdomain.h │ └── namesys.h │ ├── node │ ├── Example for this.c │ └── node.h │ ├── os │ └── utils.h │ ├── path │ └── path.h │ ├── repo │ ├── config │ │ ├── addresses.h │ │ ├── bootstrap_peers.h │ │ ├── config.h │ │ ├── datastore.h │ │ ├── gateway.h │ │ ├── identity.h │ │ ├── peer.h │ │ └── swarm.h │ └── fsrepo │ │ ├── fs_repo.h │ │ └── lmdb_datastore.h │ └── thirdparty │ └── ipfsaddr │ └── ipfs_addr.h ├── merkledag └── merkledag.c ├── multibase ├── Makefile └── multibase.c ├── namesys ├── base.c ├── dns.c ├── is_domain_test.c ├── isdomain.c ├── namesys.c ├── proquint.c └── proquint_test.c ├── node └── node.c ├── os ├── Makefile └── utils.c ├── path ├── path.c └── resolver.c ├── repo ├── Makefile ├── config │ ├── Makefile │ ├── addresses.c │ ├── bootstrap_peers.c │ ├── config.c │ ├── datastore.c │ ├── gateway.c │ ├── identity.c │ ├── peer.c │ └── swarm.c └── fsrepo │ ├── Makefile │ ├── fs_repo.c │ ├── jsmn.c │ ├── jsmn.h │ └── lmdb_datastore.c ├── test ├── Makefile ├── cid │ └── test_cid.h ├── cmd │ └── ipfs │ │ └── test_init.h ├── flatfs │ └── test_flatfs.h ├── repo │ ├── test_repo_bootstrap_peers.h │ ├── test_repo_config.h │ ├── test_repo_fsrepo.h │ └── test_repo_identity.h ├── storage │ ├── test_blocks.h │ ├── test_blockstore.h │ ├── test_datastore.h │ └── test_ds_helper.h └── testit.c └── thirdparty ├── Makefile └── ipfsaddr ├── Makefile └── ipfs_addr.c /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | make 74 | 75 | all 76 | true 77 | true 78 | true 79 | 80 | 81 | make 82 | 83 | clean 84 | true 85 | true 86 | true 87 | 88 | 89 | make 90 | 91 | rebuild 92 | true 93 | true 94 | true 95 | 96 | 97 | make 98 | clean 99 | true 100 | false 101 | true 102 | 103 | 104 | make 105 | clean 106 | true 107 | false 108 | true 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !.gitignore 4 | !Makefile 5 | !**/ 6 | 7 | *.o 8 | .settings/language.settings.xml 9 | test/test_ipfs 10 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | c-ipfs 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 BitShares Munich IVS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | DEBUG = true 3 | export DEBUG 4 | 5 | all: 6 | cd blocks; make all; 7 | cd cid; make all; 8 | cd cmd; make all; 9 | cd commands; make all; 10 | cd core; make all; 11 | cd multibase; make all; 12 | cd os; make all; 13 | cd repo; make all; 14 | cd flatfs; make all; 15 | cd datastore; make all; 16 | cd thirdparty; make all; 17 | cd test; make all; 18 | 19 | clean: 20 | cd blocks; make clean; 21 | cd cid; make clean; 22 | cd cmd; make clean; 23 | cd commands; make clean; 24 | cd core; make clean; 25 | cd multibase; make clean; 26 | cd os; make clean; 27 | cd repo; make clean; 28 | cd flatfs; make clean; 29 | cd datastore; make clean; 30 | cd thirdparty; make clean; 31 | cd test; make clean; 32 | 33 | rebuild: clean all 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-ipfs 2 | IPFS implementation in C, (not just an API client library).
3 |
4 | getting started: https://github.com/ipfs/specs/blob/master/overviews/implement-ipfs.md
5 | specifications: https://github.com/ipfs/specs
6 | getting started: https://github.com/ipfs/community/issues/177
7 | libp2p: https://github.com/libp2p/specs
8 | -------------------------------------------------------------------------------- /blocks/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = ../include/blocks/block.h ../include/blocks/blockstore.h 10 | OBJS = block.o blockstore.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /blocks/block.c: -------------------------------------------------------------------------------- 1 | /** 2 | * The implementation of methods around IPFS blocks 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "libp2p/crypto/sha256.h" 9 | #include "ipfs/blocks/block.h" 10 | #include "ipfs/cid/cid.h" 11 | 12 | /*** 13 | * Create a new block based on the incoming data 14 | * @param data the data to base the block on 15 | * @param data_size the length of the data array 16 | * @param block a pointer to the struct Block that will be created 17 | * @returns true(1) on success 18 | */ 19 | int ipfs_blocks_block_new(const unsigned char* data, size_t data_size, struct Block** block) { 20 | 21 | // allocate memory for structure 22 | (*block) = (struct Block*)malloc(sizeof(struct Block)); 23 | if ((*block) == NULL) 24 | return 0; 25 | 26 | // cid 27 | unsigned char hash[32]; 28 | if (libp2p_crypto_hashing_sha256(data, data_size, &hash[0]) == 0) { 29 | free(*block); 30 | return 0; 31 | } 32 | 33 | if (ipfs_cid_new(0, hash, 32, CID_PROTOBUF, &((*block)->cid)) == 0) { 34 | free(*block); 35 | return 0; 36 | } 37 | 38 | (*block)->data_length = data_size; 39 | 40 | (*block)->data = malloc(sizeof(unsigned char) * data_size); 41 | if ( (*block)->data == NULL) { 42 | ipfs_cid_free((*block)->cid); 43 | free(*block); 44 | return 0; 45 | } 46 | 47 | memcpy( (*block)->data, data, data_size); 48 | return 1; 49 | } 50 | 51 | /*** 52 | * Free resources used by the creation of a block 53 | * @param block the block to free 54 | * @returns true(1) on success 55 | */ 56 | int ipfs_blocks_block_free(struct Block* block) { 57 | ipfs_cid_free(block->cid); 58 | if (block->data != NULL) 59 | free(block->data); 60 | free(block); 61 | return 1; 62 | } 63 | -------------------------------------------------------------------------------- /blocks/blockstore.c: -------------------------------------------------------------------------------- 1 | /*** 2 | * a thin wrapper over a datastore for getting and putting block objects 3 | */ 4 | #include "libp2p/crypto/encoding/base32.h" 5 | #include "ipfs/cid/cid.h" 6 | #include "ipfs/blocks/block.h" 7 | #include "ipfs/datastore/ds_helper.h" 8 | #include "ipfs/repo/fsrepo/fs_repo.h" 9 | 10 | /** 11 | * Delete a block based on its Cid 12 | * @param cid the Cid to look for 13 | * @param returns true(1) on success 14 | */ 15 | int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo) { 16 | return 0; 17 | } 18 | 19 | /*** 20 | * Determine if the Cid can be found 21 | * @param cid the Cid to look for 22 | * @returns true(1) if found 23 | */ 24 | int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo) { 25 | return 0; 26 | } 27 | 28 | /*** 29 | * Find a block based on its Cid 30 | * @param cid the Cid to look for 31 | * @param block where to put the data to be returned 32 | * @returns true(1) on success 33 | */ 34 | int ipfs_blockstore_get(struct Cid* cid, struct Block* block, struct FSRepo* fs_repo) { 35 | return 0; 36 | } 37 | 38 | /*** 39 | * Put a block in the blockstore 40 | * @param block the block to store 41 | * @returns true(1) on success 42 | */ 43 | int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo) { 44 | // from blockstore.go line 118 45 | // Get Datastore key, which is a base32 key of the binary, 46 | size_t key_length = libp2p_crypto_encoding_base32_encode_size(block->data_length); 47 | unsigned char key[key_length]; 48 | int retVal = ipfs_datastore_helper_ds_key_from_binary(block->data, block->data_length, &key[0], key_length, &key_length); 49 | if (retVal == 0) 50 | return 0; 51 | 52 | // send to Put with key 53 | fs_repo->config->datastore->datastore_put(key, key_length, block, fs_repo->config->datastore); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /cid/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = cid.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /cid/cid.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Content ID 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ipfs/cid/cid.h" 10 | #include "libp2p/crypto/encoding/base58.h" 11 | #include "ipfs/multibase/multibase.h" 12 | #include "mh/multihash.h" 13 | #include "multiaddr/varint.h" 14 | 15 | 16 | /** 17 | * Create a new CID based on the given hash 18 | * @param version the version 19 | * @param hash the multihash 20 | * @param hash_length the length of the multihash in bytes 21 | * @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF) 22 | * @param cid where to put the results 23 | * @returns true(1) on success 24 | */ 25 | int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** ptrToCid) { 26 | // allocate memory 27 | *ptrToCid = (struct Cid*)malloc(sizeof(struct Cid)); 28 | struct Cid* cid = *ptrToCid; 29 | if (cid == NULL) 30 | return 0; 31 | cid->hash = malloc(sizeof(unsigned char) * hash_length); 32 | if (cid->hash == NULL) { 33 | free(cid); 34 | return 0; 35 | } 36 | // assign values 37 | cid->version = version; 38 | cid->codec = codec; 39 | memcpy(cid->hash, hash, hash_length); 40 | cid->hash_length = hash_length; 41 | 42 | return 1; 43 | 44 | } 45 | 46 | /*** 47 | * Free the resources from a Cid 48 | * @param cid the struct 49 | * @returns 1 50 | */ 51 | int ipfs_cid_free(struct Cid* cid) { 52 | if (cid->hash != NULL) 53 | free(cid->hash); 54 | free(cid); 55 | return 1; 56 | } 57 | 58 | /*** 59 | * Fill a Cid struct based on a base 58 encoded string 60 | * @param incoming the string 61 | * @param incoming_size the size of the string 62 | * @cid the Cid struct to fill 63 | * @return true(1) on success 64 | */ 65 | int ipfs_cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid** cid) { 66 | int retVal = 0; 67 | 68 | if (incoming_length < 2) 69 | return 0; 70 | 71 | // is this a sha_256 multihash? 72 | if (incoming_length == 46 && incoming[0] == 'Q' && incoming[1] == 'm') { 73 | size_t hash_length = libp2p_crypto_encoding_base58_decode_size(incoming_length); 74 | unsigned char hash[hash_length]; 75 | unsigned char* ptr = hash; 76 | retVal = libp2p_crypto_encoding_base58_decode(incoming, incoming_length, &ptr, &hash_length); 77 | if (retVal == 0) 78 | return 0; 79 | // now we have the hash, build the object 80 | return ipfs_cid_new(0, hash, hash_length, CID_PROTOBUF, cid); 81 | } 82 | 83 | // TODO: finish this 84 | /* 85 | // it wasn't a sha_256 multihash, try to decode it using multibase 86 | size_t buffer_size = multibase_decode_size(incoming_length); 87 | if (buffer_size == 0) 88 | return 0; 89 | unsigned char buffer[buffer_size]; 90 | 91 | memset(buffer, 0, buffer_size); 92 | 93 | retVal = multibase_decode(incoming, incoming_length, buffer, buffer_size, &buffer_size); 94 | if (retVal == 0) 95 | return 0; 96 | 97 | return cid_cast(buffer, buffer_size, cid); 98 | */ 99 | return 0; 100 | } 101 | 102 | /*** 103 | * Turn a multibase decoded string of bytes into a Cid struct 104 | * @param incoming the multibase decoded array 105 | * @param incoming_size the size of the array 106 | * @param cid the Cid structure to fill 107 | */ 108 | int ipfs_cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid) { 109 | // this is a multihash 110 | if (incoming_size == 34 && incoming[0] == 18 && incoming[1] == 32) { 111 | cid->hash_length = mh_multihash_length(incoming, incoming_size); 112 | cid->codec = CID_PROTOBUF; 113 | cid->version = 0; 114 | 115 | mh_multihash_digest(incoming, incoming_size, &cid->hash, &cid->hash_length); 116 | return 1; 117 | } 118 | 119 | // This is not a multihash. Perhaps it is using varints. Try to peel the information out of the bytes. 120 | // first the version 121 | int pos = 0, retVal = 0; 122 | size_t num_bytes = 0; 123 | num_bytes = uvarint_decode32(&incoming[pos], incoming_size - pos, &cid->version); 124 | if (num_bytes < 0 || cid->version > 1 || cid->version < 0) 125 | return 0; 126 | pos = num_bytes; 127 | // now the codec 128 | uint32_t codec = 0; 129 | num_bytes = uvarint_decode32(&incoming[pos], incoming_size - pos, &codec); 130 | if (num_bytes < 0) 131 | return 0; 132 | cid->codec = codec; 133 | pos += num_bytes; 134 | // now what is left 135 | cid->hash_length = incoming_size - pos; 136 | cid->hash = &incoming[pos]; 137 | 138 | return 1; 139 | } 140 | -------------------------------------------------------------------------------- /cmd/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | cd ipfs; make all; 3 | 4 | clean: 5 | cd ipfs; make clean; -------------------------------------------------------------------------------- /cmd/ipfs/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../../c-libp2p/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = init.o main.o ../../commands/argument.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | ipfs: $(OBJS) 16 | $(CC) -o $@ $^ $(LFLAGS) 17 | 18 | all: $(OBJS) 19 | 20 | clean: 21 | rm -f *.o 22 | rm -f ipfs -------------------------------------------------------------------------------- /cmd/ipfs/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ipfs/cmd/ipfs/init.h" 5 | #include "ipfs/commands/request.h" 6 | #include "ipfs/commands/command_option.h" 7 | #include "ipfs/os/utils.h" 8 | #include "ipfs/core/ipfs_node.h" 9 | #include "ipfs/core/builder.h" 10 | #include "ipfs/repo/config/config.h" 11 | #include "ipfs/repo/fsrepo/fs_repo.h" 12 | 13 | const int nBitsForKeypairDefault = 2048; 14 | 15 | /*** 16 | * runs before major processing during initialization 17 | * @param request the request 18 | * @returns 0 if a problem, otherwise a 1 19 | */ 20 | int init_pre_run(struct Request* request) { 21 | //TODO: make sure daemon is not running 22 | return 1; 23 | } 24 | 25 | /** 26 | * This actually opens the repo and gets things set up 27 | * @param repo the repo information 28 | * @returns true(1) on success 29 | */ 30 | int initialize_ipns_keyspace(struct FSRepo* repo) { 31 | //open fs repo 32 | int retVal = ipfs_repo_fsrepo_open(repo); 33 | if (retVal == 0) 34 | return 0; 35 | //TODO: make a new node, then close it 36 | //TODO: setup offline routing on new node 37 | struct IpfsNode* ipfs_node; 38 | struct Context* ctx; 39 | struct BuildCfg* bld_cfg; 40 | //TODO: see line 185 of init.go, what does core.BldCfg{Repo: r} do? BldCfg is a structure 41 | retVal = ipfs_core_builder_new_node(ctx, bld_cfg, ipfs_node); 42 | //return namesys_initialize_keyspace(ctx, ipfs_node->DAG, ipfs_node->Namesys, ipfs_node->pinning, ipfs_node->private_key); 43 | return retVal; 44 | } 45 | 46 | /** 47 | * called by init_run, to do the heavy lifting 48 | * @param out_file an output stream (stdout) 49 | * @param repo_root a path that is where the .ipfs directory will be put 50 | * @param empty true(1) if empty, false(0) if not 51 | * @param num_bits_for_keypair number of bits for key pair 52 | * @param conf the configuration struct 53 | * @returns 0 on error, 1 on success 54 | */ 55 | int do_init(FILE* out_file, char* repo_root, int empty, int num_bits_for_keypair, struct RepoConfig* conf) { 56 | // make sure the directory is writable 57 | if (!os_utils_directory_writeable(repo_root)) 58 | return 0; 59 | // verify that it is not already initialized 60 | if (fs_repo_is_initialized(repo_root)) 61 | return 0; 62 | //TODO: If the conf is null, make one 63 | if ( conf->identity->peer_id == NULL) { 64 | int retVal = ipfs_repo_config_init(conf, num_bits_for_keypair, repo_root); 65 | if (retVal == 0) 66 | return 0; 67 | } 68 | // initialize the fs repo 69 | struct FSRepo* repo; 70 | int retVal = ipfs_repo_fsrepo_new(repo_root, conf, &repo); 71 | if (retVal == 0) 72 | return 0; 73 | retVal = ipfs_repo_fsrepo_init(repo); 74 | if (retVal == 0) 75 | return 0; 76 | 77 | //TODO: add default assets 78 | return initialize_ipns_keyspace(repo); 79 | } 80 | 81 | /*** 82 | * does major processing during initialization 83 | * @param request the request 84 | * @returns 0 if a problem, otherwise a 1 85 | */ 86 | int init_run(struct Request* request) { 87 | // TODO: make sure offline 88 | // TODO: check parameters for logic errors 89 | // TODO: Initialize 90 | struct RepoConfig* conf; 91 | int retVal = ipfs_repo_config_new(&conf); 92 | // TODO: handle files in request 93 | // do the heavy lifting 94 | int num_bits_for_key_pair = request->cmd.options[0]->default_int_val; 95 | return do_init(stdout, request->invoc_context->config_root, 1, num_bits_for_key_pair, conf); 96 | } 97 | 98 | /*** 99 | * does the cleanup after major processing during initialization 100 | * @param request the request 101 | * @returns 0 if a problem, otherwise a 1 102 | */ 103 | int init_post_run(struct Request* request) { 104 | // nothing to do 105 | return 1; 106 | } 107 | 108 | int ipfs_cmd_ipfs_init_command_new(struct Command* cmd) { 109 | int retVal = 1; 110 | 111 | // help text 112 | cmd->help_text.tagline = "Initializes IPFS config file."; 113 | cmd->help_text.short_description = "\nInitializes IPFS configuration files and generates a new keypair.\n\nipfs uses a repository in the local file system. By default, the repo is\nlocated at ~/.ipfs. To change the repo location, set the $IPFS_PATH\nenvironment variable.:\n\n export IPFS_PATH=/path/to/ipfsrepo"; 114 | 115 | cmd->argument_count = 1; 116 | cmd->option_count = 2; 117 | commands_command_init(cmd); 118 | // allocate memory for array of pointers 119 | retVal = commands_argument_init(cmd->arguments[0], "default-config", 0, 0, "Initialize with the given configuration"); 120 | if (retVal == 0) 121 | return 0; 122 | cmd->arguments[0]->enable_stdin = 1; 123 | 124 | // options 125 | cmd->options[0]->name_count = 2; 126 | retVal = commands_command_option_init(cmd->options[0], "Number of bits to use in the generated RSA private key"); 127 | cmd->options[0]->names[0] = "bits"; 128 | cmd->options[0]->names[1] = "b"; 129 | cmd->options[0]->kind = integer; 130 | cmd->options[0]->default_int_val = nBitsForKeypairDefault; 131 | cmd->options[1]->name_count = 2; 132 | retVal = commands_command_option_init(cmd->options[1], "Don't add and pin help files to the local storage"); 133 | cmd->options[1]->default_bool_val = 0; 134 | cmd->options[1]->names[0] = "empty-repo"; 135 | cmd->options[1]->names[1] = "e"; 136 | 137 | // function pointers 138 | cmd->pre_run = init_pre_run; 139 | cmd->run = init_run; 140 | cmd->post_run = init_post_run; 141 | 142 | return retVal; 143 | } 144 | 145 | /*** 146 | * Uninitializes all the dynamic memory caused by get_init_command 147 | * @param command the struct 148 | * @returns 0 on failure, otherwise 1 149 | */ 150 | int ipfs_cmd_ipfs_init_command_free(struct Command* command) { 151 | // NOTE: commands_command_free takes care of arguments and command_options 152 | commands_command_free(command); 153 | return 1; 154 | } 155 | -------------------------------------------------------------------------------- /cmd/ipfs/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void print_help(int longHelp, FILE* outStream) { 6 | 7 | } 8 | 9 | /** 10 | * command line interface to IPFS. 11 | * Steps: 12 | * 1) parse the command line 13 | * 2) if user requests help, display then exit 14 | * 3) run the command 15 | * 4) output the response 16 | * 5) if anything fails, print the error, maybe with help 17 | */ 18 | int main(int argc, char** argv) { 19 | 20 | if (argc == 2) { 21 | if (strncmp(argv[1], "help", 4) == 0) { 22 | print_help(1, stdout); 23 | exit(0); 24 | } else if (strncmp(argv[1], "--version", 9) == 0) { 25 | argv[1] = "version"; 26 | } 27 | } // end of help 28 | 29 | // parse command line into an invocation 30 | // exit 31 | exit(0); 32 | } 33 | -------------------------------------------------------------------------------- /commands/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include 3 | LFLAGS = 4 | DEPS = ../include/ipfs/commands/argument.h ../include/ipfs/commands/command_option.h \ 5 | ../include/ipfs/commands/command.h ../include/ipfs/commands/context.h \ 6 | ../include/ipfs/commands/req_log.h ../include/ipfs/commands/request.h 7 | OBJS = argument.o command.o command_option.o 8 | 9 | %.o: %.c $(DEPS) 10 | $(CC) -c -o $@ $< $(CFLAGS) 11 | 12 | all: $(OBJS) 13 | cd cli; make all; 14 | 15 | clean: 16 | rm -f *.o 17 | cd cli; make clean; 18 | -------------------------------------------------------------------------------- /commands/argument.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ipfs/commands/argument.h" 5 | 6 | int commands_argument_free(struct Argument* argument) { 7 | free(argument); 8 | return 1; 9 | } 10 | 11 | int commands_argument_init(struct Argument* argument, char* name, int required, int variadic, char* description) { 12 | argument->name = name; 13 | argument->required = required; 14 | argument->variadic = variadic; 15 | argument->description = description; 16 | return 1; 17 | } 18 | 19 | int commands_argument_string_init(struct Argument* argument, char* name, int required, int variadic, char* description) { 20 | int retVal = commands_argument_init(argument, name, required, variadic, description); 21 | if (retVal) 22 | argument->type = string; 23 | return retVal; 24 | } 25 | 26 | int commands_argument_file_init(struct Argument* argument, char* name, int required, int variadic, char* description) { 27 | int retVal = commands_argument_init(argument, name, required, variadic, description); 28 | if (retVal) 29 | argument->type = file; 30 | return retVal; 31 | } 32 | -------------------------------------------------------------------------------- /commands/cli/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../../c-libp2p/include 3 | LFLAGS = 4 | DEPS = parse.h 5 | OBJS = parse.o 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | all: $(OBJS) 11 | 12 | clean: 13 | rm -f *.o 14 | -------------------------------------------------------------------------------- /commands/cli/parse.c: -------------------------------------------------------------------------------- 1 | #include "ipfs/commands/cli/parse.h" 2 | 3 | int cli_parse(char** params, FILE* inStream, struct Command* cmd, struct Request* request) { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /commands/command.c: -------------------------------------------------------------------------------- 1 | // 2 | // command.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | #include 9 | 10 | #include "ipfs/commands/command.h" 11 | 12 | int commands_command_init(struct Command* cmd) { 13 | // allocate memory for Argument array 14 | cmd->arguments = malloc(cmd->argument_count * sizeof(struct Argument*)); 15 | if (cmd->arguments == NULL) 16 | return 0; 17 | // allocate memory for each argument 18 | for(int i = 0; i < cmd->argument_count; i++) 19 | cmd->arguments[i] = malloc(sizeof(struct Argument)); 20 | 21 | // allocate memory for CommandOption array 22 | cmd->options = malloc(cmd->option_count * sizeof(struct CommandOption*)); 23 | if (cmd->options == NULL) 24 | return 0; 25 | // allocate memory for each CommandOption 26 | for(int i = 0; i < cmd->option_count; i++) 27 | cmd->options[i] = malloc(sizeof(struct CommandOption)); 28 | return 1; 29 | } 30 | 31 | int commands_command_free(struct Command* cmd) { 32 | // arguments 33 | for(int i = 0; i < cmd->argument_count; i++) 34 | commands_argument_free(cmd->arguments[i]); 35 | free(cmd->arguments); 36 | 37 | //command options 38 | for(int i = 0; i < cmd->option_count; i++) 39 | commands_command_option_free(cmd->options[i]); 40 | free(cmd->options); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /commands/command_option.c: -------------------------------------------------------------------------------- 1 | // 2 | // option.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/26/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "ipfs/commands/command_option.h" 13 | 14 | int commands_command_option_init(struct CommandOption* option, char* description) { 15 | option->description = description; 16 | // allocate memory for names 17 | option->names = malloc(option->name_count * sizeof(char*)); 18 | if (option->names == NULL) 19 | return 0; 20 | return 1; 21 | } 22 | 23 | int commands_command_option_free(struct CommandOption* option) { 24 | free(option->names); 25 | free(option); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include 3 | LFLAGS = 4 | DEPS = builder.h ipfs_node.h 5 | OBJS = builder.o 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | all: $(OBJS) 11 | 12 | clean: 13 | rm -f *.o 14 | -------------------------------------------------------------------------------- /core/builder.c: -------------------------------------------------------------------------------- 1 | // 2 | // builder.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include "ipfs/core/builder.h" 10 | 11 | int ipfs_core_builder_new_node(struct Context* context, struct BuildCfg* build_cfg, struct IpfsNode* buildConfig) { 12 | // TODO: Implement this method 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /datastore/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../lmdb/libraries/liblmdb 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = ../include/ipfsdatastore/ds_helper.h 10 | OBJS = ds_helper.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /datastore/ds_helper.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Some code to help with the datastore / blockstore interface 3 | */ 4 | #include "libp2p/crypto/encoding/base32.h" 5 | #include "ipfs/datastore/ds_helper.h" 6 | /** 7 | * Generate a key based on the passed in binary_array 8 | * @param binary_array what to base the key on 9 | * @param array_length the size of the binary array 10 | * @param results where the key will be put 11 | * @param max_results_length the size of the results buffer 12 | * @param results_length the length of the generated key 13 | * @returns true(1) on success 14 | */ 15 | int ipfs_datastore_helper_ds_key_from_binary(unsigned char* binary_array, size_t array_length, 16 | char* results, size_t max_results_length, size_t* results_length) { 17 | 18 | size_t encoded_length = libp2p_crypto_encoding_base32_encode_size(array_length); 19 | if (encoded_length > max_results_length) 20 | return 0; 21 | 22 | *results_length = max_results_length; 23 | int retVal = libp2p_crypto_encoding_base32_encode(binary_array, array_length, results, results_length); 24 | if (retVal == 0) { 25 | *results_length = 0; 26 | return 0; 27 | } 28 | 29 | return 1; 30 | } 31 | 32 | /** 33 | * Generate a binary array based on the passed in datastore key 34 | * @param ds_key the base32 encoded key 35 | * @param key_length the length of the base32 "string" 36 | * @param binary_array where to put the decoded value 37 | * @param max_binary_array_length the memory size of binary_array 38 | * @param completed_binary_array_length the length of what was written to the binary_array 39 | * @returns true(1) on success 40 | */ 41 | int ipfs_datastore_helper_binary_from_ds_key(unsigned char* ds_key, size_t key_length, unsigned char* binary_array, 42 | size_t max_binary_array_length, size_t* completed_binary_array_length) { 43 | 44 | size_t decoded_length = libp2p_crypto_encoding_base32_decode_size(key_length); 45 | if (decoded_length > max_binary_array_length) 46 | return 0; 47 | 48 | *completed_binary_array_length = max_binary_array_length; 49 | int retVal = libp2p_crypto_encoding_base32_decode(ds_key, key_length, binary_array, completed_binary_array_length); 50 | if (retVal == 0) { 51 | *completed_binary_array_length = 0; 52 | return 0; 53 | } 54 | return 1; 55 | } 56 | -------------------------------------------------------------------------------- /datastore/key.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * Constructs a new "clean" key. Will remove things like slashes 5 | * @param input the input 6 | * @param output the output 7 | * @param max_output_length the amount of memory allocated for output 8 | * @param actual_output_length the amount of bytes written to output 9 | * @returns true(1) on success 10 | */ 11 | int ipfs_datastore_key_new(const char* input, char* output, size_t max_output_length, size_t* actual_output_length) { 12 | //TODO: clean the input 13 | if (strlen(input) + 1 > max_output_length) 14 | return 0; 15 | 16 | memcpy(output, input, strlen(input) + 1); 17 | return 1; 18 | } 19 | -------------------------------------------------------------------------------- /flatfs/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | CFLAGS = -O0 -I../include -I../../c-libp2p/include 4 | 5 | ifdef DEBUG 6 | CFLAGS += -g3 7 | endif 8 | 9 | LFLAGS = 10 | DEPS = ../include/flatfs/flatfs.h 11 | OBJS = flatfs.o 12 | 13 | %.o: %.c $(DEPS) 14 | $(CC) -c -o $@ $< $(CFLAGS) 15 | 16 | all: $(OBJS) 17 | 18 | clean: 19 | rm -f *.o 20 | -------------------------------------------------------------------------------- /flatfs/flatfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * a datastore implementation that stores all 3 | * objects in a 2 level directory structure in 4 | * the local file system, regardless of the 5 | * hierarchy of the keys. Modeled after go-ds-flatfs 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "ipfs/os/utils.h" 13 | 14 | #define FLATFS_MAX_PREFIX_LENGTH 16 15 | 16 | /** 17 | * Helper (private) methods 18 | */ 19 | 20 | /** 21 | * remove beginning slash from string 22 | * @param in the filename to look at 23 | * @param out a place to store the results 24 | * @param the size of out 25 | * @returns true(1) on success 26 | */ 27 | int ipfs_flatfs_remove_preceeding_slash(const char* in, char* out, size_t max_size) { 28 | // make sure max_size is reasonable 29 | if (max_size < strlen(in) + 1) 30 | return 0; 31 | int pos = 0; 32 | while (in[pos] == '/') 33 | pos++; 34 | strncpy(out, &in[pos], strlen(in) - pos); 35 | out[strlen(in) - pos] = 0; 36 | return 1; 37 | } 38 | 39 | /** 40 | * Create a directory if it doesn't already exist 41 | * @param full_directory the full path 42 | * @returns true(1) on successful create or if it already exists and is writable. false(0) otherwise. 43 | */ 44 | int ipfs_flatfs_create_directory(const char* full_directory) { 45 | // shortcut 46 | if (os_utils_directory_writeable(full_directory)) 47 | return 1; 48 | // is it there, just not writeable? 49 | if (os_utils_directory_exists(full_directory)) { 50 | return 0; 51 | } 52 | // it is not there, create it 53 | if (mkdir(full_directory, S_IRWXU) == -1) 54 | return 0; 55 | 56 | return 1; 57 | } 58 | 59 | /*** 60 | * public methods 61 | */ 62 | 63 | /** 64 | * Given a filename (usually a long hash), derive a subdirectory name 65 | * @param datastore_path the path to the datastore 66 | * @param proposed_filename the filename to use 67 | * @param derived_path the complete pathname to the directory that should contain the proposed_filename 68 | * @param max_derived_path_length the maximum memory allocated for derived_path 69 | * @returns true(1) on success 70 | */ 71 | int ipfs_flatfs_get_directory(const char* datastore_path, const char* proposed_filename, 72 | char* derived_path, size_t max_derived_path_length) { 73 | // make sure max_derived_path_length is a reasonable number 74 | if (max_derived_path_length < strlen(datastore_path) + 17) 75 | return 0; 76 | 77 | // remove slash prefix if there is one 78 | char buffer[max_derived_path_length]; 79 | int retVal = ipfs_flatfs_remove_preceeding_slash(proposed_filename, buffer, max_derived_path_length); 80 | if (retVal == 0) 81 | return 0; 82 | 83 | // make it 16 characters 84 | if (strlen(buffer) < 16) { 85 | int pos = strlen(buffer); 86 | int lacking = 16 - pos; // how many we should add 87 | memset(&buffer[strlen(buffer)], '_', lacking); 88 | buffer[pos + lacking] = 0; 89 | } 90 | // it may be too long, cut it 91 | if (strlen(buffer) > 16) 92 | buffer[16] = 0; 93 | retVal = os_utils_filepath_join(datastore_path, buffer, derived_path, max_derived_path_length); 94 | return retVal; 95 | } 96 | 97 | /** 98 | * Given the proposed filename, return the acutal filename on the disk (clean the name and add .data suffix) 99 | * @param proposed_filename the start 100 | * @param derived_filename the results 101 | * @param max_derived_filename_length the buffer size 102 | * @returns true(1) on success 103 | */ 104 | int ipfs_flatfs_get_filename(const char* proposed_filename, char* derived_filename, size_t max_derived_filename_length) { 105 | // get rid of slashes 106 | char buffer[max_derived_filename_length]; 107 | int retVal = ipfs_flatfs_remove_preceeding_slash(proposed_filename, buffer, max_derived_filename_length); 108 | if (retVal == 0) 109 | return 0; 110 | 111 | // make sure we have space 112 | if (max_derived_filename_length < strlen(buffer) + 6) // ".data" plus terminating null 113 | return 0; 114 | 115 | // add the suffix 116 | strncat(buffer, ".data", 6); 117 | 118 | // put it in the result buffer 119 | strncpy(derived_filename, buffer, strlen(buffer) + 1); 120 | 121 | return 1; 122 | } 123 | 124 | /** 125 | * Combines the datastore path, the directory (derived from the filename itself), the proposed 126 | * filename, and the suffix (.data) to build a complete filename on the disk 127 | * @param datastore_path where the datastore is 128 | * @param proposed_filename the filename we want to use 129 | * @param derived_full_filename where the results will be put 130 | * @param max_derived_filename_length the size of memory allocated for "derived_full_filename" 131 | * @returns true(1) on success 132 | */ 133 | int ipfs_flatfs_get_full_filename(const char* datastore_path, const char* proposed_filename, 134 | char* derived_full_filename, size_t max_derived_filename_length) { 135 | // get rid of preceeding / 136 | char directory[max_derived_filename_length]; 137 | int retVal = ipfs_flatfs_remove_preceeding_slash(proposed_filename, directory, max_derived_filename_length); 138 | if (retVal == 0) 139 | return 0; 140 | 141 | // start with the path 142 | retVal = ipfs_flatfs_get_directory(datastore_path, proposed_filename, directory, max_derived_filename_length); 143 | if (retVal == 0) 144 | return retVal; 145 | 146 | // now get the filename 147 | char actual_filename[max_derived_filename_length]; 148 | retVal = ipfs_flatfs_get_filename(proposed_filename, actual_filename, max_derived_filename_length); 149 | if (retVal == 0) 150 | return 0; 151 | 152 | // now merge the two 153 | retVal = os_utils_filepath_join(directory, actual_filename, derived_full_filename, max_derived_filename_length); 154 | 155 | return retVal; 156 | } 157 | 158 | 159 | /** 160 | * Write a file given the key and the contents 161 | * @param datastore_path the root of the flatfs datastore 162 | * @param key the "filename" 163 | * @para byte the contents of the file as a byte array 164 | * @param num_bytes the length of the byte array 165 | */ 166 | int ipfs_flatfs_put(const char* datastore_path, const char* key, unsigned char* byte, size_t num_bytes) { 167 | size_t filename_length = strlen(datastore_path) + strlen(key) + 24; // subdirectory is 16, 2 slashes, .data suffix, terminating null 168 | // subdirectory 169 | char full_filename[filename_length]; 170 | int retVal = ipfs_flatfs_get_directory(datastore_path, key, full_filename, filename_length); 171 | if (retVal == 0) 172 | return 0; 173 | retVal = ipfs_flatfs_create_directory(full_filename); 174 | if (retVal == 0) 175 | return 0; 176 | 177 | // filename 178 | retVal = ipfs_flatfs_get_full_filename(datastore_path, key, full_filename, filename_length); 179 | if (retVal == 0) 180 | return 0; 181 | 182 | //TODO: Error checking (i.e. too many open files 183 | 184 | // write temp file 185 | char temp_filename[filename_length + 5]; 186 | strncpy(temp_filename, full_filename, strlen(full_filename) + 1); 187 | strcat(temp_filename, ".tmp"); 188 | FILE* out = fopen(temp_filename, "w"); 189 | size_t bytes_written = fwrite(byte, num_bytes, 1, out); 190 | fclose(out); 191 | 192 | // rename temp file to real name 193 | retVal = rename(temp_filename, full_filename); 194 | if (retVal != 0) 195 | return 0; 196 | 197 | return bytes_written == num_bytes; 198 | } 199 | -------------------------------------------------------------------------------- /include/ipfs/blocks/block.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * IPFS has the notion of storage blocks. 3 | */ 4 | 5 | #ifndef __IPFS_BLOCKS_BLOCK_H__ 6 | #define __IPFS_BLOCKS_BLOCK_H__ 7 | 8 | #include "ipfs/cid/cid.h" 9 | 10 | struct Block { 11 | struct Cid* cid; 12 | unsigned char* data; 13 | size_t data_length; 14 | }; 15 | 16 | /*** 17 | * Create a new block based on the incoming data. 18 | * @param data the data to base the block on 19 | * @param data_size the length of the data array 20 | * @param block a pointer to the struct Block that will be created 21 | * @returns true(1) on success 22 | */ 23 | int ipfs_blocks_block_new(const unsigned char* data, size_t data_size, struct Block** block); 24 | 25 | /*** 26 | * Free resources used by the creation of a block 27 | * @param block the block to free 28 | * @returns true(1) on success 29 | */ 30 | int ipfs_blocks_block_free(struct Block* block); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/ipfs/blocks/blockstore.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * a thin wrapper over a datastore for getting and putting block objects 3 | */ 4 | 5 | #ifndef __IPFS_BLOCKS_BLOCKSTORE_H__ 6 | #ifndef __IPFS_BLOCKS_BLOCKSTORE_H__ 7 | 8 | /** 9 | * Delete a block based on its Cid 10 | * @param cid the Cid to look for 11 | * @param returns true(1) on success 12 | */ 13 | int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo); 14 | 15 | /*** 16 | * Determine if the Cid can be found 17 | * @param cid the Cid to look for 18 | * @returns true(1) if found 19 | */ 20 | int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo); 21 | 22 | /*** 23 | * Find a block based on its Cid 24 | * @param cid the Cid to look for 25 | * @param block where to put the data to be returned 26 | * @returns true(1) on success 27 | */ 28 | int ipfs_blockstore_get(struct Cid* cid, struct Block* block, struct FSRepo* fs_repo); 29 | 30 | /*** 31 | * Put a block in the blockstore 32 | * @param block the block to store 33 | * @returns true(1) on success 34 | */ 35 | int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo); 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/ipfs/cid/cid.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * A content id 3 | */ 4 | 5 | #ifndef __IPFS_CID_CID_H 6 | #define __IPFS_CID_CID_H 7 | 8 | #include 9 | 10 | #define CID_PROTOBUF 0x70 11 | #define CID_CBOR 0x71 12 | #define CID_RAW 0x72 13 | #define CID_JSON 0x73 14 | #define CID_ETHEREUM_BLOCK 0x90 15 | #define CID_ETHEREUM_TX 0x91 16 | #define CID_BITCOIN_BLOCK 0xb0 17 | #define CID_BITCOIN_TX 0xb1 18 | #define CID_ZCASH_BLOCK 0xc0 19 | #define CID_ZCASH_TX 0xc1 20 | 21 | struct Cid { 22 | int version; 23 | char codec; 24 | unsigned char* hash; // a multihash 25 | size_t hash_length; 26 | }; 27 | 28 | 29 | /** 30 | * Create a new CID based on the given hash 31 | * @param version the version 32 | * @param hash the multihash 33 | * @param hash_length the length of the multihash in bytes 34 | * @param codec the codec to be used (NOTE: For version 0, this should be CID_PROTOBUF) 35 | * @param cid where to put the results 36 | * @returns true(1) on success 37 | */ 38 | int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** cid); 39 | 40 | /*** 41 | * Free the resources from a Cid 42 | * @param cid the struct 43 | * @returns 1 44 | */ 45 | int ipfs_cid_free(struct Cid* cid); 46 | 47 | /*** 48 | * Fill a Cid struct based on a base 58 encoded string 49 | * @param incoming the string 50 | * @param incoming_size the size of the string 51 | * @cid the Cid struct to fill 52 | * @return true(1) on success 53 | */ 54 | int ipfs_cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid** cid); 55 | 56 | /*** 57 | * Turn a multibase decoded string of bytes into a Cid struct 58 | * @param incoming the multibase decoded array 59 | * @param incoming_size the size of the array 60 | * @param cid the Cid structure to fill 61 | */ 62 | int ipfs_cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/ipfs/cmd/ipfs/init.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Initialize an IPFS repository 3 | */ 4 | #ifndef __CMD_IPFS_INIT_H__ 5 | #define __CMD_IPFS_INIT_H__ 6 | 7 | #include "ipfs/commands/command.h" 8 | 9 | /*** 10 | * Returns a command structure customized for the init command 11 | * @param command the struct to fill 12 | * @returns 0 on failure, otherwise 1 13 | */ 14 | int ipfs_cmd_ipfs_init_command_new(struct Command* command); 15 | 16 | /*** 17 | * Uninitializes all the dynamic memory caused by get_init_command 18 | * @param command the struct 19 | * @returns 0 on failure, otherwise 1 20 | */ 21 | int ipfs_cmd_ipfs_init_command_free(struct Command* command); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ipfs/commands/argument.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_ARGUMENT_H__ 2 | #define __COMMANDS_ARGUMENT_H__ 3 | 4 | enum ArgumentType { string, file }; 5 | 6 | struct Argument { 7 | char* name; 8 | enum ArgumentType type; 9 | int required; 10 | int variadic; 11 | int supports_stdin; 12 | int recursive; 13 | char* description; 14 | int enable_stdin; 15 | }; 16 | 17 | /** 18 | * Initialize an argument structure 19 | * @param argument the structure to initialize 20 | * @param name the name of the argument 21 | * @param required true(1) if the argument is required 22 | * @param variadic true(1) if the argument is variadic 23 | * @param description the description of the argument 24 | * @returns true(1) if all went okay 25 | */ 26 | int commands_argument_init(struct Argument* argument, char* name, int required, int variadic, char* description); 27 | /*** 28 | * Free resources caused by init of argument 29 | * @param argument the structure to clean up 30 | * @returns true(1) 31 | */ 32 | int commands_argument_free(struct Argument* argument); 33 | /*** 34 | * initializes a string type argument 35 | * @param argument the structure to initialize 36 | * @param name the name of the argument 37 | * @param required true(1) if the argument is required 38 | * @param variadic true(1) if the argument is variadic 39 | * @param description the description of the argument 40 | * @returns true(1) if all went okay 41 | */ 42 | int commands_argument_string_init(struct Argument* argument, char* name, int required, int variadic, char* description); 43 | /*** 44 | * initializes a file type argument 45 | * @param argument the structure to initialize 46 | * @param name the name of the argument 47 | * @param required true(1) if the argument is required 48 | * @param variadic true(1) if the argument is variadic 49 | * @param description the description of the argument 50 | * @returns true(1) if all went okay 51 | */ 52 | int commands_argument_file_init(struct Argument* argument, char* name, int required, int variadic, char* description); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/ipfs/commands/cli/parse.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * methods to parse the command line parameters 3 | */ 4 | #ifndef __COMMANDS_CLI_PARSE_H__ 5 | #define __COMMANDS_CLI_PARSE_H__ 6 | 7 | #include 8 | 9 | #include "ipfs/commands/command.h" 10 | 11 | /*** 12 | * turns parameters passed in into a Request struct 13 | * @param params the command line parameters 14 | * @param inStream a stream (for piped input) 15 | * @param cmd the command struct, already initialized 16 | * @param request the end result, something that can be passed on that actually does something 17 | * @returns 0 if something bad happens, otherwise 1 18 | */ 19 | int cli_parse(char** params, FILE* inStream, struct Command* cmd, struct Request* request); 20 | 21 | int cli_parse_opts(char** params, struct Command* cmd, char* path, char** stringVals); 22 | 23 | #endif /* parse_h */ 24 | -------------------------------------------------------------------------------- /include/ipfs/commands/command.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * The structures to commands 3 | */ 4 | 5 | #ifndef __COMMANDS_COMMAND_H__ 6 | #define __COMMANDS_COMMAND_H__ 7 | 8 | #include "ipfs/commands/argument.h" 9 | //#include "ipfs/commands/request.h" 10 | #include "command_option.h" 11 | 12 | // forward declaration 13 | struct Request; 14 | 15 | struct HelpText { 16 | char* tagline; 17 | char* short_description; 18 | char** synopsis_options_values; 19 | 20 | // optional 21 | char* usage; 22 | char* long_description; 23 | char* options; 24 | char* subcommands; 25 | char* synopsis; 26 | }; 27 | 28 | struct Command { 29 | struct CommandOption** options; 30 | int option_count; 31 | struct Argument** arguments; 32 | int argument_count; 33 | int (*pre_run)(struct Request*); 34 | int (*run)(struct Request*); 35 | int (*post_run)(struct Request*); 36 | //struct marshaller** marshallers; 37 | struct HelpText help_text; 38 | 39 | // a boolean to determine if this is an external 40 | // binary. 41 | int external; 42 | 43 | //struct type return_type; 44 | char** subcommands; 45 | }; 46 | 47 | // construction/destruction 48 | int commands_command_init(struct Command* cmd); 49 | int commands_command_free(struct Command* cmd); 50 | 51 | #endif // command.h 52 | -------------------------------------------------------------------------------- /include/ipfs/commands/command_option.h: -------------------------------------------------------------------------------- 1 | // 2 | // option.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/26/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __COMMANDS_COMMAND_OPTION_H__ 10 | #define __COMMANDS_COMMAND_OPTION_H__ 11 | 12 | #include 13 | 14 | enum Kind { invalid, boolean, integer, unsignedInt, decimal, str }; 15 | 16 | struct CommandOption { 17 | char** names; 18 | int name_count; 19 | enum Kind kind; 20 | char* description; 21 | int default_int_val; 22 | int default_bool_val; 23 | uint32_t default_uint_val; 24 | float default_float_val; 25 | char* default_string_val; 26 | }; 27 | 28 | /*** 29 | * Allocate the resources needed for a command option 30 | * @param option the CommandOption to initialize 31 | * @param description a description of this CommandOption 32 | * @returns true(1) on success 33 | */ 34 | int commands_command_option_init(struct CommandOption* option, char* description); 35 | 36 | /*** 37 | * Cleans up the resources of a CommandOption 38 | * @param option the CommandOption to clean up 39 | * @returns true(1) 40 | */ 41 | int commands_command_option_free(struct CommandOption* option); 42 | 43 | #endif /* option_h */ 44 | -------------------------------------------------------------------------------- /include/ipfs/commands/context.h: -------------------------------------------------------------------------------- 1 | // 2 | // context.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __COMMANDS_CONTEXT_H__ 10 | #define __COMMANDS_CONTEXT_H__ 11 | 12 | #include "ipfs/commands/req_log.h" 13 | #include "ipfs/repo/config/config.h" 14 | #include "ipfs/core/ipfs_node.h" 15 | 16 | struct Context { 17 | int online; 18 | char* config_root; 19 | struct ReqLog req_log; 20 | struct RepoConfig config; 21 | int (*load_config)(char* path); 22 | struct IpfsNode node; 23 | int (*construct_node)(struct IpfsNode* node); 24 | }; 25 | 26 | #endif /* context_h */ 27 | -------------------------------------------------------------------------------- /include/ipfs/commands/req_log.h: -------------------------------------------------------------------------------- 1 | // 2 | // req_log.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __COMMANDS_REQ_LOG_H__ 10 | #define __COMMANDS_REQ_LOG_H__ 11 | 12 | struct ReqLogEntry { 13 | long start_time; 14 | long end_time; 15 | int active; 16 | char* command; 17 | struct Option** options; 18 | struct Argument** args; 19 | int id; 20 | struct Request* req; 21 | struct ReqLog* log; 22 | }; 23 | 24 | struct ReqLog { 25 | struct ReqLogEntry** requests; 26 | int next_id; 27 | //mutex lock; 28 | long keep_duration; 29 | }; 30 | 31 | #endif /* req_log_h */ 32 | -------------------------------------------------------------------------------- /include/ipfs/commands/request.h: -------------------------------------------------------------------------------- 1 | // 2 | // request.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/26/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __COMMANDS_REQUEST_H__ 10 | #define __COMMANDS_REQUEST_H__ 11 | 12 | #include "context.h" 13 | #include "command.h" 14 | 15 | struct Request { 16 | char* path; 17 | //optmap options; 18 | char* arguments; 19 | //file[] files; 20 | struct Command cmd; 21 | struct Context* invoc_context; 22 | //context rctx; 23 | //map[string]Option optionDefs; 24 | //map[string]interface{} values; 25 | //ioReader stdin; 26 | }; 27 | 28 | #endif /* request_h */ 29 | -------------------------------------------------------------------------------- /include/ipfs/core/builder.h: -------------------------------------------------------------------------------- 1 | // 2 | // builder.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __CORE_BUILDER_H__ 10 | #define __CORE_BUILDER_H__ 11 | 12 | #include 13 | 14 | #include "ipfs/commands/context.h" 15 | #include "ipfs/repo/config/config.h" 16 | 17 | struct BuildCfg { 18 | int online; 19 | // ExtraOpts map[string]bool 20 | int permanent; 21 | int nil_repo; 22 | //struct RoutingOption routing; 23 | //struct HostOption host; 24 | //struct Repo repo; 25 | }; 26 | 27 | int ipfs_core_builder_new_node(struct Context* context, struct BuildCfg* build_cfg, struct IpfsNode* buildConfig); 28 | 29 | #endif /* builder_h */ 30 | -------------------------------------------------------------------------------- /include/ipfs/core/ipfs_node.h: -------------------------------------------------------------------------------- 1 | // 2 | // ipfs_node.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __CORE_IPFS_NODE_H__ 10 | #define __CORE_IPFS_NODE_H__ 11 | 12 | struct IpfsNode { 13 | //struct PeerId identity; 14 | //struct Repo repo; 15 | //struct Pinner pinning; // an interface 16 | //struct Mount** mounts; 17 | //struct PrivKey* private_key; 18 | // TODO: Add more here 19 | }; 20 | 21 | #endif /* ipfs_node_h */ 22 | -------------------------------------------------------------------------------- /include/ipfs/datastore/ds_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Some code to help with the datastore / blockstore interface 3 | */ 4 | #ifndef __IPFS_DATASTORE_DS_HELPER_H__ 5 | #define __IPFS_DATASTORE_DS_HELPER_H__ 6 | 7 | #include 8 | 9 | /** 10 | * Generate a key based on the passed in binary_array 11 | * @param binary_array what to base the key on 12 | * @param array_length the size of the binary array 13 | * @param results where the key will be put 14 | * @param max_results_length the size of the results buffer 15 | * @param results_length the length of the generated key 16 | * @returns true(1) on success 17 | */ 18 | int ipfs_datastore_helper_ds_key_from_binary(unsigned char* binary_array, size_t array_length, 19 | char* results, size_t max_results_length, size_t* results_length); 20 | 21 | /** 22 | * Generate a binary array based on the passed in datastore key 23 | * @param ds_key the base32 encoded key 24 | * @param key_length the length of the base32 "string" 25 | * @param binary_array where to put the decoded value 26 | * @param max_binary_array_length the memory size of binary_array 27 | * @param completed_binary_array_length the length of what was written to the binary_array 28 | * @returns true(1) on success 29 | */ 30 | int ipfs_datastore_helper_binary_from_ds_key(unsigned char* ds_key, size_t key_length, unsigned char* binary_array, 31 | size_t max_binary_array_length, size_t* completed_binary_array_length); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/ipfs/datastore/key.h: -------------------------------------------------------------------------------- 1 | #ifndef __IPFS_DATASTORE_KEY_H__ 2 | #define __IPFS_DATASTORE_KEY_H__ 3 | 4 | /** 5 | * Constructs a new "clean" key. Will remove things like slashes 6 | * @param input the input 7 | * @param output the output 8 | * @param max_output_length the amount of memory allocated for output 9 | * @param actual_output_length the amount of bytes written to output 10 | * @returns true(1) on success 11 | */ 12 | int ipfs_datastore_key_new(const char* input, char* output, size_t max_output_length, size_t* actual_output_length); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/ipfs/flatfs/flatfs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * a datastore implementation that stores all 3 | * objects in a 2 level directory structure in 4 | * the local file system, regardless of the 5 | * hierarchy of the keys. Modeled after go-ds-flatfs 6 | */ 7 | 8 | /** 9 | * Given a filename (usually a long hash), derive a subdirectory name 10 | * @param datastore_path the path to the datastore 11 | * @param proposed_filename the filename to use 12 | * @param derived_path the complete pathname to the directory that should contain the proposed_filename 13 | * @param max_derived_path_length the maximum memory allocated for derived_path 14 | * @returns true(1) on success 15 | */ 16 | int ipfs_flatfs_get_directory(const char* datastore_path, const char* proposed_filename, 17 | char* derived_path, size_t max_derived_path_length); 18 | 19 | /** 20 | * Given the proposed filename, return the acutal filename on the disk (clean the name and add .data suffix) 21 | * @param proposed_filename the start 22 | * @param derived_filename the results 23 | * @param max_derived_filename_length the buffer size 24 | * @returns true(1) on success 25 | */ 26 | int ipfs_flatfs_get_filename(const char* proposed_filename, char* derived_filename, size_t max_derived_filename_length); 27 | 28 | /** 29 | * Combines the datastore path, the directory (derived from the filename itself), the proposed 30 | * filename, and the suffix (.data) to build a complete filename on the disk 31 | * @param datastore_path where the datastore is 32 | * @param proposed_filename the filename we want to use 33 | * @param derived_full_filename where the results will be put 34 | * @param max_derived_filename_length the size of memory allocated for "derived_full_filename" 35 | * @returns true(1) on success 36 | */ 37 | int ipfs_flatfs_get_full_filename(const char* datastore_path, const char* proposed_filename, 38 | char* derived_full_filename, size_t max_derived_filename_length); 39 | -------------------------------------------------------------------------------- /include/ipfs/multibase/multibase.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __IPFS_MULTIBASE_MULTIBASE_H__ 4 | #define __IPFS_MULTIBASE_MULTIBASE_H__ 5 | 6 | // the first digit of data, to determine the encoding used or using 7 | #define MULTIBASE_BASE1 '1' 8 | #define MULTIBASE_BASE2 '0' 9 | #define MULTIBASE_BASE8 '7' 10 | #define MULTIBASE_BASE10 '9' 11 | #define MULTIBASE_BASE16 'f' 12 | #define MULTIBASE_BASE58_FLICKR 'Z' 13 | #define MULTIBASE_BASE58_BTC 'z' 14 | 15 | /** 16 | * Encode data in multibase format 17 | * @param base the format to use (i.e. MULTIBASE_BASE58_BTC) 18 | * @param incoming the data to encode 19 | * @param incoming_length the length of the data to encode 20 | * @param results where to put the results 21 | * @param results_max_length the size of the results buffer 22 | * @param results_length the size of the results after being encoded 23 | * @returns true(1) on success 24 | */ 25 | int multibase_encode(const char base, const unsigned char* incoming, size_t incoming_length, unsigned char* results, size_t results_max_length, size_t* results_length); 26 | 27 | /*** 28 | * Calculates the size of the buffer neccessary to encode the incoming byte array 29 | * @param base the encoding to use 30 | * @param incoming the incoming array of bytes 31 | * @param incoming_length the length of the array in bytes 32 | * @returns the appropriate size of the buffer 33 | */ 34 | int multibase_encode_size(const char base, const unsigned char* incoming, size_t incoming_length); 35 | 36 | /** 37 | * Decode data that was encoded in multibase format 38 | * @param incoming the data to decode 39 | * @param incoming_length the length of the data to decode 40 | * @param results where to put the results 41 | * @param results_max_length the size of the results buffer 42 | * @param results_length the size of the results after being encoded 43 | * @returns true(1) on success 44 | */ 45 | int multibase_decode(const unsigned char* incoming, size_t incoming_length, unsigned char* results, size_t results_max_length, size_t* results_length); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/ipfs/namesys/namesys.h: -------------------------------------------------------------------------------- 1 | #ifndef NAMESYS_H 2 | #define NAMESYS_H 3 | 4 | #define DefaultDepthLimit 32 5 | 6 | #ifdef NAMESYS_C 7 | char *ErrNamesys[] = { 8 | NULL, 9 | "ErrAllocFailed", 10 | "ErrNULLPointer", 11 | "ErrPipe", 12 | "ErrPoll", 13 | "Could not publish name." 14 | "Could not resolve name.", 15 | "Could not resolve name (recursion limit exceeded).", 16 | "expired record", 17 | "unrecognized validity type", 18 | "not a valid proquint string", 19 | "not a valid domain name", 20 | "not a valid dnslink entry" 21 | }; 22 | #else 23 | extern char *ErrNamesys; 24 | #endif // NAMESYS_C 25 | 26 | enum { 27 | ErrAllocFailed = 1, 28 | ErrNULLPointer, 29 | ErrPipe, 30 | ErrPoll, 31 | ErrPublishFailed, 32 | ErrResolveFailed, 33 | ErrResolveRecursion, 34 | ErrExpiredRecord, 35 | ErrUnrecognizedValidity, 36 | ErrInvalidProquint, 37 | ErrInvalidDomain, 38 | ErrInvalidDNSLink 39 | } NamesysErrs; 40 | 41 | typedef struct s_resolvers { 42 | char *protocol; 43 | int (*func)(char**, char*); 44 | } resolvers; 45 | 46 | typedef struct s_resolver { 47 | // resolveOnce looks up a name once (without recursion). 48 | int (*resolveOnce) (char **, char *); 49 | } resolver; 50 | 51 | //TODO ciPrivKey from c-libp2p-crypto 52 | typedef void* ciPrivKey; 53 | 54 | typedef struct s_publishers { 55 | char *protocol; 56 | int (*func) (ciPrivKey, char*); 57 | int (*func_eol) (ciPrivKey, char*, time_t); 58 | } publishers; 59 | 60 | typedef struct s_mpns { 61 | resolvers *resolver; 62 | publishers *Publisher; 63 | } mpns; 64 | 65 | typedef struct s_tlds { 66 | char *str; 67 | int condition; 68 | } tlds; 69 | 70 | int resolve (resolver *r, char **p, char *str, int depth, char **prefixes); 71 | int Resolve(char **path, char *name); 72 | int ResolveN(char **path, char *name, int depth); 73 | int resolveOnce (char **path, char *name); 74 | int Publish (char *proto, ciPrivKey name, char *value); 75 | int PublishWithEOL (char *proto, ciPrivKey name, char *value, time_t eol); 76 | 77 | int ProquintResolveOnce (char **p, char *name); 78 | 79 | int domainMatchString (char *d); 80 | int IsICANNTLD(char *s); 81 | int IsExtendedTLD (char *s); 82 | int IsTLD (char *s); 83 | int IsDomain (char *s); 84 | 85 | typedef struct s_DNSResolver { 86 | // TODO 87 | } DNSResolver; 88 | 89 | int DNSResolverResolveOnce (DNSResolver *r, char **path, char *name); 90 | int workDomain (int output, DNSResolver *r, char *name); 91 | int parseEntry (char **Path, char *txt); 92 | int tryParseDnsLink (char **Path, char *txt); 93 | #endif //NAMESYS_H 94 | -------------------------------------------------------------------------------- /include/ipfs/node/Example for this.c: -------------------------------------------------------------------------------- 1 | #include "repo/test_repo_config.h" 2 | #include "repo/test_repo_identity.h" 3 | #include "repo/test_repo_bootstrap_peers.h" 4 | #include "repo/test_repo_fsrepo.h" 5 | #include "cmd/ipfs/test_init.h" 6 | #include "cid/test_cid.h" 7 | #include "flatfs/test_flatfs.h" 8 | #include "storage/test_ds_helper.h" 9 | #include "storage/test_datastore.h" 10 | #include "storage/test_blocks.h" 11 | #include "ipfs/node/node.h" 12 | /*TODOS! 13 | *Incoroparate protobuf funcs 14 | *Incoroparate multihash funcs 15 | */ 16 | int main(int argc, char** argv) 17 | { 18 | printf("XETH TESTS\n"); 19 | ////Links////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | //Variables of link: 21 | char * name = "Alex"; 22 | char * ahash = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"; 23 | struct Link * mylink; 24 | mylink = Create_Link(name,ahash); 25 | printf("===================================\n" \ 26 | "Node Link:\n" \ 27 | " -Name: %s\n" \ 28 | " -Size: %lu\n" \ 29 | "\n Cid Details:\n\n" \ 30 | " -Version: %d\n" \ 31 | " -Codec: %c\n" \ 32 | " -Hash: %s\n" \ 33 | " -Hash Length: %lu\n" \ 34 | "====================================\n" \ 35 | , mylink->name, mylink->size, mylink->Lcid->version,mylink->Lcid->codec,mylink->Lcid->hash,mylink->Lcid->hash_length); 36 | 37 | //Link Two for testing purposes 38 | char * name2 = "Simo"; 39 | char * ahash2 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo"; 40 | struct Link * mylink2; 41 | mylink2 = Create_Link(name2,ahash2); 42 | 43 | ////Nodes///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | //N_Create_From_Link 46 | struct Node * Mynode; 47 | Mynode = N_Create_From_Link(mylink); 48 | mylink->name = "HAHA";//Testing for valid node creation 49 | printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->Lcid->hash); 50 | 51 | //N_Add_Link 52 | Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2)); 53 | mylink2->name = "HAHA";//Testing for valid node creation 54 | printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->Lcid->hash); 55 | 56 | //Node_Get_Link 57 | struct Link * ResultLink = Node_Get_Link(Mynode, "Simo"); 58 | printf("\nResultLink: \nName: %s\nHash: %s\n\n", ResultLink->name, ResultLink->Lcid->hash); 59 | 60 | //Node_Resolve_Links 61 | struct Link_Proc * LPRX = Node_Resolve_Links(Mynode, "Alex/Simo"); 62 | for(int i=0;iammount;i++) 63 | { 64 | printf("RESOLVE LINKS-Result: %s\n", LPRX->links[i]->name); 65 | } 66 | Free_Link_Proc(LPRX); 67 | 68 | //Node_Remove Link 69 | 70 | int StatUs = Node_Remove_Link("Simo", Mynode); 71 | printf("Status: %d\n",StatUs); 72 | printf("Outlinkamt: %d\n", Mynode->link_ammount); 73 | 74 | //Node Copy 75 | struct Node * Node2; 76 | Node2 = Node_Copy(Mynode); 77 | printf("NODE COPY TEST: [0]: %s\n", Node2->links[0]->Lcid->hash); 78 | Node_Delete(Node2); 79 | 80 | //Node_Set_Data 81 | Node_Set_Data(Mynode, "DATA_HERE"); 82 | 83 | //Node_Get_Data 84 | unsigned char * meh; 85 | meh = Node_Get_Data(Mynode); 86 | printf("NODE DATA: %s", meh); 87 | 88 | 89 | //Free Everything 90 | Free_Link(mylink); 91 | Free_Link(mylink2); 92 | Free_Link(ResultLink); 93 | 94 | Node_Delete(Mynode); 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /include/ipfs/node/node.h: -------------------------------------------------------------------------------- 1 | /** 2 | * An implementation of an IPFS node 3 | * Copying the go-ipfs-node project 4 | */ 5 | #ifndef IPFS_NODE_H 6 | #define IPFS_NODE_H 7 | #include 8 | #include 9 | #include 10 | #include "inttypes.h" 11 | #include "ipfs/cid/cid.h" 12 | 13 | int debug = 0; // Set to 1 to enable debug mode of this program 14 | 15 | /*==================================================================================== 16 | * 17 | * Structures 18 | * 19 | *===================================================================================*/ 20 | 21 | struct Link 22 | { 23 | char * name; 24 | size_t size; 25 | struct Cid * Lcid; 26 | }; 27 | struct Node 28 | { 29 | unsigned char * data; 30 | unsigned char * encoded; 31 | struct Cid * cached; 32 | int link_ammount; 33 | struct Link * links[]; 34 | }; 35 | /*==================================================================================== 36 | * 37 | * Functions 38 | * 39 | *===================================================================================*/ 40 | 41 | /*==================================================================================== 42 | * Link Functions 43 | *===================================================================================*/ 44 | /* Create_Link 45 | * @Param name: The name of the link (char *) 46 | * @Param size: Size of the link (size_t) 47 | * @Param ahash: An Qmhash 48 | */ 49 | struct Link * Create_Link(char * name, unsigned char * ahash) 50 | { 51 | struct Link * mylink; 52 | mylink = malloc(sizeof(struct Link)); 53 | mylink->name = name; 54 | int ver = 0; 55 | size_t lenhash = strlen(ahash)-1; 56 | ipfs_cid_new(ver, ahash, lenhash*2, CID_PROTOBUF, &mylink->Lcid); 57 | mylink->size = sizeof(mylink) + mylink->Lcid->hash_length; //Unsure of this 58 | return mylink; 59 | } 60 | /* Free_Link 61 | * @param L: Free the link you have allocated. 62 | */ 63 | void Free_Link(struct Link * L) 64 | { 65 | ipfs_cid_free(L->Lcid); 66 | free(L); 67 | } 68 | /*==================================================================================== 69 | * Node Functions 70 | *===================================================================================*/ 71 | /*Create_Empty_Node 72 | * Creates an empty node, allocates the required memory 73 | * Returns a fresh new node with no data set in it. 74 | */ 75 | struct Node * Create_Empty_Node() 76 | { 77 | struct Node * N; 78 | N = (struct Node *)malloc(sizeof(struct Node)); 79 | return N; 80 | } 81 | /*Node_Set_Data 82 | * Sets the data of a node 83 | * @param Node: The node which you want to set data in. 84 | * @param Data, the data you want to assign to the node 85 | * returns 1 on success 0 on failure 86 | */ 87 | int Node_Set_Data(struct Node * N, unsigned char * Data) 88 | { 89 | if(!N || !Data) 90 | { 91 | return 0; 92 | } 93 | N->encoded = NULL; 94 | N->cached = NULL; 95 | N->data = Data; 96 | return 1; 97 | } 98 | /*Node_Get_Data 99 | * Gets data from a node 100 | * @param Node: = The node you want to get data from. (unsigned char *) 101 | * Returns data of node. 102 | */ 103 | unsigned char * Node_Get_Data(struct Node * N) 104 | { 105 | unsigned char * DATA; 106 | DATA = N->data; 107 | return DATA; 108 | } 109 | 110 | /*Node_Copy: Returns a copy of the node you input 111 | * @param Node: The node you want to copy (struct CP_Node *) 112 | * Returns a copy of the node you wanted to copy. 113 | */ 114 | struct Node * Node_Copy(struct Node * CP_Node) 115 | { 116 | struct Node * CN; 117 | CN = (struct Node*) malloc(sizeof(struct Node) + sizeof(struct Link) * 2); 118 | if(CP_Node->link_ammount != 0) 119 | { 120 | for(int i=0; ilink_ammount; i++) 121 | { 122 | CN->links[i] = malloc(sizeof(struct Link)); 123 | } 124 | } 125 | memcpy(CN, CP_Node, sizeof(struct Node)); 126 | memcpy(CN->links[0],CP_Node->links[0], sizeof(struct Link)); 127 | return CN; 128 | } 129 | /*Node_Delete 130 | * Once you are finished using a node, always delete it using this. 131 | * It will take care of the links inside it. 132 | * @param N: the node you want to free. (struct Node *) 133 | */ 134 | void Node_Delete(struct Node * N) 135 | { 136 | if(N->link_ammount > 0) 137 | { 138 | for(int i=0; ilink_ammount; i++) 139 | { 140 | free(N->links[i]); 141 | } 142 | } 143 | free(N); 144 | } 145 | /*Node_Get_Link 146 | * Returns a copy of the link with given name 147 | * @param Name: (char * name) searches for link with this name 148 | * Returns the link struct if it's found otherwise returns NULL 149 | */ 150 | struct Link * Node_Get_Link(struct Node * N, char * Name) 151 | { 152 | struct Link * L; 153 | for(int i=0;ilink_ammount;i++) 154 | { 155 | if(strcmp(N->links[i]->name,Name) == 0) 156 | { 157 | L = (struct Link *)malloc(sizeof(struct Link)); 158 | memcpy(L,N->links[i],sizeof(struct Link)); 159 | int ver = L->Lcid->version; 160 | char * ahash = L->Lcid->hash; 161 | size_t lenhash = L->Lcid->hash_length; 162 | ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &L->Lcid); 163 | return L; 164 | } 165 | } 166 | return NULL; 167 | } 168 | /*Node_Remove_Link 169 | * Removes a link from node if found by name. 170 | * @param name: Name of link (char * name) 171 | * returns 1 on success, 0 on failure. 172 | */ 173 | int Node_Remove_Link(char * Name, struct Node * mynode) 174 | { 175 | for(int i=0; ilink_ammount; i++) 176 | { 177 | if(mynode->links[i]->name == Name) 178 | { 179 | for(int x=i;xlink_ammount && x+1 != mynode->link_ammount;i++) 180 | { 181 | memcpy(mynode->links[x],mynode->links[x+1],sizeof(struct Link)); 182 | } 183 | free(mynode->links[mynode->link_ammount-1]); 184 | mynode->link_ammount--; 185 | return 1; 186 | } 187 | } 188 | return 0; 189 | } 190 | /* N_Add_Link 191 | * Adds a link to your node 192 | * @param mynode: &yournode 193 | * @param mylink: the CID you want to create a node from 194 | * @param linksz: sizeof(your cid here) 195 | * Returns your node with the newly added link 196 | */ 197 | struct Node * N_Add_Link(struct Node ** mynode, struct Link * mylink, size_t linksz) 198 | { 199 | struct Node * Nl = *mynode; 200 | Nl->link_ammount++; 201 | size_t calculatesize = 0; 202 | if(Nl->link_ammount != 0) 203 | { 204 | for(int i=0; ilink_ammount-1;i++) 205 | { 206 | calculatesize = calculatesize + sizeof(Nl->links[i]); 207 | } 208 | calculatesize = calculatesize + linksz; 209 | Nl = (struct Node *) realloc(Nl, sizeof(struct Node) + calculatesize); 210 | } 211 | else 212 | { 213 | Nl = (struct Node *) malloc(sizeof(struct Node) + linksz); 214 | } 215 | Nl->links[Nl->link_ammount-1] = malloc(sizeof(struct Link)); 216 | memcpy(Nl->links[Nl->link_ammount-1],mylink,sizeof(struct Link)); 217 | return Nl; 218 | } 219 | 220 | /*N_Create_From_Link 221 | * Create a node from a link 222 | * @param mylink: the link you want to create it from. (struct Cid *) 223 | * @param linksize: sizeof(the link in mylink) (size_T) 224 | * Returns a fresh new node with the link you specified. Has to be freed with Node_Free preferably. 225 | */ 226 | struct Node * N_Create_From_Link(struct Link * mylink) 227 | { 228 | struct Node * mynode; 229 | mynode = (struct Node *) malloc(sizeof(struct Node) + sizeof(struct Link)); 230 | mynode->link_ammount = 0; 231 | mynode->link_ammount++; 232 | mynode->links[0] = malloc(sizeof(struct Link)); 233 | memcpy(mynode->links[0], mylink, sizeof(struct Link)); 234 | return mynode; 235 | } 236 | /*N_Create_From_Data 237 | * @param data: bytes buffer you want to create the node from 238 | * returns a node with the data you inputted. 239 | */ 240 | struct Node * N_Create_From_Data(unsigned char * data) 241 | { 242 | struct Node * mynode; 243 | mynode = (struct Node *) malloc(sizeof(struct Node)); 244 | mynode->data = data; 245 | return mynode; 246 | } 247 | /*Node_Resolve_Max_Size 248 | * !!!This shouldn't concern you! 249 | *Gets the ammount of words that will be returned by Node_Resolve 250 | *@Param1: The string that will be processed (eg: char * sentence = "foo/bar/bin") 251 | *Returns either -1 if something went wrong or the ammount of words that would be processed. 252 | */ 253 | int Node_Resolve_Max_Size(char * input1) 254 | { 255 | if(!input1) 256 | { 257 | return -1; // Input is null, therefor nothing can be processed. 258 | } 259 | char input[strlen(input1)]; 260 | bzero(input, strlen(input1)); 261 | strcpy(input, input1); 262 | int num = 0; 263 | char * tr; 264 | char * end; 265 | tr=strtok_r(input,"/",&end); 266 | for(int i = 0;tr;i++) 267 | { 268 | tr=strtok_r(NULL,"/",&end); 269 | num++; 270 | } 271 | return num; 272 | } 273 | 274 | /*Node_Resolve Basically stores everything in a pointer array eg: char * bla[Max_Words_] 275 | * !!!This shouldn't concern you!!! 276 | *@param1: Pointer array(char * foo[x], X=Whatever ammount there is. should be used with the helper function Node_Resolve_Max_Size) 277 | *@param2: Sentence to gather words/paths from (Eg: char * meh = "foo/bar/bin") 278 | *@Returns 1 or 0, 0 if something went wrong, 1 if everything went smoothly. 279 | */ 280 | 281 | int Node_Resolve(char ** result, char * input1) 282 | { 283 | if(!input1) 284 | { 285 | return 0; // Input is null, therefor nothing can be processed. 286 | } 287 | char input[strlen(input1)]; 288 | bzero(input, strlen(input1)); 289 | strcpy(input, input1); 290 | char * tr; 291 | char * end; 292 | tr=strtok_r(input,"/",&end); 293 | for(int i = 0;tr;i++) 294 | { 295 | if(debug == 1) 296 | { 297 | printf("TR: %s\n", tr); 298 | } 299 | result[i] = (char *) malloc(strlen(tr)+1); 300 | strcpy(result[i], tr); 301 | tr=strtok_r(NULL,"/",&end); 302 | } 303 | return 1; 304 | } 305 | /************************************************************************************************************************************** 306 | *|||||||||||||||||||||||||||||||||||||||| !!!! IMPORTANT !!! ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||* 307 | ************************************************************************************************************************************** 308 | * Not sure where this is used, I'm making something to easen it up for all of you. 309 | * This in itself will get all the links for you in a link[] array inside Link_Proc 310 | * the memory allocation for storage will be noted in the ammount of links. 311 | * After being done with this, you have to free the array for which you will have a function specially made for you. 312 | * 313 | * What this does: 314 | * It searches for links using a path like /foo/bar/bin/, if links with those names are found in the node you specify, it stores them 315 | * in a custom struct, Link_Proc; which is what Node_Resolve_Link returns. 316 | * Notes: 317 | * Use it, free it, it's all already laid out for you. 318 | * There will also be a tutorial demonstrating it in the same folder here so everyone can understand this. 319 | */ 320 | struct Link_Proc 321 | { 322 | char * remaining_links; // Not your concern. 323 | int ammount; //This will store the ammount of links, so you know what to process. 324 | struct Link * links[]; // Link array 325 | }; 326 | /*Node_Resolve_Links 327 | * Processes a path returning all links. 328 | * @param N: The node you want to get links from 329 | * @param path: The "foo/bar/bin" path 330 | */ 331 | struct Link_Proc * Node_Resolve_Links(struct Node * N, char * path) 332 | { 333 | if(!N || !path) 334 | { 335 | return NULL; 336 | } 337 | int expected_link_ammount = Node_Resolve_Max_Size(path); 338 | struct Link_Proc * LProc = (struct Link_Proc *) malloc(sizeof(struct Link_Proc) + sizeof(struct Link) * expected_link_ammount); 339 | LProc->ammount = 0; 340 | char * linknames[expected_link_ammount]; 341 | Node_Resolve(linknames, path); 342 | for(int i=0;ilinks[i] = (struct Link *)malloc(sizeof(struct Link)); 349 | memcpy(LProc->links[i], proclink, sizeof(struct Link)); 350 | LProc->ammount++; 351 | free(proclink); 352 | } 353 | } 354 | //Freeing pointer array 355 | for(int i=0;iammount != 0) 368 | { 369 | for(int i=0;iammount;i++) 370 | { 371 | Free_Link(LPRC->links[i]); 372 | } 373 | } 374 | free(LPRC); 375 | } 376 | 377 | /*Node_Tree() Basically a unix-like ls 378 | *@Param1: Result char * foo[strlen(sentence)] 379 | *@Param2: char sentence[] = foo/bar/bin/whatever 380 | *Return: 0 if failure, 1 if success 381 | */ 382 | int Node_Tree(char * result, char * input1) //I don't know where you use this but here it is. 383 | { 384 | if(!input1) 385 | { 386 | return 0; 387 | } 388 | char input[strlen(input1)]; 389 | bzero(input, strlen(input1)); 390 | strcpy(input, input1); 391 | for(int i=0; i 8 | #include 9 | #include 10 | 11 | /** 12 | * get an environment varible from the os 13 | * @param variable the variable to look for 14 | * @returns the results 15 | */ 16 | char* os_utils_getenv(const char* variable); 17 | 18 | /** 19 | * get the user's home directory 20 | * @returns the user's home directory 21 | */ 22 | char* os_utils_get_homedir(); 23 | 24 | /** 25 | * join 2 pieces of a filepath, being careful about the slashes 26 | * @param root the root part 27 | * @param extension what should be concatenated 28 | * @param results where to put the results 29 | * @param max_len throw an error if the total is longer than max_len 30 | */ 31 | int os_utils_filepath_join(const char* root, const char* extension, char* results, unsigned long max_len); 32 | 33 | int os_utils_file_exists(const char* file_name); 34 | 35 | int os_utils_file_size(const char* file_name); 36 | 37 | int os_utils_directory_writeable(const char* path); 38 | 39 | int os_utils_directory_exists(const char* path); 40 | 41 | #endif /* utils_h */ 42 | -------------------------------------------------------------------------------- /include/ipfs/path/path.h: -------------------------------------------------------------------------------- 1 | #ifndef IPFS_PATH_H 2 | #define IPFS_PATH_H 3 | 4 | #ifdef IPFS_PATH_C 5 | char *ErrPath[] = { 6 | NULL, 7 | // ErrBadPath is returned when a given path is incorrectly formatted 8 | "invalid 'ipfs ref' path", 9 | // Paths after a protocol must contain at least one component 10 | "path must contain at least one component", 11 | "TODO: ErrCidDecode", 12 | NULL, 13 | "no link named %s under %s" 14 | }; 15 | #else 16 | extern char **ErrPath; 17 | #endif // IPFS_PATH_C 18 | 19 | enum { 20 | ErrBadPath = 1, 21 | ErrNoComponents, 22 | ErrCidDecode, 23 | ErrNoLink, 24 | ErrNoLinkFmt 25 | } PathErrs; 26 | 27 | char* PathFromCid (struct Cid *c); 28 | char** SplitN (char *p, char *delim, int n); 29 | char** Segments (char *p); 30 | int SegmentsLength (char **s); 31 | void FreeSegments (char ***s); 32 | int IsJustAKey (char *p); 33 | int PopLastSegment (char **str, char *p); 34 | char *PathFromSegments(char *prefix, char **seg); 35 | int ParseCidToPath (char *dst, char *txt); 36 | int ParsePath (char *dst, char *txt); 37 | int PathIsValid (char *p); 38 | 39 | // Resolver provides path resolution to IPFS 40 | // It has a pointer to a DAGService, which is uses to resolve nodes. 41 | // TODO: now that this is more modular, try to unify this code with the 42 | // the resolvers in namesys 43 | typedef struct s_resolver { 44 | DAGService DAG; 45 | int (*ResolveOnce)(NodeLink **lnk, Context ctx, DAGService *ds, Node **nd, char *name); 46 | } Resolver; 47 | #endif // IPFS_PATH_H 48 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/addresses.h: -------------------------------------------------------------------------------- 1 | // 2 | // addresses.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef addresses_h 10 | #define addresses_h 11 | 12 | #include "swarm.h" 13 | 14 | struct Addresses { 15 | struct SwarmAddresses* swarm; 16 | char* api; 17 | char* gateway; 18 | }; 19 | 20 | /** 21 | * initialize the Addresses struct with data. Must add the SwarmAddresses later 22 | * @param addresses the struct 23 | * @param api the API address (like "/ip4/127.0.0.1/tcp/5001") 24 | * @param gateway the gateway address (like "ip4/127.0.0.1/tcp/8080") 25 | * @returns true(1) on success, otherwise false(0) 26 | */ 27 | int repo_config_addresses_new(struct Addresses** addresses, char* api, char* gateway); 28 | 29 | /** 30 | * clear any memory allocated by a address_new call 31 | * @param addresses the struct 32 | * @returns true(1) 33 | */ 34 | int repo_config_addresses_free(struct Addresses* addresses); 35 | 36 | #endif /* addresses_h */ 37 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/bootstrap_peers.h: -------------------------------------------------------------------------------- 1 | // 2 | // bootstrap_peer.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef bootstrap_peer_h 10 | #define bootstrap_peer_h 11 | 12 | #include "ipfs/thirdparty/ipfsaddr/ipfs_addr.h" 13 | 14 | struct BootstrapPeers { 15 | int num_peers; 16 | struct IPFSAddr** peers; 17 | }; 18 | 19 | /*** 20 | * get a list of peers to use to bootstrap the instance 21 | * @param bootstrap_peers an array of IPFSAddr structs, will be allocated by this function 22 | * @returns true(1) on success, otherwise false(0) 23 | */ 24 | int repo_config_bootstrap_peers_retrieve(struct BootstrapPeers* bootstrap_peers); 25 | 26 | /*** 27 | * frees up memory caused by call to repo_config_bootstrap_peers_retrieve 28 | * @param list the list to free 29 | * @returns true(1) 30 | */ 31 | int repo_config_bootstrap_peers_free(struct BootstrapPeers* list); 32 | 33 | #endif /* bootstrap_peer_h */ 34 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H__ 2 | #define __CONFIG_H__ 3 | 4 | #include "datastore.h" 5 | #include "identity.h" 6 | #include "swarm.h" 7 | #include "bootstrap_peers.h" 8 | #include "addresses.h" 9 | #include "gateway.h" 10 | 11 | struct MDNS { 12 | int enabled; 13 | int interval; 14 | }; 15 | 16 | struct Discovery { 17 | struct MDNS mdns; 18 | }; 19 | 20 | struct Mounts { 21 | char* ipfs; 22 | char* ipns; 23 | }; 24 | 25 | struct Ipns { 26 | int resolve_cache_size; 27 | }; 28 | 29 | struct Reprovider { 30 | char* interval; 31 | }; 32 | 33 | struct RepoConfig { 34 | struct Identity* identity; 35 | struct Datastore* datastore; 36 | struct Addresses* addresses; 37 | struct Mounts mounts; 38 | struct Discovery discovery; 39 | struct Ipns ipns; 40 | struct BootstrapPeers peer_addresses; 41 | //struct tour tour; 42 | struct Gateway* gateway; 43 | //struct supernode_routing supernode_client_config; 44 | //struct api api; 45 | struct Reprovider reprovider; 46 | }; 47 | 48 | /** 49 | * provide the full path of the config file, given the directory. 50 | * NOTE: This allocates memory for result. Make sure to clean up after yourself. 51 | * @param path the path to the config file (without the actual file name) 52 | * @param result the full filename including the path 53 | * @returns true(1) on success, false(0) otherwise 54 | */ 55 | int repo_config_get_file_name(char* path, char** result); 56 | 57 | /*** 58 | * Returns the path "extension" relative to the configuration root. 59 | * If an empty string is provided for config_root, the default root 60 | * is used. 61 | * @param config_root the path to the root of the configuration 62 | * @param extension the extension to add to the path 63 | * @param result the result of config_root with extension appended 64 | * @param max_len the max length of the result 65 | * @returns true(1) if everything went okay, false(0) otherwise 66 | */ 67 | int config_path(char* config_root, char* extension, char* result, int max_len); 68 | 69 | /*** 70 | * create a configuration based on the passed in parameters 71 | * @param config the configuration struct 72 | * @param num_bits_for_keypair number of bits for the key pair 73 | * @returns true(1) on success, otherwise 0 74 | */ 75 | int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path); 76 | 77 | /*** 78 | * Initialize memory for a RepoConfig struct 79 | * @param config the structure to initialize 80 | * @returns true(1) on success 81 | */ 82 | int ipfs_repo_config_new(struct RepoConfig** config); 83 | 84 | /*** 85 | * free all resources that were allocated to store config information 86 | * @param config the config 87 | * @returns true(1) 88 | */ 89 | int ipfs_repo_config_free(struct RepoConfig* config); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/datastore.h: -------------------------------------------------------------------------------- 1 | #ifndef __DATASTORE_H__ 2 | #define __DATASTORE_H__ 3 | 4 | #include 5 | #include "ipfs/blocks/block.h" 6 | 7 | //const char* datastore_default_directory = "datastore"; 8 | 9 | struct Datastore { 10 | char* type; 11 | char* path; 12 | char* storage_max; 13 | int storage_gc_watermark; 14 | char* gc_period; 15 | char* params; 16 | int no_sync; 17 | int hash_on_read; 18 | int bloom_filter_size; 19 | 20 | // function pointers for datastore operations 21 | int (*datastore_open)(int argc, char** argv, struct Datastore* datastore); 22 | int (*datastore_close)(struct Datastore* datastore); 23 | int (*datastore_put)(const char* key, size_t key_size, struct Block* block, struct Datastore* datastore); 24 | //int (*datastore_get)(const char* key, struct Block* block); 25 | // a handle to the datastore "context" used by the datastore 26 | void* handle; 27 | }; 28 | 29 | /*** 30 | * Initialize the structure of the datastore to default settings. Used for 31 | * creating a new datastore on the disk. 32 | * @param datastore the struct to initialize 33 | * @param config_root the path to the root of IPFS 34 | * @returns true(1) on success 35 | */ 36 | int ipfs_repo_config_datastore_init(struct Datastore* datastore, char* config_root); 37 | 38 | /*** 39 | * initialize the structure of the datastore 40 | * @param datastore the struct to initialize 41 | * @returns true(1) on success 42 | */ 43 | int ipfs_repo_config_datastore_new(struct Datastore** datastore); 44 | 45 | 46 | /*** 47 | * deallocate the memory and clear resources from a datastore_init 48 | * @param datastore the struct to deallocate 49 | * @returns true(1) 50 | */ 51 | int ipfs_repo_config_datastore_free(struct Datastore* datastore); 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/gateway.h: -------------------------------------------------------------------------------- 1 | // 2 | // gateway.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef gateway_h 10 | #define gateway_h 11 | 12 | struct HTTPHeader { 13 | char* header; 14 | char* value; 15 | }; 16 | 17 | struct HTTPHeaders { 18 | struct HTTPHeader** headers; 19 | int num_elements; 20 | }; 21 | 22 | struct PathPrefixes { 23 | int num_elements; 24 | char** prefixes; 25 | }; 26 | 27 | struct Gateway { 28 | char* root_redirect; 29 | int writable; 30 | struct PathPrefixes path_prefixes; 31 | struct HTTPHeaders* http_headers; 32 | }; 33 | 34 | int repo_config_gateway_http_header_init(struct HTTPHeaders* http_headers, char** headers, char** values, int num_elements); 35 | 36 | int repo_config_gateway_new(struct Gateway** gateway); 37 | 38 | int repo_config_gateway_free(struct Gateway* gateway); 39 | 40 | #endif /* gateway_h */ 41 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/identity.h: -------------------------------------------------------------------------------- 1 | // 2 | // identity.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef __REPO_CONFIG_IDENTITY_H__ 10 | #define __REPO_CONFIG_IDENTITY_H__ 11 | 12 | #include "libp2p/crypto/rsa.h" 13 | 14 | struct Identity { 15 | char* peer_id; // a pretty-printed hash of the public key 16 | struct RsaPrivateKey private_key; // a private key 17 | }; 18 | 19 | /*** 20 | * initializes a new keypair, and puts it in the Identity struct 21 | */ 22 | int repo_config_identity_init(struct Identity* identity, unsigned long num_bits_for_keypair); 23 | 24 | /*** 25 | * Build a RsaPrivateKey struct from a base64 string of the private key 26 | * @param identity where to put the new struct 27 | * @param base64 the base 64 encoded private key in DER format 28 | * @returns true(1) on success 29 | */ 30 | int repo_config_identity_build_private_key(struct Identity* identity, const char* base64); 31 | 32 | /*** 33 | * Frees resources held by Identity 34 | * @param identity the identity that we're cleaning up 35 | * @returns true(0) 36 | */ 37 | int repo_config_identity_free(struct Identity* identity); 38 | 39 | /*** 40 | * Initializes a new identity struct that will need to be identity_free'd 41 | * @param identity the identity to allocate memory for 42 | * @returns true(1) on success 43 | */ 44 | int repo_config_identity_new(struct Identity** identity); 45 | 46 | #endif /* identity_h */ 47 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/peer.h: -------------------------------------------------------------------------------- 1 | // 2 | // peer.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/3/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef peer_h 10 | #define peer_h 11 | 12 | 13 | /*** 14 | * given a public key, find the peer id 15 | * @param public_key the public key in bytes 16 | * @param id the resultant peer id 17 | * @returns true(1) on success 18 | */ 19 | int repo_config_peer_id_from_public_key(char* public_key, char* id); 20 | 21 | #endif /* peer_h */ 22 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/swarm.h: -------------------------------------------------------------------------------- 1 | // 2 | // swarm.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef swarm_h 10 | #define swarm_h 11 | 12 | struct SwarmAddresses { 13 | int num_addresses; 14 | char** addresses; 15 | }; 16 | 17 | /** 18 | * add addresses to the SwarmAddresses struct 19 | * @param swarm_addresses the structure 20 | * @param addresses the array of addresses to store 21 | * @param array_length the number of elements in addresses array 22 | * @returns true(1) on success 23 | */ 24 | int repo_config_swarm_address_init(struct SwarmAddresses* swarm_addresses, char** addresses, int array_length); 25 | 26 | int repo_config_swarm_address_new(struct SwarmAddresses** swarm_addresses); 27 | /*** 28 | * free up memory from repo_config_swarm_address_new 29 | * @param swarm_addresses the structure 30 | * @returns true(1) 31 | */ 32 | int repo_config_swarm_address_free(struct SwarmAddresses* swarm_addresses); 33 | 34 | #endif /* swarm_h */ 35 | -------------------------------------------------------------------------------- /include/ipfs/repo/fsrepo/fs_repo.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * handles a repo on the file system 3 | */ 4 | #ifndef fs_repo_h 5 | #define fs_repo_h 6 | 7 | #include 8 | #include "ipfs/repo/config/config.h" 9 | 10 | 11 | /** 12 | * a structure to hold the repo info 13 | */ 14 | struct FSRepo { 15 | int closed; 16 | char* path; 17 | struct IOCloser* lock_file; 18 | struct RepoConfig* config; 19 | }; 20 | 21 | /** 22 | * opens a fsrepo 23 | * @param repo the repo struct. Should contain the path. This method will do the rest 24 | * @return 0 if there was a problem, otherwise 1 25 | */ 26 | int ipfs_repo_fsrepo_open(struct FSRepo* repo); 27 | 28 | /*** 29 | * checks to see if the repo is initialized 30 | * @param repo_path the path to the repo 31 | * @returns true(1) if it is initialized, otherwise false(0) 32 | */ 33 | int fs_repo_is_initialized(char* repo_path); 34 | 35 | /** 36 | * write the config file to disk 37 | * @param path the path to the file 38 | * @param config the config structure 39 | * @returns true(1) on success 40 | */ 41 | int fs_repo_write_config_file(char* path, struct RepoConfig* config); 42 | 43 | /** 44 | * constructs the FSRepo struct. 45 | * Remember: ipfs_repo_fsrepo_free must be called 46 | * @param repo_path the path to the repo 47 | * @param config the optional config file. NOTE: if passed, fsrepo_free will free resources of the RepoConfig. 48 | * @param repo the struct to allocate memory for 49 | * @returns false(0) if something bad happened, otherwise true(1) 50 | */ 51 | int ipfs_repo_fsrepo_new(char* repo_path, struct RepoConfig* config, struct FSRepo** fs_repo); 52 | 53 | /*** 54 | * Free all resources used by this struct 55 | * @param repo the repo to clean up 56 | * @returns true(1) on success 57 | */ 58 | int ipfs_repo_fsrepo_free(struct FSRepo* config); 59 | 60 | /*** 61 | * Initialize a new repo with the specified configuration 62 | * @param config the information in order to build the repo 63 | * @returns true(1) on success 64 | */ 65 | int ipfs_repo_fsrepo_init(struct FSRepo* config); 66 | 67 | #endif /* fs_repo_h */ 68 | -------------------------------------------------------------------------------- /include/ipfs/repo/fsrepo/lmdb_datastore.h: -------------------------------------------------------------------------------- 1 | #ifndef __FS_REPO_LMDB_DATASTORE_H__ 2 | #define __FS_REPO_LMDB_DATASTORE_H__ 3 | 4 | #include "ipfs/repo/config/datastore.h" 5 | 6 | /*** 7 | * Places the LMDB methods into the datastore's function pointers 8 | * @param datastore the datastore to fill 9 | * @returns true(1) on success; 10 | */ 11 | int repo_fsrepo_lmdb_cast(struct Datastore* datastore); 12 | 13 | /** 14 | * Open an lmdb database with the given parameters. 15 | * Note: for now, the parameters are not used 16 | * @param argc number of parameters in the following array 17 | * @param argv an array of parameters 18 | */ 19 | int repo_fsrepro_lmdb_open(int argc, char** argv, struct Datastore* datastore); 20 | 21 | /*** 22 | * Close an LMDB database 23 | * NOTE: for now, argc and argv are not used 24 | * @param argc number of parameters in the argv array 25 | * @param argv parameters to be passed in 26 | * @param datastore the datastore struct that contains information about the opened database 27 | */ 28 | int repo_fsrepo_lmdb_close(struct Datastore* datastore); 29 | 30 | /*** 31 | * Creates the directory 32 | * @param datastore contains the path that needs to be created 33 | * @returns true(1) on success 34 | */ 35 | int repo_fsrepo_lmdb_create_directory(struct Datastore* datastore); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/ipfs/thirdparty/ipfsaddr/ipfs_addr.h: -------------------------------------------------------------------------------- 1 | // 2 | // ipfs_addr.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef ipfs_addr_h 10 | #define ipfs_addr_h 11 | 12 | struct IPFSAddr { 13 | char* entire_string; 14 | }; 15 | 16 | /** 17 | * initialize a new IPFSAddr struct. NOTE: be sure to use ipfsaddr_free() 18 | * @param addr the struct to initialize 19 | * @param string the string that contains the address 20 | * @returns true(1) on success, false(0) otherwise 21 | */ 22 | int ipfsaddr_new(struct IPFSAddr** addr, char* string); 23 | 24 | /*** 25 | * frees allocated memory in the struct 26 | * @param addr the struct that is going away 27 | * @returns true(1) on success, false(0) otherwise 28 | */ 29 | int ipfsaddr_free(struct IPFSAddr* addr); 30 | 31 | #endif /* ipfs_addr_h */ 32 | -------------------------------------------------------------------------------- /merkledag/merkledag.c: -------------------------------------------------------------------------------- 1 | /** 2 | * A basic storage building block of the IPFS system 3 | */ 4 | 5 | /*** 6 | * Adds a node to the dagService and blockService 7 | * @param node the node to add 8 | * @returns true(1) on success 9 | */ 10 | int ipfs_merkledag_add(struct Node* node) { 11 | // taken from merkledag.go line 59 12 | // TODO: put in blockstore 13 | // TODO: call HasBlock (unsure why as yet) 14 | 15 | } 16 | -------------------------------------------------------------------------------- /multibase/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = multibase.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /multibase/multibase.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ipfs/multibase/multibase.h" 5 | #include "libp2p/crypto/encoding/base58.h" 6 | #include "libp2p/crypto/encoding/base16.h" 7 | 8 | /** 9 | * Encode data in multibase format. NOTE: currently only supports MULTIBASE_BASE58_BTC and MULTIBASE_BASE16 10 | * @param base the format to use (i.e. MULTIBASE_BASE58_BTC) 11 | * @param incoming the data to encode 12 | * @param incoming_length the length of the data to encode 13 | * @param results where to put the results 14 | * @param results_max_length the size of the results buffer 15 | * @param results_length the size of the results after being encoded 16 | * @returns true(1) on success 17 | */ 18 | int multibase_encode(const char base, const unsigned char* incoming, size_t incoming_length, unsigned char* results, size_t results_max_length, size_t* results_length) { 19 | *results_length = results_max_length; 20 | int retVal = 0; 21 | 22 | switch (base) { 23 | case (MULTIBASE_BASE58_BTC): 24 | retVal = libp2p_crypto_encoding_base58_encode(incoming, incoming_length, &results, results_length); 25 | break; 26 | case(MULTIBASE_BASE16): 27 | retVal = libp2p_crypto_encoding_base16_encode(incoming, incoming_length, results, results_length); 28 | break; 29 | default: // unsupported format 30 | return 0; 31 | } 32 | // check to see if there was a problem 33 | if (retVal == 0) 34 | return 0; 35 | 36 | // we have the hash, now add the code to the first byte (if there is room) 37 | 38 | if (*results_length >= results_max_length) { // It could be equal, but should never be greater. But just in case. 39 | return 0; // buffer isn't big enough 40 | } 41 | 42 | memcpy(&results[1], results, *results_length); 43 | results[0] = base; 44 | *results_length += 1; 45 | 46 | return 1; 47 | } 48 | 49 | /*** 50 | * Calculates the size of the buffer neccessary to encode the incoming byte array 51 | * @param base the encoding to use 52 | * @param incoming the incoming array of bytes 53 | * @param incoming_length the length of the array in bytes 54 | * @returns the appropriate size of the buffer 55 | */ 56 | int multibase_encode_size(const char base, const unsigned char* incoming, size_t incoming_length) { 57 | switch (base) { 58 | case (MULTIBASE_BASE58_BTC): 59 | return libp2p_crypto_encoding_base58_encode_size(incoming_length) + 1; 60 | case (MULTIBASE_BASE16): 61 | return libp2p_crypto_encoding_base16_encode_size(incoming_length); 62 | } 63 | return 0; 64 | } 65 | 66 | /** 67 | * Decode data that was encoded in multibase format 68 | * @param incoming the data to decode 69 | * @param incoming_length the length of the data to decode 70 | * @param results where to put the results 71 | * @param results_max_length the size of the results buffer 72 | * @param results_length the size of the results after being encoded 73 | * @returns true(1) on success 74 | */ 75 | int multibase_decode(const unsigned char* incoming, size_t incoming_length, unsigned char* results, size_t results_max_length, size_t* results_length) { 76 | *results_length = results_max_length; 77 | int retVal = 0; 78 | 79 | const char base = incoming[0]; 80 | 81 | switch (base) { 82 | case (MULTIBASE_BASE58_BTC): 83 | retVal = libp2p_crypto_encoding_base58_decode(&incoming[1], incoming_length - 1, &results, results_length); 84 | break; 85 | case(MULTIBASE_BASE16): 86 | retVal = libp2p_crypto_encoding_base16_decode(&incoming[1], incoming_length - 1, results, results_length); 87 | break; 88 | default: // unsupported format 89 | return 0; 90 | } 91 | // check to see if there was a problem 92 | if (retVal == 0) 93 | return 0; 94 | 95 | return 1; 96 | } 97 | 98 | /*** 99 | * Calculates the size of the buffer neccessary to decode the incoming byte array 100 | * @param base the encoding to use 101 | * @param incoming the incoming array of bytes 102 | * @param incoming_length the length of the array in bytes 103 | * @returns the appropriate size of the buffer 104 | */ 105 | int multibase_decode_size(const char base, const unsigned char* incoming, size_t incoming_length) { 106 | switch (base) { 107 | case (MULTIBASE_BASE58_BTC): 108 | return libp2p_crypto_encoding_base58_decode_size(incoming_length) + 1; 109 | case (MULTIBASE_BASE16): 110 | return libp2p_crypto_encoding_base16_decode_size(incoming_length); 111 | } 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /namesys/base.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ipfs/cid/cid.h" 4 | #include "ipfs/path/path.h" 5 | #include "ipfs/namesys/namesys.h" 6 | 7 | int resolve (resolver *r, char **p, char *str, int depth, char **prefixes) 8 | { 9 | int err, i; 10 | char ipfs_prefix[] = "/ipfs/"; 11 | 12 | for (;;) { 13 | err = r->resolveOnce(p, str); 14 | if (err) { 15 | //log.Warningf("Could not resolve %s", name); 16 | *p = NULL; 17 | return err; 18 | } 19 | //log.Debugf("Resolved %s to %s", name, p.String()); 20 | if (memcmp(p, ipfs_prefix, strlen(ipfs_prefix)) == 0) { 21 | // we've bottomed out with an IPFS path 22 | return 0; 23 | } 24 | if (depth == 1) { 25 | return ErrResolveRecursion; 26 | } 27 | for (i = 0 ; prefixes[i] ; i++) { 28 | if (memcmp(*p, prefixes[i], strlen(prefixes[i])) == 0) { 29 | if (SegmentsLength(prefixes) == 1) { 30 | str += strlen(prefixes[i]); 31 | } 32 | break; 33 | } 34 | } 35 | if ( !prefixes[i] ) { 36 | return 0; 37 | } 38 | if (depth > 1) { 39 | depth--; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /namesys/dns.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "ipfs/cid/cid.h" 10 | #include "ipfs/path/path.h" 11 | #include "ipfs/namesys/namesys.h" 12 | 13 | /*type LookupTXTFunc func(name string) (txt []string, err error) 14 | 15 | // DNSResolver implements a Resolver on DNS domains 16 | type DNSResolver struct { 17 | lookupTXT LookupTXTFunc 18 | // TODO: maybe some sort of caching? 19 | // cache would need a timeout 20 | } 21 | 22 | // NewDNSResolver constructs a name resolver using DNS TXT records. 23 | func NewDNSResolver() Resolver { 24 | return &DNSResolver{lookupTXT: net.LookupTXT} 25 | } 26 | 27 | // newDNSResolver constructs a name resolver using DNS TXT records, 28 | // returning a resolver instead of NewDNSResolver's Resolver. 29 | func newDNSResolver() resolver { 30 | return &DNSResolver{lookupTXT: net.LookupTXT} 31 | } 32 | 33 | // Resolve implements Resolver. 34 | func (r *DNSResolver) Resolve(ctx context.Context, name string) (path.Path, error) { 35 | return r.ResolveN(ctx, name, DefaultDepthLimit) 36 | } 37 | 38 | // ResolveN implements Resolver. 39 | func (r *DNSResolver) ResolveN(ctx context.Context, name string, depth int) (path.Path, error) { 40 | return resolve(ctx, r, name, depth, "/ipns/") 41 | } 42 | 43 | type lookupRes struct { 44 | path path.Path 45 | error error 46 | }*/ 47 | 48 | // resolveOnce implements resolver. 49 | // TXT records for a given domain name should contain a b58 50 | // encoded multihash. 51 | int DNSResolverResolveOnce (char **path, char *name) 52 | { 53 | char **segments, *domain, *dnslink, buf[500], dlprefix[] = "_dnslink."; 54 | int p1[2], p2[2], r, c=2; 55 | struct pollfd event[2], *e; 56 | 57 | segments = SplitN(name, "/", 2); 58 | domain = segments[0]; 59 | 60 | *path = NULL; 61 | 62 | if (!IsDomain(domain)) { 63 | return ErrInvalidDomain; 64 | } 65 | //log.Infof("DNSResolver resolving %s", domain); 66 | 67 | if (pipe(p1) || pipe(p2)) { 68 | return ErrPipe; 69 | } 70 | 71 | r = fork(); 72 | switch(r) { 73 | case -1: 74 | return ErrPipe; 75 | case 0: // child 76 | close(p1[STDIN_FILENO]); // we don't need to read at child process. 77 | return workDomain (p1[STDOUT_FILENO], r, domain); 78 | } 79 | close(p1[STDOUT_FILENO]); // we don't need to write at main process. 80 | r = fork(); 81 | switch(r) { 82 | case -1: 83 | return ErrPipe; 84 | case 0: // child 85 | close(p2[STDIN_FILENO]); // we don't need to read at child process. 86 | 87 | dnslink = malloc(strlen(domain) + sizeof(dlprefix)); 88 | if (!dnslink) { 89 | return ErrAllocFailed; 90 | } 91 | strcpy (dnslink, dlprefix); 92 | strcat (dnslink, domain); 93 | 94 | return workDomain (p2[STDOUT_FILENO], r, dnslink); 95 | } 96 | close(p2[STDOUT_FILENO]); // we don't need to write at main process. 97 | 98 | memset(&event, 0, sizeof(struct pollfd)); 99 | event[0].fd = p1[STDIN_FILENO]; 100 | event[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL; 101 | event[1].fd = p2[STDIN_FILENO]; 102 | event[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL; 103 | e = event; 104 | 105 | do { 106 | r = poll(e, c, -1); 107 | if (r == -1) { 108 | return ErrPoll; 109 | } 110 | for (r = 0 ; r < c ; r++) { 111 | if (e[r].revents & POLLIN) { 112 | r = read(e[r].fd, buf, sizeof(buf)); 113 | if (r > 0) { 114 | buf[r] = '\0'; 115 | *path = malloc(r+1); 116 | if (*path) { 117 | strcpy(*path, buf); 118 | } 119 | } else if (r <= 0) { 120 | return ErrPoll; 121 | } 122 | } 123 | } 124 | if (event[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { 125 | event[0].events = 0; 126 | e++; c--; 127 | wait(&r); 128 | } 129 | if (event[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { 130 | event[1].events = 0; 131 | c--; 132 | wait(&r); 133 | } 134 | } while (c); // wait for child process finish. 135 | 136 | if (!*path) { 137 | return ErrResolveFailed; 138 | } 139 | 140 | if (SegmentsLength (segments) > 1) { 141 | name = *path + strlen(*path) - 1; 142 | while (*name == '/') { 143 | *name-- = '\0'; 144 | } 145 | name = *path; 146 | *path = PathFromSegments (name, segments+1); 147 | free (name); 148 | if (!*path) { 149 | return ErrResolveFailed; 150 | } 151 | } 152 | FreeSegments (&segments); 153 | return 0; 154 | } 155 | 156 | int workDomain (int output, DNSResolver *r, char *name) 157 | { 158 | char **txt, *path; 159 | int i, err = r->lookupTXT(&txt, name); 160 | 161 | if (err) { 162 | return err; 163 | } 164 | 165 | for (i = 0 ; txt[i] ; i++) { 166 | err = parseEntry (&path, txt[i]); 167 | if (!err) { 168 | err = (write (output, path, strlen(path)) != strlen(path)); 169 | free (path); 170 | if (err) { 171 | return ErrPipe; 172 | } 173 | return 0; 174 | } 175 | } 176 | return ErrResolveFailed; 177 | } 178 | 179 | int parseEntry (char **path, char *txt) 180 | { 181 | char buf[500]; 182 | int err; 183 | 184 | err = ParseCidToPath(buf, txt); // bare IPFS multihashes 185 | if (! err) { 186 | *path = malloc(strlen(buf) + 1); 187 | if (!*path) { 188 | return ErrAllocFailed; 189 | } 190 | strcpy(*path, buf); 191 | return 0; 192 | } 193 | return tryParseDnsLink(path, txt); 194 | } 195 | 196 | int tryParseDnsLink(char **path, char *txt) 197 | { 198 | char **parts = SplitN(txt, "=", 2), buf[500]; 199 | int err; 200 | 201 | if (SegmentsLength(parts) == 2 && strcmp(parts[0], "dnslink")==0) { 202 | err = ParsePath(buf, parts[1]); 203 | if (err == 0) { 204 | *parts = malloc(strlen(buf) + 1); 205 | if (! *parts) { 206 | return ErrAllocFailed; 207 | } 208 | strcpy(*parts, buf); 209 | return 0; 210 | } 211 | return err; 212 | } 213 | return ErrInvalidDNSLink; 214 | } 215 | -------------------------------------------------------------------------------- /namesys/is_domain_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ipfs/namesys/namesys.h" 4 | 5 | int main(int argc, char **argv) 6 | { 7 | int i; 8 | tlds chk[] = { 9 | { "foo.bar.baz.com", 1 }, 10 | { "foo.bar.baz", 0 }, 11 | { "foo.bar.baz.com.", 1 }, 12 | { "com", 0 }, // yeah yeah... 13 | { ".", 0 }, // yeah yeah... 14 | { "..", 0 }, 15 | { ".foo.com.", 0 }, 16 | { ".foo.com", 0 }, 17 | { "fo o.com", 0 }, 18 | { "example.com", 1 }, 19 | { "fjdoisajfdiosafdsa8fd8saf8dsa8fdsafdsa-fd-sa-fd-saf-dsa.org", 1 }, 20 | { "fjdoisajfdiosafdsa8fd8saf8dsa8fdsafdsa-fd-sa-fd-saf-dsa.bit", 1 }, 21 | { "fjdoisajfdiosafdsa8fd8saf8dsa8fdsafdsa-fd-sa-fd-saf-dsa.onion", 1 }, 22 | { "a.b.c.d.e.f.g.h.i.j.k.l.museum", 1 }, 23 | { "a.b.c.d.e.f.g.h.i.j.k.l", 0 }, 24 | { NULL, 0 } 25 | }; 26 | 27 | for (i = 0 ; chk[i].str ; i++) { 28 | if (IsDomain (chk[i].str) != chk[i].condition) { 29 | printf ("Misclassification: %s should be %d\n", chk[i].str, chk[i].condition); 30 | } 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /namesys/isdomain.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ipfs/namesys/namesys.h" 5 | #include "ipfs/namesys/isdomain.h" 6 | 7 | void ToUpper(char *dst, char *src) 8 | { 9 | while(*src) { 10 | *dst++ = toupper(*src++); 11 | } 12 | *dst = '\0'; 13 | } 14 | 15 | int HasSuffix (char *s, char *suf) 16 | { 17 | char *p; 18 | 19 | p = s + strlen(s) - strlen(suf); 20 | return strcmp(p, suf) == 0; 21 | } 22 | 23 | int IsAtArray(tlds *a, char *s) 24 | { 25 | char str[strlen(s)+1]; 26 | 27 | ToUpper(str, s); 28 | while(a->str) { 29 | if (strcmp(a->str, str) == 0) { 30 | return a->condition; 31 | } 32 | a++; 33 | } 34 | return 0; 35 | } 36 | 37 | int domainMatchString (char *d) 38 | { 39 | char str[strlen(d)+1], *p = str, *l; 40 | 41 | ToUpper(str, d); 42 | 43 | // l point to last two chars. 44 | l = p + strlen(p) - 2; 45 | 46 | // can't start with a dot 47 | if (*p == '.') { 48 | return 0; // invalid 49 | } 50 | 51 | // last 2 chars can't be a dot or a number. 52 | if ((*l >= 'A' && *l <= 'Z') && (l[1] >= 'A' && l[1] <= 'Z')) { 53 | while (*p) { 54 | if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '.' || *p == '-') { 55 | p++; 56 | } else { 57 | return 0; // invalid 58 | } 59 | } 60 | } else { 61 | return 0; // invalid 62 | } 63 | 64 | return 1; // valid 65 | } 66 | 67 | // IsICANNTLD returns whether the given string is a TLD (Top Level Domain), 68 | // according to ICANN. Well, really according to the TLDs listed in this 69 | // package. 70 | int IsICANNTLD(char *s) 71 | { 72 | return IsAtArray (TLDs, s); 73 | } 74 | 75 | // IsExtendedTLD returns whether the given string is a TLD (Top Level Domain), 76 | // extended with a few other "TLDs", .bit, .onion 77 | int IsExtendedTLD (char *s) 78 | { 79 | return IsAtArray (ExtendedTLDs, s); 80 | } 81 | 82 | // IsTLD returns whether the given string is a TLD (according to ICANN, or 83 | // in the set of ExtendedTLDs listed in this package. 84 | int IsTLD (char *s) 85 | { 86 | return IsICANNTLD (s) || IsExtendedTLD(s); 87 | } 88 | 89 | // IsDomain returns whether given string is a domain. 90 | // It first checks the TLD, and then uses a regular expression. 91 | int IsDomain (char *s) 92 | { 93 | char str[strlen(s)]; 94 | char *tld; 95 | 96 | strcpy(str, s); 97 | s = str; // work with local copy. 98 | 99 | if (HasSuffix (s, ".")) { 100 | s[strlen(s) - 1] = '\0'; 101 | } 102 | 103 | tld = strrchr(s, '.'); 104 | 105 | if (!tld) { // don't have a dot. 106 | return 0; 107 | } 108 | 109 | tld++; // ignore last dot 110 | 111 | if (!IsTLD (tld)) { 112 | return 0; 113 | } 114 | 115 | return domainMatchString(s); 116 | } 117 | -------------------------------------------------------------------------------- /namesys/namesys.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ipfs/cid/cid.h" 5 | #include "ipfs/path/path.h" 6 | #define NAMESYS_C 7 | #include "ipfs/namesys/namesys.h" 8 | 9 | /* mpns (a multi-protocol NameSystem) implements generic IPFS naming. 10 | * 11 | * Uses several Resolvers: 12 | * (a) IPFS routing naming: SFS-like PKI names. 13 | * (b) dns domains: resolves using links in DNS TXT records 14 | * (c) proquints: interprets string as the raw byte data. 15 | * 16 | * It can only publish to: (a) IPFS routing naming. 17 | */ 18 | 19 | mpns **ns; 20 | // NewNameSystem will construct the IPFS naming system based on Routing 21 | /* 22 | func NewNameSystem(r routing.ValueStore, ds ds.Datastore, cachesize int) NameSystem { 23 | return &mpns{ 24 | resolvers: map[string]resolver{ 25 | "dns": newDNSResolver(), 26 | "proquint": new(ProquintResolver), 27 | "dht": NewRoutingResolver(r, cachesize), 28 | }, 29 | publishers: map[string]Publisher{ 30 | "/ipns/": NewRoutingPublisher(r, ds), 31 | }, 32 | } 33 | }*/ 34 | 35 | const DefaultResolverCacheTTL = time.Minute; 36 | 37 | // Resolve implements Resolver. 38 | int Resolve(char **path, char *name) 39 | { 40 | return ResolveN(path, name, DefaultDepthLimit); 41 | } 42 | 43 | // ResolveN implements Resolver. 44 | int ResolveN(char **path, char *name, int depth) 45 | { 46 | char ipfs_prefix[] = "/ipfs/"; 47 | char p[500]; 48 | char *ps[] = {"/ipns/", NULL}; 49 | int err; 50 | resolver r; 51 | 52 | r.resolveOnce = resolveOnce; 53 | 54 | if (memcmp(name, ipfs_prefix, strlen(ipfs_prefix)) == 0) { 55 | ParsePath(p, name); 56 | *path = malloc(strlen(p) + 1); 57 | if (*p) { 58 | strcpy(*path, p); 59 | } else { 60 | err = ErrAllocFailed; 61 | } 62 | return err; 63 | } 64 | 65 | if (*name == '/') { 66 | int err; 67 | char *str = malloc(sizeof(ipfs_prefix) + strlen(name)); 68 | if (!str) { 69 | return ErrAllocFailed; 70 | } 71 | strcpy(str, ipfs_prefix); 72 | strcat(str, name+1); // ignore inital / from name, because ipfs_prefix already has it. 73 | err = ParsePath(p, str); // save return value. 74 | free (str); // so we can free allocated memory before return. 75 | *path = malloc(strlen(p) + 1); 76 | if (*p) { 77 | strcpy(*path, p); 78 | } else { 79 | err = ErrAllocFailed; 80 | } 81 | return err; 82 | } 83 | 84 | return resolve(&r, path, name, depth, ps); 85 | } 86 | 87 | // resolveOnce implements resolver. 88 | int resolveOnce (char **path, char *name) 89 | { 90 | char ipns_prefix[] = "/ipns/"; 91 | char *ptr = NULL; 92 | char **segs; 93 | int i, err = 0; 94 | 95 | if (!name) { // NULL pointer. 96 | return ErrNULLPointer; 97 | } 98 | 99 | if (memcmp (name, ipns_prefix, strlen(ipns_prefix)) == 0) { // prefix missing. 100 | ptr = malloc(strlen(name) + sizeof(ipns_prefix)); 101 | if (!ptr) { // allocation fail. 102 | return ErrAllocFailed; 103 | } 104 | strcpy(ptr, ipns_prefix); 105 | strcat(ptr, name); 106 | segs = Segments(ptr); 107 | free (ptr); 108 | } else { 109 | segs = Segments(name); 110 | } 111 | 112 | if (!segs || SegmentsLength(segs) < 2) { 113 | //log.Warningf("Invalid name syntax for %s", name); 114 | return ErrResolveFailed; 115 | } 116 | 117 | for (i = 0 ; ns[i] ; i++) { 118 | char *p; 119 | //log.Debugf("Attempting to resolve %s with %s", segments[1], ns[i]->resolver->protocol); 120 | err = ns[i]->resolver->func(&p, segs[1]); 121 | if (!err) { 122 | if (SegmentsLength(segs) > 2) { 123 | *path = PathFromSegments(p, segs+2); 124 | } else { 125 | *path = p; 126 | } 127 | return 0; 128 | } 129 | } 130 | //log.Warningf("No resolver found for %s", name); 131 | return ErrResolveFailed; 132 | } 133 | 134 | // Publish implements Publisher 135 | int Publish (char *proto, ciPrivKey name, char *value) 136 | { 137 | int i; 138 | 139 | for (i = 0 ; ns[i] ; i++) { 140 | if (strcmp(ns[i]->Publisher->protocol, proto)==0) { 141 | return ns[i]->Publisher->func(name, value); 142 | } 143 | } 144 | return ErrPublishFailed; 145 | } 146 | 147 | int PublishWithEOL (char *proto, ciPrivKey name, char *value, time_t eol) 148 | { 149 | int i; 150 | 151 | for (i = 0 ; ns[i] ; i++) { 152 | if (strcmp(ns[i]->Publisher->protocol, proto)==0) { 153 | return ns[i]->Publisher->func_eol(name, value, eol); 154 | } 155 | } 156 | return ErrPublishFailed; 157 | } 158 | -------------------------------------------------------------------------------- /namesys/proquint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ipfs/namesys/namesys.h" 5 | #include "ipfs/cid/cid.h" 6 | #include "ipfs/path/path.h" 7 | 8 | const uint8_t conse[] = {'b', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'z'}; 9 | const uint8_t vowse[] = {'a', 'i', 'o', 'u'}; 10 | 11 | // Find decoded number from the encoded consonant. 12 | static inline int consd(char c) 13 | { 14 | int i; 15 | 16 | for (i = 0 ; i < sizeof(conse) ; i++) { 17 | if (c == conse[i]) { 18 | return i; 19 | } 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | // Find decoded number of encoded vowel. 26 | static inline int vowsd(char c) 27 | { 28 | int i; 29 | 30 | for (i = 0 ; i < sizeof(vowse) ; i++) { 31 | if (c == vowse[i]) { 32 | return i; 33 | } 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | /** 40 | * Tests if a given string is a Proquint identifier 41 | * 42 | * @param {string} str The candidate string. 43 | * 44 | * @return {bool} Whether or not it qualifies. 45 | * @return {error} Error 46 | */ 47 | int ProquintIsProquint(char *str) 48 | { 49 | int i, c; 50 | 51 | // if str is null, or length isn't 11 or don't have - at middle 52 | if (!str || strlen(str) != 11 || str[5] != '-') { 53 | return 0; // it's not a proquint 54 | } 55 | 56 | // run every position 57 | for (i = 0 ; i < 11 ; i++) { 58 | if (i == 5) i++; // skip -, already tested. 59 | switch (i) { 60 | case 1: 61 | case 3: 62 | case 7: 63 | case 9: 64 | // compare with vowse array 65 | c = vowsd(str[i]); 66 | if (str[i] != vowse[c]) { 67 | return 0; // it's not a proquint 68 | } 69 | break; 70 | default: // 0,2,4,6,8,10 71 | // compare with conse array 72 | c = consd(str[i]); 73 | if (str[i] != conse[c]) { 74 | return 0; // it's not a proquint 75 | } 76 | } 77 | } 78 | 79 | return 1; // passed on every value. 80 | } 81 | 82 | /** 83 | * Encodes an arbitrary byte slice into an identifier. 84 | * 85 | * @param {[]byte} buf Slice of bytes to encode. 86 | * 87 | * @return {string} The given byte slice as an identifier. 88 | */ 89 | char *ProquintEncode(char *buf) 90 | { 91 | char *ret; 92 | int i, c; 93 | uint16_t n; 94 | 95 | if (!buf) { 96 | return NULL; 97 | } 98 | 99 | ret = malloc(12); 100 | if (!ret) { 101 | return NULL; 102 | } 103 | 104 | for (i = 0, c = 0; i < 4; i += 2) { 105 | n = ((buf[i] & 0xff) << 8) | (buf[i + 1] & 0xff); 106 | 107 | ret[c++] = conse[(n >> 12) & 0x0f]; 108 | ret[c++] = vowse[(n >> 10) & 0x03]; 109 | ret[c++] = conse[(n >> 6) & 0x0f]; 110 | ret[c++] = vowse[(n >> 4) & 0x03]; 111 | ret[c++] = conse[n & 0x0f]; 112 | ret[c++] = '-'; 113 | } 114 | ret[--c] = '\0'; 115 | 116 | return ret; 117 | } 118 | 119 | /** 120 | * Decodes an identifier into its corresponding byte slice. 121 | * 122 | * @param {string} str Identifier to convert. 123 | * 124 | * @return {[]byte} The identifier as a byte slice. 125 | */ 126 | char *ProquintDecode(char *str) 127 | { 128 | char *ret; 129 | int i, c; 130 | uint16_t x; 131 | 132 | // make sure its a valid Proquint string. 133 | if (!ProquintIsProquint(str)) { 134 | return NULL; 135 | } 136 | 137 | ret = malloc(4); 138 | if (!ret) { 139 | return NULL; 140 | } 141 | 142 | for (i = 0, c = 0 ; i < 11 ; i += 6) { 143 | x =(consd(str[i + 0]) << 12) | \ 144 | (vowsd(str[i + 1]) << 10) | \ 145 | (consd(str[i + 2]) << 6) | \ 146 | (vowsd(str[i + 3]) << 4) | \ 147 | (consd(str[i + 4]) << 0); 148 | 149 | ret[c++] = x >> 8; 150 | ret[c++] = x & 0xff; 151 | } 152 | 153 | return ret; 154 | } 155 | 156 | // resolveOnce implements resolver. Decodes the proquint string. 157 | int ProquintResolveOnce (char **p, char *name) 158 | { 159 | int err = ProquintIsProquint(name); 160 | char buf[500]; 161 | 162 | if (err) { 163 | *p = NULL; 164 | err = ErrInvalidProquint; 165 | } else { 166 | err = ParsePath(buf, ProquintDecode(name)); 167 | if (!err) { 168 | *p = malloc (strlen(buf) + 1); 169 | if (p) { 170 | strcpy(*p, buf); 171 | } 172 | } 173 | } 174 | return err; 175 | } 176 | -------------------------------------------------------------------------------- /namesys/proquint_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int ProquintIsProquint(char *str); 10 | char *ProquintEncode(char *buf); 11 | char *ProquintDecode(char *str); 12 | 13 | int main(void) { 14 | char *r, *s; 15 | int i; 16 | char *p[] = {"lusab-babad", "gutih-tugad", "gutuk-bisog", "mudof-sakat", 17 | "haguz-biram", "mabiv-gibot", "natag-lisaf", "tibup-zujah", 18 | "tobog-higil", "todah-vobij", "sinid-makam", "budov-kuras", 19 | NULL}; 20 | 21 | for (i = 0 ; p[i] ; i++) { 22 | r = ProquintDecode (p[i]); 23 | if (r) { 24 | struct in_addr ip_addr; 25 | memcpy (&(ip_addr.s_addr), r, sizeof(ip_addr.s_addr)); 26 | printf ("%s\t%s", p[i], inet_ntoa(ip_addr)); 27 | s = ProquintEncode(r); 28 | free (r); 29 | if (s) { 30 | printf ("\t%s", s); 31 | free (s); 32 | } 33 | printf("\n"); 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /node/node.c: -------------------------------------------------------------------------------- 1 | /** 2 | * An implementation of an IPFS node 3 | * Copying the go-ipfs-node project 4 | */ 5 | 6 | #include "ipfs/node/node.h" 7 | 8 | -------------------------------------------------------------------------------- /os/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include 3 | LFLAGS = 4 | DEPS = 5 | OBJS = utils.o 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | all: $(OBJS) 11 | 12 | clean: 13 | rm -f *.o 14 | -------------------------------------------------------------------------------- /os/utils.c: -------------------------------------------------------------------------------- 1 | #include "ipfs/os/utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /** 10 | * get an environment varible from the os 11 | * @param variable the variable to look for 12 | * @returns the results 13 | */ 14 | char* os_utils_getenv(const char* variable) { 15 | return getenv(variable); 16 | } 17 | 18 | /** 19 | * returns the user's home directory 20 | * @returns the home directory 21 | */ 22 | char* os_utils_get_homedir() { 23 | struct passwd *pw = getpwuid(getuid()); 24 | return pw->pw_dir; 25 | } 26 | 27 | /** 28 | * join 2 pieces of a filepath, being careful about the slashes 29 | * @param root the root part 30 | * @param extension what should be concatenated 31 | * @param results where to put the results 32 | * @param max_len throw an error if the total is longer than max_len 33 | */ 34 | int os_utils_filepath_join(const char* root, const char* extension, char* results, unsigned long max_len) { 35 | if (strlen(root) + strlen(extension) + 1 > max_len) 36 | return 0; 37 | strncpy(results, root, strlen(root) + 1); 38 | // one of these should have a slash. If not, add one 39 | if (root[strlen(root)-1] != '/' && extension[0] != '/') { 40 | results[strlen(root)] = '/'; 41 | results[strlen(root)+1] = 0; 42 | } 43 | strncat(results, extension, strlen(extension)+1); 44 | return 1; 45 | } 46 | 47 | int os_utils_file_exists(const char* file_name) { 48 | if (access(file_name, F_OK) != -1) 49 | return 1; 50 | return 0; 51 | } 52 | 53 | int os_utils_directory_exists(const char* directory_name) { 54 | if (access(directory_name, F_OK) != -1) 55 | return 1; 56 | return 0; 57 | } 58 | 59 | int os_utils_directory_writeable(const char* path) { 60 | int result = access(path, W_OK); 61 | return result == 0; 62 | } 63 | 64 | int os_utils_file_size(const char* path) { 65 | // open file 66 | FILE* in_file = fopen(path, "r"); 67 | // determine size 68 | fseek(in_file, 0L, SEEK_END); 69 | size_t file_size = ftell(in_file); 70 | fclose(in_file); 71 | return file_size; 72 | } 73 | -------------------------------------------------------------------------------- /path/path.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define IPFS_PATH_C 5 | #include 6 | 7 | // FromCid safely converts a cid.Cid type to a Path type 8 | char* PathFromCid (struct Cid *c) 9 | { 10 | const char prefix[] = "/ipfs/"; 11 | char *rpath, *cidstr = CidString(c); 12 | 13 | rpath = malloc(sizeof(prefix) + strlen(cidstr)); 14 | if (!rpath) return NULL; 15 | strcpy(rpath, prefix); 16 | strcat(rpath, cidstr); 17 | return rpath; 18 | } 19 | 20 | char** SplitN (char *p, char *delim, int n) 21 | { 22 | char *c, **r, *rbuf; 23 | int i, dlen = strlen(delim); 24 | 25 | if (n == 0) { 26 | return NULL; // no split? 27 | } 28 | 29 | if (n < 0) { // negative, count all delimiters + 1. 30 | for (c = p , n = 0 ; c ; n++) { 31 | c = strstr(c, delim); 32 | if (c) { 33 | c += dlen; 34 | } 35 | } 36 | } else { 37 | n++; // increment param value. 38 | } 39 | 40 | rbuf = malloc(strlen(p) + 1); 41 | if (!rbuf) { 42 | return NULL; 43 | } 44 | 45 | r = calloc(sizeof(char*), n + 1); // splits plus NULL pointer termination 46 | if (!r) { 47 | free(rbuf); 48 | return NULL; 49 | } 50 | 51 | strcpy(rbuf, p); // keep original 52 | for (c = rbuf, i = 0 ; i < n && c ; i++) { 53 | r[i] = c; 54 | c = strstr(c, delim); 55 | if (c) { 56 | *c = '\0'; 57 | c += dlen; 58 | } 59 | } 60 | r[i] = NULL; 61 | 62 | return r; 63 | } 64 | 65 | char** Segments (char *p) 66 | { 67 | if (*p == '/') p++; // Ignore leading slash 68 | 69 | return SplitN (p, "/", -1); 70 | } 71 | 72 | // Count Segments 73 | int SegmentsLength (char **s) 74 | { 75 | int r = 0; 76 | 77 | if (s) { 78 | while (s[r]) r++; 79 | } 80 | 81 | return r; 82 | } 83 | 84 | // free memory allocated by Segments 85 | void FreeSegments (char ***s) 86 | { 87 | if (*s && **s) { 88 | free(**s); // free string buffer 89 | free(*s); // free array 90 | *s = NULL; 91 | } 92 | } 93 | 94 | // IsJustAKey returns true if the path is of the form or /ipfs/. 95 | int IsJustAKey (char *p) 96 | { 97 | char **parts; 98 | int ret = 0; 99 | parts = Segments (p); 100 | if (parts) { 101 | if (SegmentsLength (parts) == 2 && strcmp (parts[0], "ipfs") == 0) ret++; 102 | FreeSegments(&parts); 103 | } 104 | return ret; 105 | } 106 | 107 | // PopLastSegment returns a new Path without its final segment, and the final 108 | // segment, separately. If there is no more to pop (the path is just a key), 109 | // the original path is returned. 110 | int PopLastSegment (char **str, char *p) 111 | { 112 | if (IsJustAKey(p)) return 0; 113 | *str = strrchr(p, '/'); 114 | if (!*str) return ErrBadPath; // error 115 | **str = '\0'; 116 | *str++; 117 | return 0; 118 | } 119 | 120 | char *PathFromSegments(char *prefix, char **seg) 121 | { 122 | int retlen, i; 123 | char *ret; 124 | 125 | if (!prefix || !seg) return NULL; 126 | 127 | retlen = strlen(prefix); 128 | for (i = 0 ; seg[i] ; i++) { 129 | retlen += strlen(seg[i]) + 1; // count each segment length + /. 130 | } 131 | 132 | ret = malloc(retlen + 1); // allocate final string size + null terminator. 133 | if (!ret) return NULL; 134 | 135 | strcpy(ret, prefix); 136 | for (i = 0 ; seg[i] ; i++) { 137 | strcat(ret, "/"); 138 | strcat(ret, seg[i]); 139 | } 140 | return ret; 141 | } 142 | 143 | int ParseCidToPath (char *dst, char *txt) 144 | { 145 | struct Cid *c; 146 | char *r; 147 | 148 | if (!txt || txt[0] == '\0') return ErrNoComponents; 149 | 150 | c = cidDecode(txt); 151 | 152 | if (!c) { 153 | return ErrCidDecode; 154 | } 155 | 156 | r = PathFromCid(c); 157 | 158 | if (!r) { 159 | return ErrCidDecode; 160 | } 161 | strcpy (dst, r); 162 | free (r); 163 | return 0; 164 | } 165 | 166 | int ParsePath (char *dst, char *txt) 167 | { 168 | int err, i; 169 | char *c; 170 | const char prefix[] = "/ipfs/"; 171 | const int plen = strlen(prefix); 172 | 173 | if (!txt || txt[0] == '\0') return ErrNoComponents; 174 | 175 | if (*txt != '/' || strchr (txt+1, '/') == NULL) { 176 | if (*txt == '/') { 177 | txt++; 178 | } 179 | err = ParseCidToPath (dst+plen, txt); 180 | if (err == 0) { // only change dst if ParseCidToPath returned success. 181 | // Use memcpy instead of strcpy to avoid overwriting 182 | // result of ParseCidToPath with a null terminator. 183 | memcpy (dst, prefix, plen); 184 | } 185 | return err; 186 | } 187 | 188 | c = txt; 189 | for (i = 0 ; (c = strchr(c, '/')) ; i++) c++; 190 | if (i < 3) return ErrBadPath; 191 | 192 | if (strcmp (txt, prefix) == 0) { 193 | char buf[strlen(txt+5)]; 194 | strcpy (buf, txt+6); // copy to temp buffer. 195 | c = strchr(buf, '/'); 196 | if (c) *c = '\0'; 197 | return ParseCidToPath(dst, buf); 198 | } else if (strcmp (txt, "/ipns/") != 0) { 199 | return ErrBadPath; 200 | } 201 | return 0; 202 | } 203 | 204 | int PathIsValid (char *p) 205 | { 206 | char buf[4096]; 207 | return ParsePath(buf, p); 208 | } 209 | -------------------------------------------------------------------------------- /path/resolver.c: -------------------------------------------------------------------------------- 1 | #include "ipfs/cid/cid.h" 2 | #include "ipfs/path/path.h" 3 | 4 | Resolver* NewBasicResolver (DAGService *ds) 5 | { 6 | Resolver *ret = malloc(sizeof(Resolver)); 7 | if (!ret) return NULL; 8 | ret->DAG = ds; 9 | ret->ResolveOnce = ResolveSingle; 10 | return ret; 11 | } 12 | 13 | // SplitAbsPath clean up and split fpath. It extracts the first component (which 14 | // must be a Multihash) and return it separately. 15 | int SplitAbsPath (struct Cid* cid, char ***parts, char *fpath) 16 | { 17 | *parts = Segments(fpath); 18 | 19 | if (strcmp (**parts, "ipfs") == 0) *parts++; 20 | 21 | // if nothing, bail. 22 | if (!**parts) return ErrNoComponents; 23 | 24 | // first element in the path is a cid 25 | cid_decode_from_string(**parts, strlen(**parts), cid); 26 | return 0; 27 | } 28 | 29 | // ResolvePath fetches the node for given path. It returns the last item 30 | // returned by ResolvePathComponents. 31 | int ResolvePath(Node **nd, Context ctx, Resolver *s, char *fpath) 32 | { 33 | int err = IsValid(fpath); 34 | Node **ndd; 35 | 36 | if (err) { 37 | return err; 38 | } 39 | err = ResolvePathComponents(&ndd, ctx, s, fpath); 40 | if (err) { 41 | return err; 42 | } 43 | if (ndd == NULL) { 44 | return ErrBadPath; 45 | } 46 | while(*ndd) { 47 | *nd = *ndd; 48 | ndd++; 49 | } 50 | return 0; 51 | } 52 | 53 | int ResolveSingle(NodeLink **lnk, Context ctx, DAGService *ds, Node **nd, char *name) 54 | { 55 | return ResolveLink(lnk, name); 56 | } 57 | 58 | // ResolvePathComponents fetches the nodes for each segment of the given path. 59 | // It uses the first path component as a hash (key) of the first node, then 60 | // resolves all other components walking the links, with ResolveLinks. 61 | int ResolvePathComponents(Node ***nd, Context ctx, Resolver *s, char *fpath) 62 | { 63 | int err; 64 | struct Cid h; 65 | char **parts; 66 | 67 | err = SplitAbsPath(&h, &parts, fpath); 68 | if (err) { 69 | return err; 70 | } 71 | 72 | //log.Debug("resolve dag get"); 73 | //*nd = s->DAG.Get(ctx, h); 74 | //if (nd == DAG_ERR_VAL) { 75 | // return DAG_ERR_VAL; 76 | //} 77 | 78 | return ResolveLinks(ctx, *nd, parts); 79 | } 80 | 81 | // ResolveLinks iteratively resolves names by walking the link hierarchy. 82 | // Every node is fetched from the DAGService, resolving the next name. 83 | // Returns the list of nodes forming the path, starting with ndd. This list is 84 | // guaranteed never to be empty. 85 | // 86 | // ResolveLinks(nd, []string{"foo", "bar", "baz"}) 87 | // would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links 88 | int ResolveLinks(Node ***result, Context ctx, Node *ndd, char **names) 89 | { 90 | int err, idx = 0; 91 | NodeLink *lnk; 92 | Node *nd; 93 | 94 | *result = calloc (sizeof(Node*), SegmentsLength(names) + 1); 95 | if (!*result) { 96 | return -1; 97 | } 98 | memset (*result, NULL, sizeof(Node*) * (SegmentsLength(names)+1)); 99 | 100 | *result[idx++] = ndd; 101 | nd = ndd; // dup arg workaround 102 | 103 | while (*names) { 104 | //TODO 105 | //var cancel context.CancelFunc 106 | //ctx, cancel = context.WithTimeout(ctx, time.Minute) 107 | //defer cancel() 108 | 109 | // for each of the path components 110 | err = ResolveLink(&lnk, *names); 111 | if (err) { 112 | char msg[51]; 113 | *result[idx] = NULL; 114 | snprintf(msg, sizeof(msg), ErrPath[ErrNoLinkFmt], *names, nd->Cid); 115 | if (ErrPath[ErrNoLink]) { 116 | free(ErrPath[ErrNoLink]); 117 | } 118 | ErrPath[ErrNoLink] = malloc(strlen(msg) + 1); 119 | if (ErrPath[ErrNoLink]) { 120 | strcpy(ErrPath[ErrNoLink], msg); 121 | } 122 | free (*result); 123 | return ErrNoLink; 124 | } 125 | names++; 126 | } 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /repo/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | DEPS = 9 | OBJS = 10 | 11 | %.o: %.c $(DEPS) 12 | $(CC) -c -o $@ $< $(CFLAGS) 13 | 14 | all: $(OBJS) 15 | cd config; make all; 16 | cd fsrepo; make all; 17 | clean: 18 | rm -f *.o 19 | cd config; make clean; 20 | cd fsrepo; make clean; -------------------------------------------------------------------------------- /repo/config/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../c-multihash/include 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = config.h datastore.h identity.h 10 | OBJS = config.o identity.o bootstrap_peers.o datastore.o gateway.o addresses.o swarm.o peer.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /repo/config/addresses.c: -------------------------------------------------------------------------------- 1 | // 2 | // addresses.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ipfs/repo/config/addresses.h" 14 | 15 | char* alloc_and_copy(char* source) { 16 | unsigned long strLen = strlen(source); 17 | char* result = malloc(sizeof(char) * (strLen + 1)); 18 | strncpy(result, source, strLen); 19 | result[strLen] = 0; 20 | return result; 21 | } 22 | 23 | int repo_config_addresses_new(struct Addresses** addresses, char* api, char* gateway) { 24 | *addresses = (struct Addresses*)malloc(sizeof(struct Addresses)); 25 | if (*addresses == NULL) 26 | return 0; 27 | 28 | // allocate memory to store api and gateway 29 | (*addresses)->api = alloc_and_copy(api); 30 | (*addresses)->gateway = alloc_and_copy(gateway); 31 | if ( (*addresses)->api == NULL || (*addresses)->gateway == NULL) 32 | return 0; 33 | 34 | // allocate memory for swarm_addresses 35 | if (repo_config_swarm_address_new(&((*addresses)->swarm)) == 0) 36 | return 0; 37 | 38 | return 1; 39 | } 40 | 41 | int repo_config_addresses_free(struct Addresses* addresses) { 42 | free(addresses->api); 43 | free(addresses->gateway); 44 | repo_config_swarm_address_free(addresses->swarm); 45 | free(addresses); 46 | return 1; 47 | } 48 | -------------------------------------------------------------------------------- /repo/config/bootstrap_peers.c: -------------------------------------------------------------------------------- 1 | // 2 | // bootstrap_peers.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "ipfs/thirdparty/ipfsaddr/ipfs_addr.h" 13 | #include "ipfs/repo/config/bootstrap_peers.h" 14 | 15 | int repo_config_bootstrap_peers_retrieve(struct BootstrapPeers* list) { 16 | 17 | char* default_bootstrap_addresses[] = { 18 | "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io 19 | "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune.i.ipfs.io 20 | "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io 21 | "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus.i.ipfs.io 22 | "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io 23 | "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io 24 | "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io 25 | "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury.i.ipfs.io 26 | "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter.i.ipfs.io 27 | }; 28 | 29 | list->num_peers = 9; 30 | // allocate memory for list 31 | list->peers = malloc(sizeof(struct IPFSAddr*) * list->num_peers); 32 | if (list->peers == NULL) 33 | return 0; 34 | 35 | for(int i = 0; i < list->num_peers; i++) { 36 | struct IPFSAddr* currAddr; 37 | if (ipfsaddr_new(&currAddr, default_bootstrap_addresses[i]) == 0) 38 | return 0; 39 | list->peers[i] = currAddr; 40 | } 41 | return 1; 42 | } 43 | 44 | int repo_config_bootstrap_peers_free(struct BootstrapPeers* list) { 45 | 46 | for(int i = 0; i < list->num_peers; i++) { 47 | if (list->peers[i] != NULL) { 48 | ipfsaddr_free(list->peers[i]); 49 | } 50 | } 51 | free(list->peers); 52 | return 1; 53 | } 54 | -------------------------------------------------------------------------------- /repo/config/config.c: -------------------------------------------------------------------------------- 1 | // 2 | // config.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/27/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ipfs/repo/config/config.h" 14 | #include "ipfs/os/utils.h" 15 | #include "ipfs/repo/config/bootstrap_peers.h" 16 | #include "ipfs/repo/config/swarm.h" 17 | 18 | /*** 19 | * public 20 | */ 21 | 22 | /*** 23 | * gets the default path from the environment variable and/or the homedir struct 24 | * NOTE: this allocates memory for result. Clean up after yourself. 25 | * @param result where the result string will reside. 26 | * @returns true(1) on success, or false(0) 27 | */ 28 | int config_get_default_path_root(char* result) { 29 | char* root = os_utils_getenv("IPFS_PATH"); 30 | if (root == NULL) { 31 | root = os_utils_getenv("HOME"); 32 | result = malloc( strlen(root) + 7); 33 | if (result == NULL) 34 | return 0; 35 | strncpy(result, root, strlen(root)+1); 36 | strncat(result, "/.ipfs", 7); 37 | } else { 38 | char* result = malloc(strlen(root)+1); 39 | if (result == NULL) 40 | return 0; 41 | strncpy(result, root, strlen(root)+1); 42 | } 43 | return 1; 44 | } 45 | 46 | /*** 47 | * Returns the path "extension" relative to the configuration root. 48 | * If an empty string is provided for config_root, the default root 49 | * is used. NOTE: be sure to dispose of the memory allocated for result. 50 | * @param config_root the path to the root of the configuration 51 | * @param extension the extension to add to the path 52 | * @param result the result of config_root with extension appended 53 | * @returns true(1) if everything went okay, false(0) otherwise 54 | */ 55 | int config_path(char* config_root, char* extension, char* result, int max_len) { 56 | if (strlen(config_root) == 0) { 57 | char* default_path; 58 | int retVal = config_get_default_path_root(default_path); 59 | if (!retVal) 60 | return retVal; 61 | retVal = os_utils_filepath_join(default_path, extension, result, max_len); 62 | free(default_path); 63 | return retVal; 64 | } 65 | return os_utils_filepath_join(config_root, extension, result, max_len); 66 | } 67 | 68 | /** 69 | * provide the full path of the config file, given the directory. 70 | * NOTE: This allocates memory for result. Make sure to clean up after yourself. 71 | * @param path the path to the config file (without the actual file name) 72 | * @param result the full filename including the path 73 | * @returns true(1) on success, false(0) otherwise 74 | */ 75 | int repo_config_get_file_name(char* path, char** result) { 76 | unsigned long max_len = strlen(path) + 8; 77 | *result = malloc(sizeof(char) * max_len); 78 | if (result == NULL) 79 | return 0; 80 | 81 | return os_utils_filepath_join(path, "config", *result, max_len); 82 | } 83 | 84 | /*** 85 | * create a configuration based on the passed in parameters 86 | * @param config the configuration struct to be filled in 87 | * @param num_bits_for_keypair number of bits for the key pair 88 | * @returns true(1) on success, otherwise 0 89 | */ 90 | int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path) { 91 | // identity 92 | int retVal = repo_config_identity_init(config->identity, num_bits_for_keypair); 93 | if (retVal == 0) 94 | return 0; 95 | 96 | // bootstrap peers 97 | retVal = repo_config_bootstrap_peers_retrieve(&(config->peer_addresses)); 98 | if (retVal == 0) 99 | return 0; 100 | 101 | // datastore 102 | retVal = ipfs_repo_config_datastore_init(config->datastore, repo_path); 103 | if (retVal == 0) 104 | return 0; 105 | 106 | // swarm addresses 107 | char** address_array = (char * []){ "/ip4/0.0.0.0/tcp/4001", "/ip6/::/tcp/4001" }; 108 | retVal = repo_config_swarm_address_init(config->addresses->swarm, address_array, 2); 109 | if (retVal == 0) 110 | return 0; 111 | 112 | config->discovery.mdns.enabled = 1; 113 | config->discovery.mdns.interval = 10; 114 | 115 | config->mounts.ipfs = "/ipfs"; 116 | config->mounts.ipns = "/ipns"; 117 | 118 | config->ipns.resolve_cache_size = 128; 119 | 120 | config->reprovider.interval = "12h"; 121 | 122 | config->gateway->root_redirect = ""; 123 | config->gateway->writable = 0; 124 | 125 | config->gateway->path_prefixes.num_elements = 0; 126 | 127 | // gateway http headers 128 | char** header_array = (char * []) { "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", "Access-Control-Allow-Headers" }; 129 | char** header_values = (char*[]) { "*", "GET", "X-Requested-With" }; 130 | retVal = repo_config_gateway_http_header_init(config->gateway->http_headers, header_array, header_values, 3); 131 | if (retVal == 0) 132 | return 0; 133 | 134 | return 1; 135 | } 136 | 137 | /*** 138 | * Initialize memory for a RepoConfig struct 139 | * @param config the structure to initialize 140 | * @returns true(1) on success 141 | */ 142 | int ipfs_repo_config_new(struct RepoConfig** config) { 143 | *config = (struct RepoConfig*)malloc(sizeof(struct RepoConfig)); 144 | if (*config == NULL) 145 | return 0; 146 | 147 | // set initial values 148 | (*config)->peer_addresses.num_peers = 0; 149 | (*config)->peer_addresses.peers = NULL; 150 | 151 | int retVal = 1; 152 | retVal = repo_config_identity_new(&((*config)->identity)); 153 | if (retVal == 0) 154 | return 0; 155 | 156 | retVal = ipfs_repo_config_datastore_new(&((*config)->datastore)); 157 | if (retVal == 0) 158 | return 0; 159 | 160 | retVal = repo_config_addresses_new(&((*config)->addresses), "/ip4/127.0.0.1/tcp/5001", "/ip4/127.0.0.1/tcp/8080"); 161 | if (retVal == 0) 162 | return 0; 163 | 164 | retVal = repo_config_gateway_new(&((*config)->gateway)); 165 | if (retVal == 0) 166 | return 0; 167 | 168 | return 1; 169 | } 170 | 171 | /** 172 | * Free resources 173 | * @param config the struct to be freed 174 | * @returns true(1) on success 175 | */ 176 | int ipfs_repo_config_free(struct RepoConfig* config) { 177 | if (config != NULL) { 178 | if (config->identity != NULL) 179 | repo_config_identity_free(config->identity); 180 | if (&(config->peer_addresses) != NULL) 181 | repo_config_bootstrap_peers_free(&(config->peer_addresses)); 182 | if (config->datastore != NULL) 183 | ipfs_repo_config_datastore_free(config->datastore); 184 | if (config->addresses != NULL) 185 | repo_config_addresses_free(config->addresses); 186 | if (config->gateway != NULL) 187 | repo_config_gateway_free(config->gateway); 188 | free(config); 189 | } 190 | return 1; 191 | } 192 | 193 | int repo_config_martial_to_json(struct RepoConfig* config) { 194 | return 0; 195 | } 196 | 197 | -------------------------------------------------------------------------------- /repo/config/datastore.c: -------------------------------------------------------------------------------- 1 | // 2 | // datastore.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "ipfs/repo/config/datastore.h" 13 | #include "ipfs/os/utils.h" 14 | 15 | int alloc_and_assign(char** result, const char* string) { 16 | *result = malloc(strlen(string)+1); 17 | if (*result == NULL) 18 | return 0; 19 | strcpy(*result, string); 20 | return 1; 21 | } 22 | 23 | /*** 24 | * initialize the structure of the datastore 25 | * @param datastore the struct to initialize 26 | * @returns true(1) on success 27 | */ 28 | int ipfs_repo_config_datastore_init(struct Datastore* datastore, char* config_root) { 29 | unsigned long stringLength = strlen(config_root) + 12; 30 | datastore->path = malloc(sizeof(char) * stringLength); 31 | os_utils_filepath_join(config_root, "datastore", datastore->path, stringLength); 32 | alloc_and_assign(&datastore->type, "lmdb"); 33 | alloc_and_assign(&datastore->storage_max, "10GB"); 34 | datastore->storage_gc_watermark = 90; 35 | alloc_and_assign(&datastore->gc_period, "1h"); 36 | datastore->hash_on_read = 0; 37 | datastore->bloom_filter_size = 0; 38 | datastore->no_sync = 0; 39 | return 1; 40 | } 41 | 42 | /*** 43 | * initialize the structure of the datastore 44 | * @param datastore the struct to initialize 45 | * @returns true(1) on success 46 | */ 47 | int ipfs_repo_config_datastore_new(struct Datastore** datastore) { 48 | *datastore = malloc(sizeof(struct Datastore)); 49 | if (*datastore == NULL) 50 | return 0; 51 | (*datastore)->path = NULL; 52 | (*datastore)->handle = NULL; 53 | (*datastore)->type = NULL; 54 | (*datastore)->storage_max = NULL; 55 | (*datastore)->gc_period = NULL; 56 | (*datastore)->params = NULL; 57 | return 1; 58 | } 59 | 60 | /*** 61 | * deallocate the memory and clear resources from a datastore_init 62 | * @param datastore the struct to deallocate 63 | * @returns true(1) 64 | */ 65 | int ipfs_repo_config_datastore_free(struct Datastore* datastore) { 66 | if (datastore != NULL) 67 | { 68 | if (datastore->path != NULL) 69 | free(datastore->path); 70 | if (datastore->type != NULL) 71 | free(datastore->type); 72 | if (datastore->storage_max != NULL) 73 | free(datastore->storage_max); 74 | if (datastore->gc_period != NULL) 75 | free(datastore->gc_period); 76 | if (datastore->params != NULL) 77 | free(datastore->params); 78 | if (datastore->handle != NULL) 79 | datastore->datastore_close(datastore); 80 | free(datastore); 81 | } 82 | return 1; 83 | } 84 | -------------------------------------------------------------------------------- /repo/config/gateway.c: -------------------------------------------------------------------------------- 1 | // 2 | // gateway.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ipfs/repo/config/gateway.h" 14 | 15 | char* alloc_and_fill(char* source) { 16 | char* newString = malloc(sizeof(char) * (strlen(source) + 1)); 17 | strncpy(newString, source, strlen(source)); 18 | newString[strlen(source)] = 0; 19 | return newString; 20 | } 21 | 22 | int repo_config_gateway_http_header_init(struct HTTPHeaders* http_headers, char** headers, char** values, int num_elements) { 23 | // allocate memory for array 24 | http_headers->headers = malloc(sizeof(struct HTTPHeader*) * num_elements); 25 | if (http_headers->headers == NULL) { 26 | http_headers->num_elements = 0; 27 | return 0; 28 | } 29 | 30 | // now fill in the array 31 | for(int i = 0; i < num_elements; i++) { 32 | http_headers->headers[i] = malloc(sizeof(struct HTTPHeader)); 33 | if (http_headers->headers[i] == NULL) { 34 | http_headers->num_elements = i; 35 | return 0; 36 | } 37 | http_headers->headers[i]->header = alloc_and_fill(headers[i]); 38 | http_headers->headers[i]->value = alloc_and_fill(values[i]); 39 | } 40 | 41 | http_headers->num_elements = num_elements; 42 | return 1; 43 | } 44 | 45 | int repo_config_gateway_new(struct Gateway** gateway) { 46 | *gateway = (struct Gateway*)malloc(sizeof(struct Gateway)); 47 | if (*gateway == NULL) 48 | return 0; 49 | (*gateway)->http_headers = (struct HTTPHeaders*)malloc(sizeof(struct HTTPHeaders)); 50 | if ((*gateway)->http_headers == NULL) { 51 | free(*gateway); 52 | return 0; 53 | } 54 | (*gateway)->http_headers->num_elements = 0; 55 | (*gateway)->http_headers->headers = NULL; 56 | return 1; 57 | } 58 | 59 | int repo_config_gateway_free(struct Gateway* gateway) { 60 | if (gateway->http_headers != NULL) { 61 | for(int i = 0; i < gateway->http_headers->num_elements; i++) { 62 | struct HTTPHeader* currHeader = gateway->http_headers->headers[i]; 63 | free(currHeader->header); 64 | free(currHeader->value); 65 | free(currHeader); 66 | } 67 | if (gateway->http_headers->headers != NULL) 68 | free(gateway->http_headers->headers); // from init 69 | free(gateway->http_headers); // from new 70 | } 71 | free(gateway); // from new 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /repo/config/identity.c: -------------------------------------------------------------------------------- 1 | /** 2 | * an "Identity" 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ipfs/repo/config/identity.h" 10 | #include "libp2p/crypto/rsa.h" 11 | #include "libp2p/peerutils.h" 12 | #include "libp2p/crypto/encoding/base64.h" 13 | #include "libp2p/crypto/encoding/x509.h" 14 | 15 | /** 16 | * Builds the Peer ID using the private key, and places it in the identity->peer_id 17 | * @param identity Where to get the DER of the private key 18 | * @returns true(1) on success 19 | */ 20 | int repo_config_identity_build_peer_id(struct Identity* identity) { 21 | // ic key and PeerID 22 | char hash[32]; 23 | ID_FromPK_non_null_terminated(hash, identity->private_key.der, identity->private_key.der_length); 24 | 25 | // peer id is multihashed 26 | size_t sz = 255; 27 | char results[sz]; 28 | if (PrettyID(results, &sz, hash, 32) == 0) 29 | return 0; 30 | 31 | // copy it into the structure 32 | if (identity->peer_id != NULL) 33 | free(identity->peer_id); 34 | identity->peer_id = (char*)malloc(sz + 1); 35 | if (identity->peer_id == NULL) 36 | return 0; 37 | 38 | strncpy(identity->peer_id, results, sz); 39 | identity->peer_id[sz] = 0; 40 | return 1; 41 | } 42 | 43 | /*** 44 | * public methods 45 | */ 46 | 47 | /*** 48 | * Initializes a new Identity. NOTE: This builds a new private/public key pair 49 | * @param identity the identity to fill 50 | * @param num_bits_for_keypair the number of bits for the keypair 51 | * @returns true(1) on success, false(0) otherwise 52 | */ 53 | int repo_config_identity_init(struct Identity* identity, unsigned long num_bits_for_keypair) { 54 | if (num_bits_for_keypair < 1024) 55 | return 0; 56 | // generate the private key (& public) 57 | if (!libp2p_crypto_rsa_generate_keypair( &(identity->private_key), num_bits_for_keypair)) 58 | return 0; 59 | 60 | if (repo_config_identity_build_peer_id(identity) == 0) 61 | return 0; 62 | 63 | return 1; 64 | } 65 | 66 | int repo_config_identity_new(struct Identity** identity) { 67 | *identity = (struct Identity*)malloc(sizeof(struct Identity)); 68 | if (*identity == NULL) 69 | return 0; 70 | 71 | memset(*identity, 0, sizeof(struct Identity)); 72 | 73 | (*identity)->peer_id = NULL; 74 | (*identity)->private_key.public_key_der = NULL; 75 | (*identity)->private_key.der = NULL; 76 | 77 | return 1; 78 | } 79 | 80 | int repo_config_identity_free(struct Identity* identity) { 81 | if (identity != NULL) { 82 | if (identity->private_key.public_key_der != NULL) 83 | free(identity->private_key.public_key_der); 84 | if (identity->private_key.der != NULL) 85 | free(identity->private_key.der); 86 | if (identity->peer_id != NULL) 87 | free(identity->peer_id); 88 | free(identity); 89 | } 90 | return 1; 91 | } 92 | 93 | /*** 94 | * Build a RsaPrivateKey struct from a base64 string of the private key 95 | * @param identity where to put the new struct 96 | * @param base64 the null terminated base 64 encoded private key in DER format 97 | * @returns true(1) on success 98 | */ 99 | int repo_config_identity_build_private_key(struct Identity* identity, const char* base64) { 100 | size_t decoded_size = libp2p_crypto_encoding_base64_decode_size(strlen(base64)); 101 | unsigned char decoded[decoded_size]; 102 | 103 | int retVal = libp2p_crypto_encoding_base64_decode(base64, strlen(base64), decoded, decoded_size, &decoded_size); 104 | if (retVal == 0) 105 | return 0; 106 | 107 | // now convert DER to RsaPrivateKey 108 | retVal = libp2p_crypto_encoding_x509_der_to_private_key(decoded, decoded_size, &identity->private_key); 109 | if (retVal == 0) 110 | return 0; 111 | 112 | // now build the private key DER 113 | retVal = libp2p_crypto_rsa_private_key_fill_public_key(&identity->private_key); 114 | if (retVal == 0) 115 | return 0; 116 | 117 | // now build PeerID 118 | retVal = repo_config_identity_build_peer_id(identity); 119 | 120 | return retVal; 121 | } 122 | -------------------------------------------------------------------------------- /repo/config/peer.c: -------------------------------------------------------------------------------- 1 | // 2 | // NOTE: this should be moved to libp2p-peer when it is built 3 | 4 | #include 5 | 6 | #include "ipfs/repo/config/peer.h" 7 | 8 | /* from libp2p-crypto/rsa.go 9 | 10 | func (pk *RsaPublicKey) Bytes() ([]byte, error) { 11 | // x509.MarshalPKIXPublicKey(byte[]) serialises a public key to DER-encoded PKIX format 12 | 13 | b, err := x509.MarshalPKIXPublicKey(pk.k) 14 | if err != nil { 15 | return nil, err 16 | } 17 | 18 | pbmes := new(pb.PublicKey) 19 | typ := pb.KeyType_RSA 20 | pbmes.Type = &typ 21 | pbmes.Data = b 22 | return proto.Marshal(pbmes) 23 | } 24 | 25 | */ 26 | 27 | /* 28 | // from libp2p-peer/peer.go 29 | // IDFromPublicKey returns the Peer ID corresponding to pk 30 | func IDFromPublicKey(pk ic.PubKey) (ID, error) { 31 | b, err := pk.Bytes() 32 | if err != nil { 33 | return "", err 34 | } 35 | hash := u.Hash(b) 36 | return ID(hash), nil 37 | } 38 | 39 | */ 40 | 41 | 42 | /*** 43 | * public methods 44 | */ 45 | 46 | int repo_config_peer_id_from_public_key(char* public_key, char* id) { 47 | // convert to bytes 48 | // hash 49 | // return ID(hash) 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /repo/config/swarm.c: -------------------------------------------------------------------------------- 1 | // 2 | // swarm.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ipfs/repo/config/swarm.h" 14 | 15 | 16 | int repo_config_swarm_address_init(struct SwarmAddresses* swarm_addresses, char** addresses, int array_length) { 17 | // allocate memory for the addresses array 18 | swarm_addresses->addresses = malloc(sizeof(char*) * array_length); 19 | if (swarm_addresses->addresses == NULL) 20 | return 0; 21 | 22 | // copy in all the strings 23 | for(int i = 0; i < array_length; i++) { 24 | char* newString = malloc(sizeof(char) * (strlen(addresses[i]) + 1)); 25 | if (newString == NULL) 26 | return 0; 27 | strncpy(newString, addresses[i], strlen(addresses[i])); 28 | newString[strlen(addresses[i])] = 0; 29 | swarm_addresses->addresses[i] = newString; 30 | } 31 | 32 | swarm_addresses->num_addresses = array_length; 33 | 34 | return 1; 35 | } 36 | 37 | int repo_config_swarm_address_new(struct SwarmAddresses** swarm_addresses) { 38 | *swarm_addresses = (struct SwarmAddresses*)malloc(sizeof(struct SwarmAddresses)); 39 | if (*swarm_addresses == NULL) 40 | return 0; 41 | 42 | (*swarm_addresses)->num_addresses = 0; 43 | (*swarm_addresses)->addresses = NULL; 44 | return 1; 45 | } 46 | 47 | int repo_config_swarm_address_free(struct SwarmAddresses* swarm_addresses) { 48 | if (swarm_addresses->addresses != NULL) { 49 | for (int i = 0; i < swarm_addresses->num_addresses; i++) { 50 | free(swarm_addresses->addresses[i]); 51 | } 52 | free(swarm_addresses->addresses); 53 | } 54 | free(swarm_addresses); 55 | return 1; 56 | } 57 | -------------------------------------------------------------------------------- /repo/fsrepo/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../lmdb/libraries/liblmdb 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = fs_repo.o jsmn.o lmdb_datastore.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /repo/fsrepo/jsmn.c: -------------------------------------------------------------------------------- 1 | #include "jsmn.h" 2 | 3 | /** 4 | * Allocates a fresh unused token from the token pull. 5 | */ 6 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 7 | jsmntok_t *tokens, size_t num_tokens) { 8 | jsmntok_t *tok; 9 | if (parser->toknext >= num_tokens) { 10 | return NULL; 11 | } 12 | tok = &tokens[parser->toknext++]; 13 | tok->start = tok->end = -1; 14 | tok->size = 0; 15 | #ifdef JSMN_PARENT_LINKS 16 | tok->parent = -1; 17 | #endif 18 | return tok; 19 | } 20 | 21 | /** 22 | * Fills token type and boundaries. 23 | */ 24 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 25 | int start, int end) { 26 | token->type = type; 27 | token->start = start; 28 | token->end = end; 29 | token->size = 0; 30 | } 31 | 32 | /** 33 | * Fills next available token with JSON primitive. 34 | */ 35 | static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 36 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 37 | jsmntok_t *token; 38 | int start; 39 | 40 | start = parser->pos; 41 | 42 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 43 | switch (js[parser->pos]) { 44 | #ifndef JSMN_STRICT 45 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 46 | case ':': 47 | #endif 48 | case '\t' : case '\r' : case '\n' : case ' ' : 49 | case ',' : case ']' : case '}' : 50 | goto found; 51 | } 52 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 53 | parser->pos = start; 54 | return JSMN_ERROR_INVAL; 55 | } 56 | } 57 | #ifdef JSMN_STRICT 58 | /* In strict mode primitive must be followed by a comma/object/array */ 59 | parser->pos = start; 60 | return JSMN_ERROR_PART; 61 | #endif 62 | 63 | found: 64 | if (tokens == NULL) { 65 | parser->pos--; 66 | return 0; 67 | } 68 | token = jsmn_alloc_token(parser, tokens, num_tokens); 69 | if (token == NULL) { 70 | parser->pos = start; 71 | return JSMN_ERROR_NOMEM; 72 | } 73 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 74 | #ifdef JSMN_PARENT_LINKS 75 | token->parent = parser->toksuper; 76 | #endif 77 | parser->pos--; 78 | return 0; 79 | } 80 | 81 | /** 82 | * Fills next token with JSON string. 83 | */ 84 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, 85 | size_t len, jsmntok_t *tokens, size_t num_tokens) { 86 | jsmntok_t *token; 87 | 88 | int start = parser->pos; 89 | 90 | parser->pos++; 91 | 92 | /* Skip starting quote */ 93 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 94 | char c = js[parser->pos]; 95 | 96 | /* Quote: end of string */ 97 | if (c == '\"') { 98 | if (tokens == NULL) { 99 | return 0; 100 | } 101 | token = jsmn_alloc_token(parser, tokens, num_tokens); 102 | if (token == NULL) { 103 | parser->pos = start; 104 | return JSMN_ERROR_NOMEM; 105 | } 106 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 107 | #ifdef JSMN_PARENT_LINKS 108 | token->parent = parser->toksuper; 109 | #endif 110 | return 0; 111 | } 112 | 113 | /* Backslash: Quoted symbol expected */ 114 | if (c == '\\' && parser->pos + 1 < len) { 115 | int i; 116 | parser->pos++; 117 | switch (js[parser->pos]) { 118 | /* Allowed escaped symbols */ 119 | case '\"': case '/' : case '\\' : case 'b' : 120 | case 'f' : case 'r' : case 'n' : case 't' : 121 | break; 122 | /* Allows escaped symbol \uXXXX */ 123 | case 'u': 124 | parser->pos++; 125 | for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 126 | /* If it isn't a hex character we have an error */ 127 | if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 128 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 129 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 130 | parser->pos = start; 131 | return JSMN_ERROR_INVAL; 132 | } 133 | parser->pos++; 134 | } 135 | parser->pos--; 136 | break; 137 | /* Unexpected symbol */ 138 | default: 139 | parser->pos = start; 140 | return JSMN_ERROR_INVAL; 141 | } 142 | } 143 | } 144 | parser->pos = start; 145 | return JSMN_ERROR_PART; 146 | } 147 | 148 | /** 149 | * Parse JSON string and fill tokens. 150 | */ 151 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 152 | jsmntok_t *tokens, unsigned int num_tokens) { 153 | int r; 154 | int i; 155 | jsmntok_t *token; 156 | int count = parser->toknext; 157 | 158 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 159 | char c; 160 | jsmntype_t type; 161 | 162 | c = js[parser->pos]; 163 | switch (c) { 164 | case '{': case '[': 165 | count++; 166 | if (tokens == NULL) { 167 | break; 168 | } 169 | token = jsmn_alloc_token(parser, tokens, num_tokens); 170 | if (token == NULL) 171 | return JSMN_ERROR_NOMEM; 172 | if (parser->toksuper != -1) { 173 | tokens[parser->toksuper].size++; 174 | #ifdef JSMN_PARENT_LINKS 175 | token->parent = parser->toksuper; 176 | #endif 177 | } 178 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 179 | token->start = parser->pos; 180 | parser->toksuper = parser->toknext - 1; 181 | break; 182 | case '}': case ']': 183 | if (tokens == NULL) 184 | break; 185 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 186 | #ifdef JSMN_PARENT_LINKS 187 | if (parser->toknext < 1) { 188 | return JSMN_ERROR_INVAL; 189 | } 190 | token = &tokens[parser->toknext - 1]; 191 | for (;;) { 192 | if (token->start != -1 && token->end == -1) { 193 | if (token->type != type) { 194 | return JSMN_ERROR_INVAL; 195 | } 196 | token->end = parser->pos + 1; 197 | parser->toksuper = token->parent; 198 | break; 199 | } 200 | if (token->parent == -1) { 201 | if(token->type != type || parser->toksuper == -1) { 202 | return JSMN_ERROR_INVAL; 203 | } 204 | break; 205 | } 206 | token = &tokens[token->parent]; 207 | } 208 | #else 209 | for (i = parser->toknext - 1; i >= 0; i--) { 210 | token = &tokens[i]; 211 | if (token->start != -1 && token->end == -1) { 212 | if (token->type != type) { 213 | return JSMN_ERROR_INVAL; 214 | } 215 | parser->toksuper = -1; 216 | token->end = parser->pos + 1; 217 | break; 218 | } 219 | } 220 | /* Error if unmatched closing bracket */ 221 | if (i == -1) return JSMN_ERROR_INVAL; 222 | for (; i >= 0; i--) { 223 | token = &tokens[i]; 224 | if (token->start != -1 && token->end == -1) { 225 | parser->toksuper = i; 226 | break; 227 | } 228 | } 229 | #endif 230 | break; 231 | case '\"': 232 | r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 233 | if (r < 0) return r; 234 | count++; 235 | if (parser->toksuper != -1 && tokens != NULL) 236 | tokens[parser->toksuper].size++; 237 | break; 238 | case '\t' : case '\r' : case '\n' : case ' ': 239 | break; 240 | case ':': 241 | parser->toksuper = parser->toknext - 1; 242 | break; 243 | case ',': 244 | if (tokens != NULL && parser->toksuper != -1 && 245 | tokens[parser->toksuper].type != JSMN_ARRAY && 246 | tokens[parser->toksuper].type != JSMN_OBJECT) { 247 | #ifdef JSMN_PARENT_LINKS 248 | parser->toksuper = tokens[parser->toksuper].parent; 249 | #else 250 | for (i = parser->toknext - 1; i >= 0; i--) { 251 | if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 252 | if (tokens[i].start != -1 && tokens[i].end == -1) { 253 | parser->toksuper = i; 254 | break; 255 | } 256 | } 257 | } 258 | #endif 259 | } 260 | break; 261 | #ifdef JSMN_STRICT 262 | /* In strict mode primitives are: numbers and booleans */ 263 | case '-': case '0': case '1' : case '2': case '3' : case '4': 264 | case '5': case '6': case '7' : case '8': case '9': 265 | case 't': case 'f': case 'n' : 266 | /* And they must not be keys of the object */ 267 | if (tokens != NULL && parser->toksuper != -1) { 268 | jsmntok_t *t = &tokens[parser->toksuper]; 269 | if (t->type == JSMN_OBJECT || 270 | (t->type == JSMN_STRING && t->size != 0)) { 271 | return JSMN_ERROR_INVAL; 272 | } 273 | } 274 | #else 275 | /* In non-strict mode every unquoted value is a primitive */ 276 | default: 277 | #endif 278 | r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 279 | if (r < 0) return r; 280 | count++; 281 | if (parser->toksuper != -1 && tokens != NULL) 282 | tokens[parser->toksuper].size++; 283 | break; 284 | 285 | #ifdef JSMN_STRICT 286 | /* Unexpected char in strict mode */ 287 | default: 288 | return JSMN_ERROR_INVAL; 289 | #endif 290 | } 291 | } 292 | 293 | if (tokens != NULL) { 294 | for (i = parser->toknext - 1; i >= 0; i--) { 295 | /* Unmatched opened object or array */ 296 | if (tokens[i].start != -1 && tokens[i].end == -1) { 297 | return JSMN_ERROR_PART; 298 | } 299 | } 300 | } 301 | 302 | return count; 303 | } 304 | 305 | /** 306 | * Creates a new parser based over a given buffer with an array of tokens 307 | * available. 308 | */ 309 | void jsmn_init(jsmn_parser *parser) { 310 | parser->pos = 0; 311 | parser->toknext = 0; 312 | parser->toksuper = -1; 313 | } 314 | -------------------------------------------------------------------------------- /repo/fsrepo/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_UNDEFINED = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3, 22 | JSMN_PRIMITIVE = 4 23 | } jsmntype_t; 24 | 25 | enum jsmnerr { 26 | /* Not enough tokens were provided */ 27 | JSMN_ERROR_NOMEM = -1, 28 | /* Invalid character inside JSON string */ 29 | JSMN_ERROR_INVAL = -2, 30 | /* The string is not a full JSON packet, more bytes expected */ 31 | JSMN_ERROR_PART = -3 32 | }; 33 | 34 | /** 35 | * JSON token description. 36 | * type type (object, array, string etc.) 37 | * start start position in JSON data string 38 | * end end position in JSON data string 39 | */ 40 | typedef struct { 41 | jsmntype_t type; 42 | int start; 43 | int end; 44 | int size; 45 | #ifdef JSMN_PARENT_LINKS 46 | int parent; 47 | #endif 48 | } jsmntok_t; 49 | 50 | /** 51 | * JSON parser. Contains an array of token blocks available. Also stores 52 | * the string being parsed now and current position in that string 53 | */ 54 | typedef struct { 55 | unsigned int pos; /* offset in the JSON string */ 56 | unsigned int toknext; /* next token to allocate */ 57 | int toksuper; /* superior token node, e.g parent object or array */ 58 | } jsmn_parser; 59 | 60 | /** 61 | * Create JSON parser over an array of tokens 62 | */ 63 | void jsmn_init(jsmn_parser *parser); 64 | 65 | /** 66 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 67 | * a single JSON object. 68 | */ 69 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 70 | jsmntok_t *tokens, unsigned int num_tokens); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* __JSMN_H_ */ 77 | -------------------------------------------------------------------------------- /repo/fsrepo/lmdb_datastore.c: -------------------------------------------------------------------------------- 1 | /*** 2 | * Here are the wrappers for the lightning database 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "lmdb.h" 11 | #include "ipfs/repo/fsrepo/lmdb_datastore.h" 12 | 13 | /** 14 | * Write a block to the datastore with the specified key 15 | * @param key the key 16 | * @param block the block to be written 17 | * @returns true(1) on success 18 | */ 19 | int repo_fsrepo_lmdb_put(const char* key, size_t key_size, struct Block* block, struct Datastore* datastore) { 20 | int retVal; 21 | MDB_txn* mdb_txn; 22 | MDB_dbi mdb_dbi; 23 | struct MDB_val db_key; 24 | struct MDB_val db_value; 25 | 26 | MDB_env* mdb_env = (MDB_env*)datastore->handle; 27 | if (mdb_env == NULL) 28 | return 0; 29 | 30 | // open transaction 31 | retVal = mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn); 32 | if (retVal != 0) 33 | return 0; 34 | retVal = mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi); 35 | if (retVal != 0) 36 | return 0; 37 | 38 | // write 39 | db_key.mv_size = key_size; 40 | db_key.mv_data = (char*)key; 41 | db_value.mv_size = block->data_length; 42 | db_value.mv_data = block->data; 43 | retVal = mdb_put(mdb_txn, mdb_dbi, &db_key, &db_value, MDB_NODUPDATA); 44 | if (retVal != 0) 45 | return 0; 46 | 47 | // cleanup 48 | mdb_dbi_close(mdb_env, mdb_dbi); 49 | mdb_txn_commit(mdb_txn); 50 | return 1; 51 | } 52 | 53 | 54 | 55 | /** 56 | * Open an lmdb database with the given parameters. 57 | * Note: for now, the parameters are not used 58 | * @param argc number of parameters in the following array 59 | * @param argv an array of parameters 60 | */ 61 | int repo_fsrepro_lmdb_open(int argc, char** argv, struct Datastore* datastore) { 62 | // create environment 63 | struct MDB_env* mdb_env; 64 | int retVal = mdb_env_create(&mdb_env); 65 | if (retVal < 0) { 66 | mdb_env_close(mdb_env); 67 | return 0; 68 | } 69 | 70 | // open the environment 71 | retVal = mdb_env_open(mdb_env, datastore->path, 0, S_IRWXU); 72 | if (retVal < 0) { 73 | mdb_env_close(mdb_env); 74 | return 0; 75 | } 76 | 77 | datastore->handle = (void*)mdb_env; 78 | return 1; 79 | } 80 | 81 | /*** 82 | * Close an LMDB database 83 | * NOTE: for now, argc and argv are not used 84 | * @param argc number of parameters in the argv array 85 | * @param argv parameters to be passed in 86 | * @param datastore the datastore struct that contains information about the opened database 87 | */ 88 | int repo_fsrepo_lmdb_close(struct Datastore* datastore) { 89 | struct MDB_env* mdb_env = (struct MDB_env*)datastore->handle; 90 | mdb_env_close(mdb_env); 91 | return 1; 92 | } 93 | 94 | /*** 95 | * Places the LMDB methods into the datastore's function pointers 96 | * @param datastore the datastore to fill 97 | * @returns true(1) on success; 98 | */ 99 | int repo_fsrepo_lmdb_cast(struct Datastore* datastore) { 100 | datastore->datastore_open = &repo_fsrepro_lmdb_open; 101 | datastore->datastore_close = &repo_fsrepo_lmdb_close; 102 | datastore->datastore_put = &repo_fsrepo_lmdb_put; 103 | //datastore->datastore_get = &repo_fsrepo_lmdb_get; 104 | return 1; 105 | } 106 | 107 | /*** 108 | * Creates the directory 109 | * @param datastore contains the path that needs to be created 110 | * @returns true(1) on success 111 | */ 112 | int repo_fsrepo_lmdb_create_directory(struct Datastore* datastore) { 113 | return mkdir(datastore->path, S_IRWXU) == 0; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/ -g3 3 | LFLAGS = -L../../c-libp2p -L../../c-multihash -L../../c-multiaddr -lp2p -lm -lmultihash -lmultiaddr -lpthread 4 | DEPS = cmd/ipfs/test_init.h repo/test_repo_bootstrap_peers.h repo/test_repo_config.h repo/test_repo_identity.h cid/test_cid.h 5 | OBJS = testit.o ../cmd/ipfs/init.o ../commands/argument.o ../commands/command_option.o \ 6 | ../commands/command.o ../commands/cli/parse.o ../core/builder.o ../repo/fsrepo/fs_repo.o \ 7 | ../repo/fsrepo/jsmn.o ../repo/fsrepo/lmdb_datastore.o ../repo/config/config.o ../os/utils.o ../repo/config/identity.o \ 8 | ../repo/config/bootstrap_peers.o ../repo/config/datastore.o ../repo/config/gateway.o \ 9 | ../repo/config/addresses.o ../repo/config/swarm.o ../repo/config/peer.o \ 10 | ../thirdparty/ipfsaddr/ipfs_addr.o ../cid/cid.o ../multibase/multibase.o \ 11 | ../flatfs/flatfs.o ../blocks/block.o ../blocks/blockstore.o \ 12 | ../datastore/ds_helper.o 13 | 14 | %.o: %.c $(DEPS) 15 | $(CC) -c -o $@ $< $(CFLAGS) 16 | 17 | test_ipfs: $(OBJS) 18 | $(CC) -o $@ $^ $(LFLAGS) ../../lmdb/libraries/liblmdb/liblmdb.a 19 | 20 | all: test_ipfs 21 | 22 | clean: 23 | rm -f *.o 24 | rm -f test_ipfs -------------------------------------------------------------------------------- /test/cid/test_cid.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mh/hashes.h" 4 | #include "mh/multihash.h" 5 | 6 | #include "ipfs/cid/cid.h" 7 | #include "ipfs/multibase/multibase.h" 8 | 9 | #include "libp2p/crypto/sha256.h" 10 | 11 | int test_cid_new_free() { 12 | 13 | struct Cid* cid; 14 | const unsigned char* hash = "ABC123"; 15 | int retVal = ipfs_cid_new(0, (unsigned char*)hash, strlen((char*)hash), CID_PROTOBUF, &cid); 16 | if (retVal == 0) 17 | return 0; 18 | 19 | if (cid->version != 0) 20 | return 0; 21 | 22 | if (cid->codec != CID_PROTOBUF) 23 | return 0; 24 | 25 | if (cid->hash_length != strlen((char*)hash)) 26 | return 0; 27 | 28 | if (strncmp((char*)cid->hash, (char*)hash, 6) != 0) 29 | return 0; 30 | 31 | return ipfs_cid_free(cid); 32 | } 33 | 34 | /*** 35 | * Test sending a multibase encoded multihash into cid_cast method 36 | * that should return a Cid struct 37 | */ 38 | int test_cid_cast_multihash() { 39 | // first, build a multihash 40 | char* string_to_hash = "Hello, World!"; 41 | unsigned char hashed[32]; 42 | memset(hashed, 0, 32); 43 | // hash the string 44 | libp2p_crypto_hashing_sha256(string_to_hash, strlen(string_to_hash), hashed); 45 | size_t multihash_size = mh_new_length(MH_H_SHA2_256, 32); 46 | unsigned char multihash[multihash_size]; 47 | memset(multihash, 0, multihash_size); 48 | unsigned char* ptr = multihash; 49 | 50 | int retVal = mh_new(ptr, MH_H_SHA2_256, hashed, 32); 51 | if (retVal < 0) 52 | return 0; 53 | 54 | // now call cast 55 | struct Cid cid; 56 | retVal = ipfs_cid_cast(multihash, multihash_size, &cid); 57 | if (retVal == 0) 58 | return 0; 59 | // check results 60 | if (cid.version != 0) 61 | return 0; 62 | if (cid.hash_length != 32) 63 | return 0; 64 | if (cid.codec != CID_PROTOBUF) 65 | return 0; 66 | if (strncmp(hashed, cid.hash, 32) != 0) 67 | return 0; 68 | 69 | return 1; 70 | } 71 | 72 | int test_cid_cast_non_multihash() { 73 | // first, build a hash 74 | char* string_to_hash = "Hello, World!"; 75 | unsigned char hashed[32]; 76 | memset(hashed, 0, 32); 77 | // hash the string 78 | libp2p_crypto_hashing_sha256(string_to_hash, strlen(string_to_hash), hashed); 79 | 80 | // now make it a hash with a version and codec embedded in varints before the hash 81 | size_t array_size = 34; // 32 for the hash, 2 for the 2 varints 82 | unsigned char array[array_size]; 83 | memset(array, 0, array_size); 84 | // first the version 85 | array[0] = 0; 86 | // then the codec 87 | array[1] = CID_PROTOBUF; 88 | // then the hash 89 | memcpy(&array[2], hashed, 32); 90 | 91 | // now call cast 92 | struct Cid cid; 93 | int retVal = ipfs_cid_cast(array, array_size, &cid); 94 | if (retVal == 0) 95 | return 0; 96 | // check results 97 | if (cid.version != 0) 98 | return 0; 99 | if (cid.hash_length != 32) 100 | return 0; 101 | if (cid.codec != CID_PROTOBUF) 102 | return 0; 103 | if (strncmp(hashed, cid.hash, 32) != 0) 104 | return 0; 105 | 106 | return 1; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /test/cmd/ipfs/test_init.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Testing of cmd/ipfs/init 3 | */ 4 | #ifndef __TEST_INIT_H__ 5 | #define __TEST_INIT_H__ 6 | 7 | #include "ipfs/cmd/ipfs/init.h" 8 | #include "ipfs/commands/argument.h" 9 | #include "ipfs/commands/request.h" 10 | #include "ipfs/commands/command.h" 11 | 12 | #include 13 | //#include 14 | 15 | int test_init_new_installation() { 16 | unlink("/tmp/.ipfs/config"); 17 | // do the minimum to get the .ipfs directory structure and config file built 18 | struct Request request; 19 | int retVal = ipfs_cmd_ipfs_init_command_new( &request.cmd ); 20 | if (retVal == 0) 21 | return 0; 22 | 23 | // build a request so it builds the repository in the /tmp directory 24 | request.invoc_context = (struct Context*)malloc(sizeof(struct Context)); 25 | request.invoc_context->config_root = "/tmp/.ipfs"; 26 | 27 | // run the methods 28 | 29 | retVal = request.cmd.pre_run(&request); 30 | if (retVal == 0) { 31 | free(request.invoc_context); 32 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 33 | return 0; 34 | } 35 | 36 | retVal = request.cmd.run(&request); 37 | if (retVal == 0) { 38 | free(request.invoc_context); 39 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 40 | return 0; 41 | } 42 | 43 | retVal = request.cmd.post_run(&request); 44 | if (retVal == 0) { 45 | free(request.invoc_context); 46 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 47 | return 0; 48 | } 49 | 50 | // clean up 51 | ipfs_cmd_ipfs_init_command_free( &request.cmd ); 52 | free(request.invoc_context); 53 | 54 | // make sure the repository exists 55 | retVal = os_utils_file_exists("/tmp/.ipfs/config"); 56 | 57 | return retVal; 58 | } 59 | 60 | /*** 61 | * This is used for the command line interpreter, which is still in development 62 | */ 63 | int test_get_init_command() { 64 | struct Command cmd = { 0 }; 65 | int retVal = 1; 66 | // make sure its empty 67 | if (cmd.help_text.tagline != NULL) { 68 | fprintf(stderr, "short description should be null\n"); 69 | return 0; 70 | } 71 | // grab the stuff 72 | retVal = ipfs_cmd_ipfs_init_command_new(&cmd); 73 | 74 | if (!retVal) { 75 | fprintf(stderr, "Function call to get_init_command not successful. Return was %d\n", retVal); 76 | return retVal; 77 | } 78 | // make sure its right 79 | if (cmd.help_text.tagline == NULL) { 80 | fprintf(stderr, "short description is null\n"); 81 | retVal = 0; 82 | } else if (strcmp(cmd.help_text.tagline, "Initializes IPFS config file.") != 0) { 83 | fprintf(stderr, "short description is not null\n"); 84 | retVal = 0; 85 | } else if (cmd.argument_count != 1) { 86 | fprintf(stderr, "argument count should be 1"); 87 | retVal = 0; 88 | } else { 89 | struct Argument arg1 = *(cmd.arguments[0]); 90 | if (strncmp(arg1.name, "default-config", 14) != 0) { 91 | fprintf(stderr, "arg1 wrong name. Expected %s but got %s\n", "default_config", arg1.name); 92 | retVal = 0; 93 | } 94 | } 95 | ipfs_cmd_ipfs_init_command_free(&cmd); 96 | return retVal; 97 | } 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /test/flatfs/test_flatfs.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/flatfs/flatfs.h" 2 | 3 | int test_flatfs_get_directory() { 4 | char* datastore_directory = "/tmp/"; 5 | char* proposed_filename = "/ABC123XYZ"; 6 | size_t results_len = 256; 7 | char results[results_len]; 8 | 9 | // buffer too small 10 | int retVal = ipfs_flatfs_get_directory(datastore_directory, proposed_filename, results, 21); 11 | if (retVal != 0) 12 | return 0; 13 | 14 | // buffer just right 15 | retVal = ipfs_flatfs_get_directory(datastore_directory, proposed_filename, results, 22); 16 | if (retVal == 0) 17 | return 0; 18 | if (strcmp(results, "/tmp/ABC123XYZ_______") != 0) 19 | return 0; 20 | 21 | // name too long 22 | proposed_filename = "12345678901234567"; 23 | retVal = ipfs_flatfs_get_directory(datastore_directory, proposed_filename, results, 22); 24 | if (retVal == 0) 25 | return 0; 26 | if (strcmp(results, "/tmp/1234567890123456") != 0) 27 | return 0; 28 | 29 | return 1; 30 | } 31 | 32 | int test_flatfs_get_filename() { 33 | char* proposed_filename = "/ABC123XYZ"; 34 | size_t results_len = 256; 35 | char results[results_len]; 36 | 37 | // buffer too small 38 | int retVal = ipfs_flatfs_get_filename(proposed_filename, results, 14); 39 | if (retVal != 0) 40 | return 0; 41 | 42 | // buffer just right 43 | retVal = ipfs_flatfs_get_filename(proposed_filename, results, 15); 44 | if (retVal == 0) 45 | return 0; 46 | if (strcmp(results, "ABC123XYZ.data") != 0) 47 | return 0; 48 | 49 | return 1; 50 | 51 | } 52 | 53 | int test_flatfs_get_full_filename() { 54 | char* datastore_directory = "/tmp/"; 55 | char* proposed_filename = "/ABC123XYZ"; 56 | size_t results_len = 256; 57 | char results[results_len]; 58 | 59 | // buffer too small 60 | int retVal = ipfs_flatfs_get_full_filename(datastore_directory, proposed_filename, results, 21); 61 | if (retVal != 0) 62 | return 0; 63 | 64 | // buffer just right 65 | retVal = ipfs_flatfs_get_full_filename(datastore_directory, proposed_filename, results, 50); 66 | if (retVal == 0) 67 | return 0; 68 | if (strcmp(results, "/tmp/ABC123XYZ_______/ABC123XYZ.data") != 0) 69 | return 0; 70 | 71 | // name too long 72 | proposed_filename = "12345678901234567"; 73 | retVal = ipfs_flatfs_get_full_filename(datastore_directory, proposed_filename, results, 50); 74 | if (retVal == 0) 75 | return 0; 76 | if (strcmp(results, "/tmp/1234567890123456/12345678901234567.data") != 0) 77 | return 0; 78 | 79 | return 1; 80 | } 81 | -------------------------------------------------------------------------------- /test/repo/test_repo_bootstrap_peers.h: -------------------------------------------------------------------------------- 1 | // 2 | // test_repo_bootstrap_peers.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef test_repo_bootstrap_peers_h 10 | #define test_repo_bootstrap_peers_h 11 | 12 | //#include 13 | 14 | #include "ipfs/repo/config/bootstrap_peers.h" 15 | 16 | int test_repo_bootstrap_peers_init() { 17 | 18 | char* default_bootstrap_addresses[] = { 19 | "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io 20 | "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune.i.ipfs.io 21 | "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io 22 | "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus.i.ipfs.io 23 | "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io 24 | "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io 25 | "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io 26 | "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury.i.ipfs.io 27 | "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter.i.ipfs.io 28 | }; 29 | 30 | struct BootstrapPeers list; 31 | int retVal = 1; 32 | repo_config_bootstrap_peers_retrieve(&list); 33 | if ( list.num_peers != 9) { 34 | printf("Size does not equal 9 in test_repo_bootstrap_peers_init"); 35 | retVal = 0; 36 | } 37 | for(int i = 0; i < list.num_peers; i++) { 38 | unsigned long strLen = strlen(default_bootstrap_addresses[i]); 39 | if (strncmp(list.peers[i]->entire_string, default_bootstrap_addresses[i], strLen) != 0) 40 | printf("The value of element %d is: %s\n", i, list.peers[i]->entire_string); 41 | } 42 | repo_config_bootstrap_peers_free(&list); 43 | return retVal; 44 | } 45 | 46 | #endif /* test_repo_bootstrap_peers_h */ 47 | -------------------------------------------------------------------------------- /test/repo/test_repo_config.h: -------------------------------------------------------------------------------- 1 | // 2 | // test_repo_config.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/31/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef test_repo_config_h 10 | #define test_repo_config_h 11 | 12 | #include "ipfs/repo/config/config.h" 13 | #include "ipfs/repo/fsrepo/fs_repo.h" 14 | #include "ipfs/os/utils.h" 15 | 16 | int test_repo_config_new() { 17 | struct RepoConfig* repoConfig; 18 | int retVal = ipfs_repo_config_new(&repoConfig); 19 | if (retVal == 0) 20 | return 0; 21 | 22 | retVal = ipfs_repo_config_free(repoConfig); 23 | if (retVal == 0) 24 | return 0; 25 | 26 | return 1; 27 | } 28 | 29 | int test_repo_config_init() { 30 | struct RepoConfig* repoConfig; 31 | int retVal = ipfs_repo_config_new(&repoConfig); 32 | if (retVal == 0) 33 | return 0; 34 | 35 | retVal = ipfs_repo_config_init(repoConfig, 2048, "/Users/JohnJones/.ipfs"); 36 | if (retVal == 0) 37 | return 0; 38 | 39 | // now tear it apart to check for anything broken 40 | 41 | // addresses 42 | retVal = strncmp(repoConfig->addresses->api, "/ip4/127.0.0.1/tcp/5001", 23); 43 | if (retVal != 0) 44 | return 0; 45 | retVal = strncmp(repoConfig->addresses->gateway, "/ip4/127.0.0.1/tcp/8080", 23); 46 | if (retVal != 0) 47 | return 0; 48 | 49 | if (repoConfig->addresses->swarm->num_addresses != 2) 50 | return 0; 51 | 52 | retVal = strncmp(repoConfig->addresses->swarm->addresses[0], "/ip4/0.0.0.0/tcp/4001", 21); 53 | if (retVal != 0) 54 | return 0; 55 | 56 | retVal = strncmp(repoConfig->addresses->swarm->addresses[1], "/ip6/::/tcp/4001", 16); 57 | if (retVal != 0) 58 | return 0; 59 | 60 | // datastore 61 | retVal = strncmp(repoConfig->datastore->path, "/Users/JohnJones/.ipfs/datastore", 32); 62 | if (retVal != 0) 63 | return 0; 64 | 65 | ipfs_repo_config_free(repoConfig); 66 | 67 | return 1; 68 | } 69 | 70 | /*** 71 | * test the writing of the config file 72 | */ 73 | int test_repo_config_write() { 74 | // first delete the existing one 75 | unlink("/tmp/.ipfs/config"); 76 | 77 | // now build a new one 78 | struct RepoConfig* repoConfig; 79 | ipfs_repo_config_new(&repoConfig); 80 | if (!ipfs_repo_config_init(repoConfig, 2048, "/tmp/.ipfs")) { 81 | ipfs_repo_config_free(repoConfig); 82 | return 0; 83 | } 84 | 85 | if (!fs_repo_write_config_file("/tmp/.ipfs", repoConfig)) { 86 | ipfs_repo_config_free(repoConfig); 87 | return 0; 88 | } 89 | 90 | ipfs_repo_config_free(repoConfig); 91 | 92 | // check to see if the file exists 93 | return os_utils_file_exists("/tmp/.ipfs/config"); 94 | } 95 | 96 | #endif /* test_repo_config_h */ 97 | -------------------------------------------------------------------------------- /test/repo/test_repo_fsrepo.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/repo/fsrepo/fs_repo.h" 2 | 3 | int test_repo_fsrepo_open_config() { 4 | struct FSRepo* fs_repo = NULL; 5 | struct RepoConfig* repo_config = NULL; 6 | 7 | const char* path = "/tmp/.ipfs"; 8 | 9 | // create the struct 10 | int retVal = ipfs_repo_fsrepo_new((char*)path, repo_config, &fs_repo); 11 | if (retVal == 0) 12 | return 0; 13 | 14 | // open the repository and read the file 15 | retVal = ipfs_repo_fsrepo_open(fs_repo); 16 | if (retVal == 0) { 17 | ipfs_repo_fsrepo_free(fs_repo); 18 | return 0; 19 | } 20 | 21 | retVal = ipfs_repo_fsrepo_free(fs_repo); 22 | if (retVal == 0) 23 | return 0; 24 | 25 | return 1; 26 | } 27 | -------------------------------------------------------------------------------- /test/repo/test_repo_identity.h: -------------------------------------------------------------------------------- 1 | // 2 | // test_repo_identity.h 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 10/31/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #ifndef test_repo_identity_h 10 | #define test_repo_identity_h 11 | 12 | #include 13 | 14 | #include "ipfs/repo/config/identity.h" 15 | #include "libp2p/crypto/encoding/base64.h" 16 | 17 | int test_repo_config_identity_new() { 18 | struct Identity* identity; 19 | int retVal = repo_config_identity_new(&identity); 20 | if (retVal == 0) 21 | return 0; 22 | 23 | retVal = repo_config_identity_init(identity, 2046); 24 | if (retVal == 0) 25 | return 0; 26 | 27 | // now examine it 28 | int privateKeySize = sizeof(identity->private_key); 29 | if (privateKeySize < 0) { 30 | printf("Private key structure size should be greater than 0\n"); 31 | return 0; 32 | } 33 | 34 | retVal = repo_config_identity_free(identity); 35 | 36 | return retVal; 37 | } 38 | 39 | // test this key 40 | int test_repo_config_identity_private_key() { 41 | const char* priv_b64 = "CAASpwkwggSjAgEAAoIBAQDTDJBWjDzS/HxDNOHazvzH2bu9CPMVHUrrvKRdBUM5ansL6/CC3MVZ6HVm4O6QHRapN6EF2CbrTgI4KBOXIL125Xo8MlROnyfXYk3O5q2tgwL/MbW8kXjtkyCfBak7MUoLOdLU7Svg0gkl3l+uDAiDcCLnwJVcFfq9ch6z4wMOhYJqE5dtx0uXxn6IuKWl1B69FTvBXCc0thw8Rw54b941FDcsBH5ttV9mRNCJym3poZ5qalNgXlxoIIB+PUx5QD+aq7KMJdpAX8HkapBntCOahP/QUceRmma0grlZLeYkH6/oi/hIrM6se3KUZ+F6tBuDFys8UAZy/X2BCUbKjbxtAgMBAAECggEANWfQfpYuLhXGPBt9q6kFPm1SnJtPJ+CpvM2XqhJS2IyhZnrl+bd0GTRBwS7aL42s1lVFYf04nAK5fQxnKK8YQqX/MIxr2RldM5ukpN6qxGWKtJkXrAgD2dqJPrRoBpqKahzPxSHfIJ0Fw5dqDtjsrpYJvyt0oEDPmnDuZAbmFx4sJqnesPNhKxtRMBx1+yxGVuRVJjHcqAgqPqwNiuoMEaYMY+G9yzT6vza8ovCpbX7BBIgM5fAT9PD8TBG//Vu9THvj/ZomiVG2qv6RL0qQyVb+DUzPZz1amBsSvahtXCl72jA3JwAZ943RxSR66P934S0ashkVwLUi46z/EAbJ4QKBgQDojGIO07BEVL2+7VxlGL9XGZQp4Y3qlhh2zDDQGwkCq/KQ+BdNYWitPwqRl9GqFLgpmeQIhyHTOa/IThx+AXGKVQ24ROH+skUs4IbO6R3qY7BKtb5lkZE/Yln09x70BBngUYAzh/rtnsXO3cl1x2XDDqUbCwlGcDAs8Jh/6UnvQwKBgQDoVSQs7Uq9MJCGIUM2bixX89tHzSxq5mn9wMD3/XRVfT5Ua8YkYBuzcmlcT39N7L5BwuyFqX3Vi7lv/Ya/qaQP6XkrZ8W1OAaTlYewfE5ZgknJqSpXcNWhABKeNmqndvqyQ/8HNCv/j8AdraGB2DGO57Xso5J0CQ43W/U9+QIyjwKBgHLL2hw3o+wXaRO3WMUPUmVM2zdRgR0suybp5a7Vqb0H5NZrohUw4NulIzJ8H6Q2VjMzJL6Q9sGu2HepF6ecTtBa7ErqtiVlG4Dr1aCOs5XhYEWBMlwxX+JKSt4Cn+UVoTB7Cy5lEhn7JurX0Xuy0ylXMWoIKKv89cs5eg6quzTBAoGAaq9eEztLjKCWXOE9SetBdYnG8aunb9cqaJlwgu/h0bfXPVDYBbAUSEyLURY4MQI7Q1tM3Pu9iqfEmUZj7/LoIV5mg6X9RX/alT6etk3+dF+9nlqN1OU9U9cCtZ/rTcb2y5EptJcidRH/eCFY/pTV/PcttOJPx/S4kHcroC+N8MUCgYEA6DA5QHxHfNN6Nxv+pEzy2DIxFe9RrBxS+KPBsra1C8jgdeMf4EmfU0Nox92V0q0bRrD5ztqQwSONI0hSRb1iiMWR6MuFnAFajUJfASjjIlZ6nIQjQslI7vjlvYyyHS/p/Codxap+yJlTLWwVEOXp2D9pWwiMq1xEyf0TH1BosvM="; 42 | size_t decoded_len = libp2p_crypto_encoding_base64_decode_size(strlen(priv_b64)); 43 | char* out_buff = malloc(sizeof(char) * decoded_len); 44 | libp2p_crypto_encoding_base64_decode(priv_b64, strlen(priv_b64), out_buff, decoded_len, &decoded_len); 45 | char str[decoded_len]; 46 | int j = 0; 47 | free(out_buff); 48 | // now test 49 | return 1; 50 | 51 | } 52 | 53 | #endif /* test_repo_identity_h */ 54 | -------------------------------------------------------------------------------- /test/storage/test_blocks.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/blocks/block.h" 2 | 3 | int test_blocks_new() { 4 | const char* input = "Hello, World!"; 5 | int retVal = 0; 6 | struct Block* block; 7 | retVal = ipfs_blocks_block_new(input, strlen(input) + 1, &block); 8 | if (retVal == 0) 9 | return 0; 10 | 11 | // now examine the block 12 | if (strcmp(block->data, input) != 0) 13 | return 0; 14 | 15 | if (block->data_length != strlen(input) + 1) 16 | return 0; 17 | 18 | if (block->cid->codec != CID_PROTOBUF) 19 | return 0; 20 | 21 | if (block->cid->version != 0) 22 | return 0; 23 | 24 | if (block->cid->hash_length != 32) 25 | return 0; 26 | 27 | unsigned char result_hash[32] = {33, 153, 66, 187, 124, 250, 87, 12, 12, 73, 43, 247, 175, 153, 10, 51, 192, 195, 218, 69, 220, 170, 105, 179, 195, 0, 203, 213, 172, 3, 244, 10 }; 28 | for(int i = 0; i < 32; i++) { 29 | if (block->cid->hash[i] != result_hash[i]) 30 | return 0; 31 | } 32 | 33 | retVal = ipfs_blocks_block_free(block); 34 | 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /test/storage/test_blockstore.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ipfs/blocks/blockstore.h" 4 | #include "ipfs/blocks/block.h" 5 | 6 | int test_blockstore_put() { 7 | const unsigned char* input_string = "Hello, World!"; 8 | struct Block* input_block; 9 | int retVal = 0; 10 | 11 | retVal = ipfs_blocks_block_new(input_string, strlen((const char*)input_string) + 1, &input_block); 12 | if (retVal == 0) 13 | return 0; 14 | 15 | retVal = ipfs_blockstore_put(input_block); 16 | if (retVal == 0) 17 | return 0; 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /test/storage/test_datastore.h: -------------------------------------------------------------------------------- 1 | #include "libp2p/crypto/encoding/base32.h" 2 | #include "ipfs/datastore/ds_helper.h" 3 | #include "ipfs/blocks/block.h" 4 | #include "ipfs/repo/config/config.h" 5 | #include "ipfs/repo/fsrepo/fs_repo.h" 6 | 7 | #include 8 | #include 9 | 10 | int remove_directory(const char *path) 11 | { 12 | DIR *d = opendir(path); 13 | size_t path_len = strlen(path); 14 | int r = -1; 15 | 16 | if (d) 17 | { 18 | struct dirent *p; 19 | 20 | r = 0; 21 | 22 | while (!r && (p=readdir(d))) 23 | { 24 | int r2 = -1; 25 | char *buf; 26 | size_t len; 27 | 28 | /* Skip the names "." and ".." as we don't want to recurse on them. */ 29 | if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) 30 | { 31 | continue; 32 | } 33 | 34 | len = path_len + strlen(p->d_name) + 2; 35 | buf = malloc(len); 36 | 37 | if (buf) 38 | { 39 | struct stat statbuf; 40 | 41 | snprintf(buf, len, "%s/%s", path, p->d_name); 42 | 43 | if (!stat(buf, &statbuf)) 44 | { 45 | if (S_ISDIR(statbuf.st_mode)) 46 | { 47 | r2 = remove_directory(buf); 48 | } 49 | else 50 | { 51 | r2 = unlink(buf); 52 | } 53 | } 54 | 55 | free(buf); 56 | } 57 | 58 | r = r2; 59 | } 60 | 61 | closedir(d); 62 | } 63 | 64 | if (!r) 65 | { 66 | r = rmdir(path); 67 | } 68 | 69 | return r; 70 | } 71 | 72 | int make_ipfs_repository(struct FSRepo* fs_repo) { 73 | int retVal; 74 | struct RepoConfig* repo_config; 75 | 76 | unlink("/tmp/.ipfs/config"); 77 | remove_directory("/tmp/.ipfs/datastore"); 78 | remove_directory("/tmp/.ipfs/blockstore"); 79 | 80 | // build a default repo config 81 | retVal = ipfs_repo_config_new(&repo_config); 82 | if (retVal == 0) 83 | return 0; 84 | retVal = ipfs_repo_config_init(repo_config, 2048, "/tmp/.ipfs"); 85 | if (retVal == 0) 86 | return 0; 87 | // now the fs_repo 88 | retVal = ipfs_repo_fsrepo_new("/tmp/.ipfs", repo_config, &fs_repo); 89 | if (retVal == 0) 90 | return 0; 91 | // this builds a new repo 92 | retVal = ipfs_repo_fsrepo_init(fs_repo); 93 | if (retVal == 0) 94 | return 0; 95 | 96 | // clean up 97 | ipfs_repo_fsrepo_free(fs_repo); 98 | // this is cleaned up by fsrepo_free 99 | //ipfs_repo_config_free(repo_config); 100 | 101 | // make sure the repository exists 102 | retVal = os_utils_file_exists("/tmp/.ipfs/config"); 103 | return retVal; 104 | } 105 | 106 | int test_ipfs_datastore_put() { 107 | struct Block* block; 108 | int retVal; 109 | const unsigned char* input = "Hello, world!"; 110 | 111 | // build the ipfs repository, then shut it down, so we can start fresh 112 | struct FSRepo* fs_repo; 113 | retVal = make_ipfs_repository(fs_repo); 114 | if (retVal == 0) 115 | return 0; 116 | 117 | // build the block 118 | retVal = ipfs_blocks_block_new(input, strlen((char*)input), &block); 119 | if (retVal == 0) 120 | return 0; 121 | 122 | // generate the key 123 | size_t key_length = libp2p_crypto_encoding_base32_encode_size(block->data_length); 124 | unsigned char key[key_length]; 125 | retVal = ipfs_datastore_helper_ds_key_from_binary(block->data, block->data_length, &key[0], key_length, &key_length); 126 | if (retVal == 0) 127 | return 0; 128 | 129 | // open the repository 130 | retVal = ipfs_repo_fsrepo_new("/tmp/.ipfs", NULL, &fs_repo); 131 | if (retVal == 0) 132 | return 0; 133 | retVal = ipfs_repo_fsrepo_open(fs_repo); 134 | if (retVal == 0) 135 | return 0; 136 | 137 | /* 138 | 139 | // send to Put with key 140 | retVal = fs_repo->config->datastore->datastore_put(key, key_length, block, fs_repo->config->datastore); 141 | */ 142 | if (retVal == 0) 143 | return 0; 144 | 145 | // save the block 146 | 147 | // check the results 148 | 149 | // clean up 150 | ipfs_repo_fsrepo_free(fs_repo); 151 | ipfs_blocks_block_free(block); 152 | 153 | return 1; 154 | } 155 | -------------------------------------------------------------------------------- /test/storage/test_ds_helper.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/datastore/ds_helper.h" 2 | 3 | int test_ds_key_from_binary() { 4 | size_t original_incoming_length = 10; 5 | size_t incoming_length = original_incoming_length; 6 | 7 | unsigned char incoming[incoming_length + 5]; // give a little wiggle room 8 | unsigned char* ptrIncoming = &incoming[0]; 9 | 10 | for(int i = 0; i < incoming_length; i++) { 11 | incoming[i] = i; 12 | } 13 | 14 | size_t outgoing_length = 100; 15 | char outgoing[outgoing_length]; 16 | char* ptrOutgoing = &outgoing[0]; 17 | 18 | memset(outgoing, 0, outgoing_length); 19 | 20 | int retVal = ipfs_datastore_helper_ds_key_from_binary(ptrIncoming, incoming_length, ptrOutgoing, outgoing_length, &outgoing_length); 21 | if (retVal == 0) 22 | return 0; 23 | 24 | // now undo it and see if we get the same thing back... 25 | retVal = ipfs_datastore_helper_binary_from_ds_key(ptrOutgoing, outgoing_length, incoming, incoming_length + 5, &incoming_length); 26 | if (retVal == 0) 27 | return 0; 28 | 29 | if (original_incoming_length != incoming_length) 30 | return 0; 31 | 32 | for(int i = 0; i < original_incoming_length; i++) { 33 | if (incoming[i] != i) 34 | return 0; 35 | } 36 | return 1; 37 | } 38 | -------------------------------------------------------------------------------- /test/testit.c: -------------------------------------------------------------------------------- 1 | #include "storage/test_ds_helper.h" #include "storage/test_ds_helper.h" 2 | #include "storage/test_datastore.h" #include "storage/test_datastore.h" 3 | #include "storage/test_blocks.h" #include "storage/test_blocks.h" 4 | +#include "ipfs/node/node.h" 5 | 6 | -int testit(const char* name, int (*func)(void)) { +int main(int argc, char** argv) 7 | - printf("Testing %s...\n", name); +{ 8 | - int retVal = func(); + printf("XETH TESTS\n"); 9 | - if (retVal) + //Variables of link: 10 | - printf("%s success!\n", name); + char * name = "Alex"; 11 | - else + char * ahash = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"; 12 | - printf("** Uh oh! %s failed.**\n", name); + struct Link * mylink; 13 | - return retVal == 0; + mylink = Create_Link(name,ahash); 14 | -} + printf("===================================\n" \ 15 | - + "Node Link:\n" \ 16 | -const char* names[] = { + " -Name: %s\n" \ 17 | - "test_cid_new_free", + " -Size: %lu\n" \ 18 | - "test_cid_cast_multihash", + "\n Cid Details:\n\n" \ 19 | - "test_cid_cast_non_multihash", + " -Version: %d\n" \ 20 | - //"test_init_new_installation", + " -Codec: %c\n" \ 21 | - "test_repo_config_new", + " -Hash: %s\n" \ 22 | - "test_repo_config_init", + " -Hash Length: %lu\n" \ 23 | - "test_repo_config_write", + "====================================\n" \ 24 | - "test_repo_config_identity_new", + , mylink->name, mylink->size, mylink->Lcid->version,mylink->Lcid->codec,mylink->Lcid->hash,mylink->Lcid->hash_length); 25 | - "test_repo_config_identity_private_key", + //Link Two for testing purposes 26 | - "test_get_init_command", + char * name2 = "Simo"; 27 | - "test_repo_fsrepo_open_config", + char * ahash2 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo"; 28 | - "test_flatfs_get_directory", + struct Link * mylink2; 29 | - "test_flatfs_get_filename", + mylink2 = Create_Link(name2,ahash2); 30 | - "test_flatfs_get_full_filename", + //Nodes 31 | - "test_ds_key_from_binary", + struct Node * Mynode; 32 | - "test_blocks_new", + Mynode = N_Create_From_Link(mylink,sizeof(mylink)); 33 | - "test_repo_bootstrap_peers_init", + mylink->name = "HAHA";//Testing for valid node creation 34 | - "test_ipfs_datastore_put" + printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->Lcid->hash); 35 | -}; + Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2)); 36 | - + mylink2->name = "HAHA";//Testing for valid node creation 37 | -int (*funcs[])(void) = { + printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->Lcid->hash); 38 | - test_cid_new_free, + struct Link * ResultLink = Node_Get_Link("Simo", Mynode); 39 | - test_cid_cast_multihash, + printf("\nResultLink: \nName: %s\nHash: %s\n", ResultLink->name, ResultLink->Lcid->hash); 40 | - test_cid_cast_non_multihash, + Node_Remove_Link("Simo", Mynode); 41 | - //test_init_new_installation, + printf("Outlinkamt: %d\n", Mynode->link_ammount); 42 | - test_repo_config_new, + Free_Link(mylink); 43 | - test_repo_config_init, + Free_Link(mylink2); 44 | - test_repo_config_write, + Free_Link(ResultLink); 45 | - test_repo_config_identity_new, + Node_Delete(Mynode); 46 | - test_repo_config_identity_private_key, + return 0; 47 | - test_get_init_command, 48 | - test_repo_fsrepo_open_config, 49 | - test_flatfs_get_directory, 50 | - test_flatfs_get_filename, 51 | - test_flatfs_get_full_filename, 52 | - test_ds_key_from_binary, 53 | - test_blocks_new, 54 | - test_repo_bootstrap_peers_init, 55 | - test_ipfs_datastore_put 56 | -}; 57 | - 58 | -/** 59 | - * run 1 test or run all 60 | - */ 61 | -int main(int argc, char** argv) { 62 | - int counter = 0; 63 | - char* test_wanted; 64 | - int only_one = 0; 65 | - if(argc > 1) { 66 | - only_one = 1; 67 | - test_wanted = argv[1]; 68 | - } 69 | - for (int i = 0; i < sizeof(funcs) / sizeof(funcs[0]); i++) { 70 | - if (only_one && strcmp(names[i], test_wanted) == 0) 71 | - counter += testit(names[i], funcs[i]); 72 | - else 73 | - if (!only_one) 74 | - counter += testit(names[i], funcs[i]); 75 | - 76 | - } 77 | - 78 | - if (counter > 0) { 79 | - printf("***** There were %d failed test(s) *****\n", counter); 80 | - } else { 81 | - printf("All tests passed\n"); 82 | - } 83 | - return 1; 84 | } 85 | -------------------------------------------------------------------------------- /thirdparty/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | cd ipfsaddr; make all; 3 | 4 | clean: 5 | cd ipfsaddr; make clean; 6 | -------------------------------------------------------------------------------- /thirdparty/ipfsaddr/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../../c-libp2p/include 3 | LFLAGS = 4 | DEPS = 5 | OBJS = ipfs_addr.o 6 | 7 | %.o: %.c $(DEPS) 8 | $(CC) -c -o $@ $< $(CFLAGS) 9 | 10 | all: $(OBJS) 11 | 12 | clean: 13 | rm -f *.o 14 | -------------------------------------------------------------------------------- /thirdparty/ipfsaddr/ipfs_addr.c: -------------------------------------------------------------------------------- 1 | // 2 | // ipfs_addr.c 3 | // c-ipfs 4 | // 5 | // Created by John Jones on 11/2/16. 6 | // Copyright © 2016 JMJAtlanta. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "ipfs/thirdparty/ipfsaddr/ipfs_addr.h" 14 | 15 | int ipfsaddr_new(struct IPFSAddr** addr, char* string) { 16 | (*addr) = malloc(sizeof(struct IPFSAddr)); 17 | (*addr)->entire_string = malloc(sizeof(char) * (strlen(string) + 1)); 18 | if ((*addr)->entire_string == NULL) 19 | return 0; 20 | strncpy((*addr)->entire_string, string, strlen(string)); 21 | return 1; 22 | } 23 | 24 | int ipfsaddr_free(struct IPFSAddr* addr) { 25 | if (addr != NULL) { 26 | if (addr->entire_string != NULL) 27 | free(addr->entire_string); 28 | free(addr); 29 | } 30 | return 1; 31 | } 32 | --------------------------------------------------------------------------------