├── .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 |
--------------------------------------------------------------------------------