├── test ├── test_file.txt ├── blocks │ └── test_block.h ├── scripts │ ├── Makefile │ ├── run_test.sh │ ├── test_2.sh │ ├── generate_file.c │ ├── test_go.sh │ ├── test_3.sh │ ├── run_tests.sh │ ├── test_6.sh │ ├── test_4.sh │ ├── test_9.sh │ ├── test_1.sh │ ├── test_7.sh │ ├── test_8.sh │ ├── test_5.sh │ └── test_helpers.sh ├── storage │ ├── test_blockstore.h │ ├── test_ds_helper.h │ ├── test_blocks.h │ └── test_unixfs.h ├── core │ ├── test_daemon.h │ ├── test_node.h │ ├── test_compat_go.h │ ├── test_null.h │ └── test_ping.h ├── Makefile ├── repo │ ├── test_repo_bootstrap_peers.h │ ├── test_repo_fsrepo.h │ └── test_repo_identity.h ├── test_helper.h ├── exchange │ └── test_bitswap_request_queue.h ├── flatfs │ └── test_flatfs.h ├── namesys │ └── test_namesys.h ├── cmd │ └── ipfs │ │ └── test_init.h ├── config.test1.wo_journal ├── config.test2.wo_journal ├── config.test1 └── config.test2 ├── thirdparty ├── Makefile └── ipfsaddr │ ├── Makefile │ └── ipfs_addr.c ├── include └── ipfs │ ├── core │ ├── swarm.h │ ├── client_api.h │ ├── bootstrap.h │ ├── builder.h │ ├── null.h │ ├── daemon.h │ ├── net.h │ ├── ipfs_node.h │ ├── api.h │ └── http_request.h │ ├── repo │ ├── config │ │ ├── peer.h │ │ ├── bootstrap_peers.h │ │ ├── gateway.h │ │ ├── addresses.h │ │ ├── swarm.h │ │ ├── identity.h │ │ ├── replication.h │ │ └── config.h │ ├── fsrepo │ │ ├── lmdb_cursor.h │ │ ├── lmdb_datastore.h │ │ ├── jsmn.h │ │ └── journalstore.h │ └── init.h │ ├── cmd │ ├── cli.h │ └── ipfs │ │ └── init.h │ ├── util │ ├── time.h │ └── errs.h │ ├── commands │ ├── request.h │ ├── context.h │ ├── req_log.h │ ├── cli │ │ └── parse.h │ ├── command_option.h │ ├── command.h │ └── argument.h │ ├── datastore │ ├── key.h │ └── ds_helper.h │ ├── namesys │ ├── resolver.h │ ├── name.h │ ├── publisher.h │ ├── pb.h │ ├── routing.h │ └── namesys.h │ ├── thirdparty │ └── ipfsaddr │ │ └── ipfs_addr.h │ ├── path │ └── path.h │ ├── importer │ ├── resolver.h │ ├── importer.h │ └── exporter.h │ ├── unixfs │ ├── format.h │ └── unixfs.h │ ├── dnslink │ └── dnslink.h │ ├── exchange │ ├── bitswap │ │ ├── engine.h │ │ ├── want_manager.h │ │ ├── bitswap.h │ │ └── network.h │ └── exchange.h │ ├── pin │ └── pin.h │ ├── journal │ ├── journal_entry.h │ ├── journal_message.h │ └── journal.h │ ├── merkledag │ └── merkledag.h │ ├── flatfs │ └── flatfs.h │ ├── multibase │ └── multibase.h │ └── blocks │ └── block.h ├── ipfs.desktop ├── .gitmodules ├── routing ├── supernode.c └── Makefile ├── core ├── builder.c ├── Makefile ├── net.c ├── client_api.c ├── swarm.c ├── bootstrap.c └── daemon.c ├── commands ├── cli │ ├── Makefile │ └── parse.c ├── Makefile ├── command_option.c ├── argument.c └── command.c ├── journal ├── journal_message.proto └── Makefile ├── .gitignore ├── exchange ├── Makefile └── bitswap │ ├── Makefile │ └── want_manager.c ├── flatfs └── Makefile ├── multibase └── Makefile ├── repo ├── Makefile ├── fsrepo │ ├── Makefile │ └── lmdb_cursor.c └── config │ ├── Makefile │ ├── addresses.c │ ├── peer.c │ ├── swarm.c │ ├── bootstrap_peers.c │ └── gateway.c ├── pin └── Makefile ├── path └── Makefile ├── cid └── Makefile ├── dnslink └── Makefile ├── unixfs ├── Makefile └── format.c.old ├── merkledag └── Makefile ├── util ├── Makefile ├── time.c └── errs.c ├── importer └── Makefile ├── blocks └── Makefile ├── cmd ├── Makefile ├── ipfs │ ├── Makefile │ └── main.c └── cli.c ├── datastore ├── Makefile └── key.c ├── namesys ├── Makefile ├── proquint_test.c ├── pb.c ├── is_domain_test.c └── base.c ├── .project ├── README.md ├── LICENSE ├── Makefile ├── main └── Makefile └── .travis.yml /test/test_file.txt: -------------------------------------------------------------------------------- 1 | Hello, World! 2 | -------------------------------------------------------------------------------- /test/blocks/test_block.h: -------------------------------------------------------------------------------- 1 | #include "../test_helper.h" 2 | 3 | -------------------------------------------------------------------------------- /thirdparty/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | cd ipfsaddr; make all; 3 | 4 | clean: 5 | cd ipfsaddr; make clean; 6 | -------------------------------------------------------------------------------- /include/ipfs/core/swarm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/cmd/cli.h" 4 | 5 | /*** 6 | * Handle command line swarm call 7 | */ 8 | int ipfs_swarm (struct CliArguments* args); 9 | -------------------------------------------------------------------------------- /ipfs.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=c-ipfs 4 | Comment=IPFS implementation in C (not just an API client library) 5 | Exec=ipfs 6 | Icon=ipfs 7 | Terminal=true 8 | Categories=Network;P2P; 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "c-libp2p"] 2 | path = c-libp2p 3 | url = https://github.com/Agorise/c-libp2p.git 4 | [submodule "lmdb"] 5 | path = lmdb 6 | url = https://github.com/jmjatlanta/lmdb.git 7 | branch = mdb.master 8 | -------------------------------------------------------------------------------- /test/scripts/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | %.o: %.c 4 | $(CC) -c -o $@ $< 5 | 6 | generate_file: generate_file.o 7 | $(CC) -o $@ $^ 8 | 9 | all: generate_file 10 | 11 | clean: 12 | rm -f *.o 13 | rm -f generate_file 14 | -------------------------------------------------------------------------------- /routing/supernode.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "libp2p/utils/linked_list.h" 4 | 5 | int ipfs_routing_supernode_parse_provider(unsigned char* in, size_t in_size, struct Libp2pLinkedList** multiadress_head) { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /core/builder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ipfs/core/builder.h" 3 | 4 | int ipfs_core_builder_new_node(struct Context* context, struct BuildCfg* build_cfg, struct IpfsNode* buildConfig) { 5 | // TODO: Implement this method 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /test/scripts/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TEST_FILE=test_$1.sh 4 | 5 | test_success=0 6 | 7 | source ./$TEST_FILE 8 | 9 | function do_it() { 10 | pre 11 | body 12 | post 13 | return $? 14 | } 15 | 16 | do_it 17 | exit $test_success 18 | -------------------------------------------------------------------------------- /include/ipfs/core/client_api.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/core/ipfs_node.h" 2 | 3 | /** 4 | * Determine if the API is running 5 | * @param local_node the context 6 | * @returns true(1) on success, false(0) otherwise 7 | */ 8 | int api_running(struct IpfsNode* local_node); 9 | -------------------------------------------------------------------------------- /commands/cli/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../c-libp2p/include -Wall 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /journal/journal_message.proto: -------------------------------------------------------------------------------- 1 | message JournalEntry { 2 | int32 timestamp = 1; 3 | string hash = 2; 4 | bool pin = 3; 5 | } 6 | 7 | message JournalMessage { 8 | int32 current_epoch = 1; 9 | int32 start_epoch = 2; 10 | int32 end_epoch = 3; 11 | repeated JournalEntry journal_entries = 4; 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !.gitignore 4 | !Makefile 5 | !**/ 6 | 7 | *.o 8 | .settings/language.settings.xml 9 | test/test_ipfs 10 | main/ipfs 11 | test/test1.txt 12 | test/test2.txt 13 | test/scripts/hello.bin 14 | test/scripts/hello2.bin 15 | test/scripts/testlog.txt 16 | test/scripts/generate_file 17 | -------------------------------------------------------------------------------- /exchange/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -std=c11 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 bitswap; make all; 16 | clean: 17 | rm -f *.o 18 | cd bitswap; make clean; 19 | -------------------------------------------------------------------------------- /flatfs/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | CFLAGS = -O0 -I../include -I../c-libp2p/include -Wall -std=c11 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 | -------------------------------------------------------------------------------- /include/ipfs/core/bootstrap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Fires up the connection to peers 5 | */ 6 | 7 | /** 8 | * Connect to the peers in the config file 9 | * @param param a IpfsNode object 10 | * @returns nothing useful 11 | */ 12 | void *ipfs_bootstrap_swarm(void* param); 13 | 14 | void *ipfs_bootstrap_routing(void* param); 15 | -------------------------------------------------------------------------------- /multibase/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -Wall -std=c11 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 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/peer.h: -------------------------------------------------------------------------------- 1 | #ifndef peer_h 2 | #define peer_h 3 | 4 | 5 | /*** 6 | * given a public key, find the peer id 7 | * @param public_key the public key in bytes 8 | * @param id the resultant peer id 9 | * @returns true(1) on success 10 | */ 11 | int repo_config_peer_id_from_public_key(char* public_key, char* id); 12 | 13 | #endif /* peer_h */ 14 | -------------------------------------------------------------------------------- /repo/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | DEPS = 9 | OBJS = init.c 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; 21 | -------------------------------------------------------------------------------- /pin/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = pin.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /path/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = path.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /cid/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = cid.o set.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /dnslink/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = dnslink.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /unixfs/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = unixfs.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /routing/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = offline.o online.o k_routing.o supernode.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f $(OBJS) 19 | -------------------------------------------------------------------------------- /merkledag/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = merkledag.o node.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /include/ipfs/cmd/cli.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Helps parse the command line. 5 | */ 6 | 7 | /** 8 | * A structure to hold the command line arguments 9 | */ 10 | struct CliArguments { 11 | int argc; 12 | char** argv; 13 | int verb_index; 14 | char* config_dir; 15 | }; 16 | 17 | struct CliArguments* cli_arguments_new(int argc, char** argv); 18 | 19 | void cli_arguments_free(struct CliArguments* args); 20 | -------------------------------------------------------------------------------- /util/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = errs.o time.o thread_pool.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /importer/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = importer.o exporter.o resolver.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /include/ipfs/util/time.h: -------------------------------------------------------------------------------- 1 | #ifndef IPFS_TIME_H 2 | #define IPFS_TIME_H 3 | #ifndef __USE_XOPEN 4 | #define __USE_XOPEN 5 | #endif // __USE_XOPEN 6 | 7 | #ifndef __USE_ISOC11 8 | #define __USE_ISOC11 9 | #endif // __USE_ISOC11 10 | 11 | #include 12 | 13 | int ipfs_util_time_parse_RFC3339 (struct timespec *ts, char *s); 14 | char *ipfs_util_time_format_RFC3339 (struct timespec *ts); 15 | #endif // IPFS_TIME_H 16 | -------------------------------------------------------------------------------- /journal/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-protobuf -I../lmdb/libraries/liblmdb -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = journal.o journal_entry.o journal_message.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /blocks/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 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 | -------------------------------------------------------------------------------- /cmd/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = cli.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | ipfs: $(OBJS) 16 | $(CC) -o $@ $^ $(LFLAGS) 17 | 18 | all: $(OBJS) 19 | cd ipfs; make all; 20 | 21 | clean: 22 | rm -f *.o 23 | cd ipfs; make clean; 24 | -------------------------------------------------------------------------------- /datastore/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../lmdb/libraries/liblmdb -I../c-libp2p/c-protobuf -Wall -std=c11 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 | -------------------------------------------------------------------------------- /namesys/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = base.o dns.o isdomain.o namesys.o proquint.o publisher.o pb.o name.o resolver.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/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../c-libp2p/include -I../../lmdb/libraries/liblmdb -I../../c-libp2p/c-protobuf -I../../c-libp2p/c-multiaddr/include -Wall -std=c99 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = fs_repo.o jsmn.o lmdb_datastore.o lmdb_journalstore.o lmdb_cursor.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /cmd/ipfs/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../c-libp2p/include -I../../c-libp2p/c-multiaddr/include -I../../c-libp2p/c-protobuf -Wall 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 23 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -Wall -std=c11 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = builder.h ipfs_node.h 10 | OBJS = builder.o daemon.o null.o ping.o bootstrap.o ipfs_node.o api.o client_api.o http_request.o swarm.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /include/ipfs/commands/request.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_REQUEST_H__ 2 | #define __COMMANDS_REQUEST_H__ 3 | 4 | #include "context.h" 5 | #include "command.h" 6 | 7 | struct Request { 8 | char* path; 9 | //optmap options; 10 | char* arguments; 11 | //file[] files; 12 | struct Command cmd; 13 | struct Context* invoc_context; 14 | //context rctx; 15 | //map[string]Option optionDefs; 16 | //map[string]interface{} values; 17 | //ioReader stdin; 18 | }; 19 | 20 | #endif /* request_h */ 21 | -------------------------------------------------------------------------------- /include/ipfs/commands/context.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_CONTEXT_H__ 2 | #define __COMMANDS_CONTEXT_H__ 3 | 4 | #include "ipfs/commands/req_log.h" 5 | #include "ipfs/repo/config/config.h" 6 | #include "ipfs/core/ipfs_node.h" 7 | 8 | struct Context { 9 | int online; 10 | char* config_root; 11 | struct ReqLog req_log; 12 | struct RepoConfig config; 13 | int (*load_config)(char* path); 14 | struct IpfsNode node; 15 | int (*construct_node)(struct IpfsNode* node); 16 | }; 17 | 18 | #endif /* context_h */ 19 | -------------------------------------------------------------------------------- /exchange/bitswap/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../c-libp2p/include -I../../c-libp2p/c-multiaddr/include -I../../c-libp2p/c-multihash/include -I../../c-libp2p/c-protobuf -Wall -std=c99 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = 10 | OBJS = bitswap.o message.o network.o peer_request_queue.o want_manager.o wantlist_queue.o engine.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /include/ipfs/commands/req_log.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_REQ_LOG_H__ 2 | #define __COMMANDS_REQ_LOG_H__ 3 | 4 | struct ReqLogEntry { 5 | long start_time; 6 | long end_time; 7 | int active; 8 | char* command; 9 | struct Option** options; 10 | struct Argument** args; 11 | int id; 12 | struct Request* req; 13 | struct ReqLog* log; 14 | }; 15 | 16 | struct ReqLog { 17 | struct ReqLogEntry** requests; 18 | int next_id; 19 | //mutex lock; 20 | long keep_duration; 21 | }; 22 | 23 | #endif /* req_log_h */ 24 | -------------------------------------------------------------------------------- /repo/config/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../../include -I../../c-libp2p/include -I../../c-libp2p/c-multiaddr/include -I../../c-libp2p/c-multihash/include -I../../c-libp2p/c-protobuf -Wall -std=c99 3 | 4 | ifdef DEBUG 5 | CFLAGS += -g3 6 | endif 7 | 8 | LFLAGS = 9 | DEPS = config.h datastore.h identity.h replication.h 10 | OBJS = config.o identity.o bootstrap_peers.o gateway.o addresses.o swarm.o peer.o replication.o 11 | 12 | %.o: %.c $(DEPS) 13 | $(CC) -c -o $@ $< $(CFLAGS) 14 | 15 | all: $(OBJS) 16 | 17 | clean: 18 | rm -f *.o 19 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /commands/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -Wall -std=c11 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/command_option.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ipfs/commands/command_option.h" 5 | 6 | int commands_command_option_init(struct CommandOption* option, char* description) { 7 | option->description = description; 8 | // allocate memory for names 9 | option->names = malloc(option->name_count * sizeof(char*)); 10 | if (option->names == NULL) 11 | return 0; 12 | return 1; 13 | } 14 | 15 | int commands_command_option_free(struct CommandOption* option) { 16 | free(option->names); 17 | free(option); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/scripts/test_2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./test_helpers.sh 4 | 5 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 6 | 7 | function pre { 8 | post 9 | eval "$IPFS" init; 10 | check_failure_with_exit "pre" $? 11 | } 12 | 13 | function post { 14 | rm -Rf /tmp/ipfs_1; 15 | rm hello.txt; 16 | } 17 | 18 | function body { 19 | create_hello_world; 20 | eval "$IPFS" add hello.txt 21 | check_failure_with_exit "add hello.txt" $? 22 | 23 | eval "$IPFS" cat QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH 24 | check_failure_with_exit "cat hello.txt" $? 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /include/ipfs/core/builder.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_BUILDER_H__ 2 | #define __CORE_BUILDER_H__ 3 | 4 | #include 5 | 6 | #include "ipfs/commands/context.h" 7 | #include "ipfs/repo/config/config.h" 8 | #include "ipfs/core/ipfs_node.h" 9 | 10 | struct BuildCfg { 11 | int online; 12 | // ExtraOpts map[string]bool 13 | int permanent; 14 | int nil_repo; 15 | //struct RoutingOption routing; 16 | //struct HostOption host; 17 | //struct Repo repo; 18 | }; 19 | 20 | int ipfs_core_builder_new_node(struct Context* context, struct BuildCfg* build_cfg, struct IpfsNode* buildConfig); 21 | 22 | #endif /* builder_h */ 23 | -------------------------------------------------------------------------------- /test/scripts/generate_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | if (argc != 3) { 6 | fprintf(stderr, "Syntax: %s \n", argv[0]); 7 | exit(1); 8 | } 9 | 10 | char* filename = argv[1]; 11 | long file_size = atoi(argv[2]); 12 | 13 | FILE* fd = fopen(filename, "w"); 14 | if (!fd) { 15 | fprintf(stderr, "Unable to open the file %s for writing.\n", filename); 16 | exit(1); 17 | } 18 | 19 | for(size_t i = 0; i < file_size; i++) { 20 | char byte = i % 255; 21 | fwrite(&byte, 1, 1, fd); 22 | } 23 | 24 | fclose(fd); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/ipfs/namesys/resolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/core/ipfs_node.h" 4 | 5 | /** 6 | * Resolve an IPNS name. 7 | * NOTE: if recursive is set to false, the result could be another ipns path 8 | * @param local_node the context 9 | * @param path the ipns path (i.e. "/ipns/Qm12345..") 10 | * @param recursive true to resolve until the result is not ipns, false to simply get the next step in the path 11 | * @param result the results (i.e. "/ipfs/QmAb12CD...") 12 | * @returns true(1) on success, false(0) otherwise 13 | */ 14 | int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path, int recursive, char** results); 15 | -------------------------------------------------------------------------------- /include/ipfs/namesys/name.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/cmd/cli.h" 4 | 5 | /*** 6 | * Publish IPNS name 7 | */ 8 | int ipfs_name_publish(struct IpfsNode* local_node, char* name, char **response, size_t *response_size); 9 | 10 | /*** 11 | * Resolve IPNS name 12 | */ 13 | int ipfs_name_resolve(struct IpfsNode* local_node, char* name, char **response, size_t *response_size); 14 | 15 | /** 16 | * We received a cli command "ipfs name". Do the right thing. 17 | * @param argc number of arguments on the command line 18 | * @param argv actual command line arguments 19 | * @returns true(1) on success, false(0) otherwise 20 | */ 21 | int ipfs_name(struct CliArguments* args); 22 | -------------------------------------------------------------------------------- /thirdparty/ipfsaddr/ipfs_addr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ipfs/thirdparty/ipfsaddr/ipfs_addr.h" 6 | 7 | int ipfsaddr_new(struct IPFSAddr** addr, char* string) { 8 | (*addr) = malloc(sizeof(struct IPFSAddr)); 9 | (*addr)->entire_string = malloc(sizeof(char) * (strlen(string) + 1)); 10 | if ((*addr)->entire_string == NULL) 11 | return 0; 12 | strncpy((*addr)->entire_string, string, strlen(string)); 13 | return 1; 14 | } 15 | 16 | int ipfsaddr_free(struct IPFSAddr* addr) { 17 | if (addr != NULL) { 18 | if (addr->entire_string != NULL) 19 | free(addr->entire_string); 20 | free(addr); 21 | } 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /include/ipfs/thirdparty/ipfsaddr/ipfs_addr.h: -------------------------------------------------------------------------------- 1 | #ifndef ipfs_addr_h 2 | #define ipfs_addr_h 3 | 4 | struct IPFSAddr { 5 | char* entire_string; 6 | }; 7 | 8 | /** 9 | * initialize a new IPFSAddr struct. NOTE: be sure to use ipfsaddr_free() 10 | * @param addr the struct to initialize 11 | * @param string the string that contains the address 12 | * @returns true(1) on success, false(0) otherwise 13 | */ 14 | int ipfsaddr_new(struct IPFSAddr** addr, char* string); 15 | 16 | /*** 17 | * frees allocated memory in the struct 18 | * @param addr the struct that is going away 19 | * @returns true(1) on success, false(0) otherwise 20 | */ 21 | int ipfsaddr_free(struct IPFSAddr* addr); 22 | 23 | #endif /* ipfs_addr_h */ 24 | -------------------------------------------------------------------------------- /include/ipfs/core/null.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libp2p/conn/session.h" 4 | #include "ipfs/core/ipfs_node.h" 5 | 6 | void *ipfs_null_connection (void *ptr); 7 | void *ipfs_null_listen (void *ptr); 8 | int ipfs_null_shutdown(); 9 | 10 | /*** 11 | * Handle the incoming request from a Multistream 12 | * @param incoming the incoming request 13 | * @param incoming_size the size of the request in bytes 14 | * @param session the session context 15 | * @param connection_param the connection parameters 16 | * @returns True(1) on success, False(0) on error 17 | */ 18 | int ipfs_multistream_marshal(const unsigned char* incoming, size_t incoming_size, struct SessionContext* session, struct IpfsNode* local_node); 19 | 20 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/bootstrap_peers.h: -------------------------------------------------------------------------------- 1 | #ifndef bootstrap_peer_h 2 | #define bootstrap_peer_h 3 | 4 | #include "libp2p/utils/vector.h" 5 | 6 | /*** 7 | * get a list of peers to use to bootstrap the instance 8 | * @param bootstrap_peers A vector of MultiAddress structs will be allocated by this function 9 | * @returns true(1) on success, otherwise false(0) 10 | */ 11 | int repo_config_bootstrap_peers_retrieve(struct Libp2pVector** bootstrap_peers); 12 | 13 | /*** 14 | * frees up memory caused by call to repo_config_bootstrap_peers_retrieve 15 | * @param list the list to free 16 | * @returns true(1) 17 | */ 18 | int repo_config_bootstrap_peers_free(struct Libp2pVector* list); 19 | 20 | #endif /* bootstrap_peer_h */ 21 | -------------------------------------------------------------------------------- /include/ipfs/core/daemon.h: -------------------------------------------------------------------------------- 1 | #ifndef DAEMON_H 2 | #define DAEMON_H 3 | 4 | #include 5 | #include "ipfs/core/ipfs_node.h" 6 | 7 | #define MAX 5 8 | #define CONNECTIONS 50 9 | 10 | struct null_connection_params { 11 | int file_descriptor; 12 | int *count; 13 | char* ip; 14 | int port; 15 | struct IpfsNode* local_node; 16 | }; 17 | 18 | struct null_listen_params { 19 | uint32_t ipv4; 20 | uint16_t port; 21 | }; 22 | 23 | struct IpfsNodeListenParams { 24 | uint32_t ipv4; 25 | uint16_t port; 26 | struct IpfsNode* local_node; 27 | }; 28 | 29 | int ipfs_daemon (int argc, char **argv); 30 | int ipfs_daemon_start(char* repo_path); 31 | int ipfs_daemon_stop(); 32 | int ipfs_ping (int argc, char **argv); 33 | 34 | #endif // DAEMON_H 35 | -------------------------------------------------------------------------------- /test/scripts/test_go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to connect to a go swarm 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | rm -Rf /tmp/ipfs_1 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | echo cleanup complete 21 | } 22 | 23 | function body { 24 | #start the daemon 25 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 26 | daemon_id=$! 27 | sleep 5 28 | 29 | eval "$IPFS" swarm connect /ip4/107.170.104.234/tcp/4001/ipfs/QmRvKrhY2k55uQmGBq4da5XkfGEQvbhiJ4dCLKiG9qMGNF 30 | 31 | sleep 10 32 | 33 | kill -9 $daemon_id 34 | } 35 | -------------------------------------------------------------------------------- /include/ipfs/path/path.h: -------------------------------------------------------------------------------- 1 | #ifndef IPFS_PATH_H 2 | #define IPFS_PATH_H 3 | 4 | #include "ipfs/util/errs.h" 5 | 6 | char* ipfs_path_from_cid (struct Cid *c); 7 | char** ipfs_path_split_n (char *p, char *delim, int n); 8 | char** ipfs_path_split_segments (char *p); 9 | int ipfs_path_segments_length (char **s); 10 | void ipfs_path_free_segments (char ***s); 11 | char *ipfs_path_clean_path(char *str); 12 | int ipfs_path_is_just_a_key (char *p); 13 | int ipfs_path_pop_last_segment (char **str, char *p); 14 | char *ipfs_path_from_segments(char *prefix, char **seg); 15 | int ipfs_path_parse_from_cid (char *dst, char *txt); 16 | int ipfs_path_parse (char *dst, char *txt); 17 | int ipfs_path_is_valid (char *p); 18 | #endif // IPFS_PATH_H 19 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/gateway.h: -------------------------------------------------------------------------------- 1 | #ifndef gateway_h 2 | #define gateway_h 3 | 4 | struct HTTPHeader { 5 | char* header; 6 | char* value; 7 | }; 8 | 9 | struct HTTPHeaders { 10 | struct HTTPHeader** headers; 11 | int num_elements; 12 | }; 13 | 14 | struct PathPrefixes { 15 | int num_elements; 16 | char** prefixes; 17 | }; 18 | 19 | struct Gateway { 20 | char* root_redirect; 21 | int writable; 22 | struct PathPrefixes path_prefixes; 23 | struct HTTPHeaders* http_headers; 24 | }; 25 | 26 | int repo_config_gateway_http_header_init(struct HTTPHeaders* http_headers, char** headers, char** values, int num_elements); 27 | 28 | int repo_config_gateway_new(struct Gateway** gateway); 29 | 30 | int repo_config_gateway_free(struct Gateway* gateway); 31 | 32 | #endif /* gateway_h */ 33 | -------------------------------------------------------------------------------- /include/ipfs/repo/fsrepo/lmdb_cursor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lmdb.h" 4 | 5 | struct lmdb_context { 6 | MDB_env *db_environment; 7 | MDB_txn *current_transaction; 8 | MDB_dbi *datastore_db; 9 | MDB_dbi *journal_db; 10 | }; 11 | 12 | struct lmdb_trans_cursor { 13 | MDB_env* environment; 14 | MDB_txn* parent_transaction; 15 | MDB_txn* transaction; 16 | MDB_dbi* database; 17 | MDB_cursor* cursor; 18 | }; 19 | 20 | /** 21 | * Create a new lmdb_trans_cursor struct 22 | * @returns a newly allocated trans_cursor struct 23 | */ 24 | struct lmdb_trans_cursor* lmdb_trans_cursor_new(); 25 | 26 | /*** 27 | * Clean up resources from a lmdb_trans_cursor struct 28 | * @param in the cursor 29 | * @returns true(1) 30 | */ 31 | int lmdb_trans_cursor_free(struct lmdb_trans_cursor* in); 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/core/test_daemon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "ipfs/core/daemon.h" 6 | #include "../test_helper.h" 7 | #include "libp2p/utils/logger.h" 8 | 9 | int test_daemon_startup_shutdown() { 10 | int retVal = 0; 11 | pthread_t daemon_thread; 12 | char* ipfs_path = "/tmp/.ipfs"; 13 | char* peer_id = NULL; 14 | 15 | if (!drop_and_build_repository(ipfs_path, 4001, NULL, &peer_id)) { 16 | fprintf(stderr, "Unable to drop and build repository at %s\n", ipfs_path); 17 | goto exit; 18 | } 19 | 20 | pthread_create(&daemon_thread, NULL, test_daemon_start, (void*)ipfs_path); 21 | 22 | sleep(3); 23 | 24 | ipfs_daemon_stop(); 25 | 26 | pthread_join(daemon_thread, NULL); 27 | 28 | retVal = 1; 29 | exit: 30 | if (peer_id != NULL) 31 | free(peer_id); 32 | 33 | return retVal; 34 | } 35 | -------------------------------------------------------------------------------- /test/scripts/test_3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to start a deamon and have an api client do a object get 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | post 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | } 17 | 18 | function post { 19 | rm -Rf /tmp/ipfs_1; 20 | rm hello.txt; 21 | } 22 | 23 | function body { 24 | create_hello_world; 25 | eval "$IPFS" add hello.txt 26 | check_failure_with_exit "add hello.txt" $? 27 | 28 | #start the daemon 29 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 30 | daemon_id=$! 31 | sleep 5 32 | 33 | eval "$IPFS" cat QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH 34 | check_failure_with_exit "cat hello.txt" $? 35 | 36 | kill -9 $daemon_id 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/scripts/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #source ./test_helpers.sh 4 | 5 | rm testlog.txt 6 | 7 | num_tests=9 8 | tests_passed=0 9 | tests_failed=0 10 | i=1 11 | while [ $i -le $num_tests ]; do 12 | echo *Running test number $i 13 | echo *Running test number $i >> testlog.txt 14 | ./run_test.sh $i >>testlog.txt 2>&1 15 | retVal=$? 16 | if [ $retVal -ne 0 ]; then 17 | echo *Test number $i failed 18 | echo *Test number $i failed >> testlog.txt 19 | let tests_failed++ 20 | else 21 | echo *Test number $i passed 22 | echo *Test number $i passed >> testlog.txt 23 | let tests_passed++ 24 | fi 25 | let i++ 26 | done 27 | echo Of $num_tests tests, $tests_passed passed and $tests_failed failed. 28 | echo Of $num_tests tests, $tests_passed passed and $tests_failed failed. >> testlog.txt 29 | echo Results are in testlog.txt 30 | -------------------------------------------------------------------------------- /commands/cli/parse.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "libp2p/utils/logger.h" 4 | #include "ipfs/commands/cli/parse.h" 5 | 6 | 7 | /*** 8 | * Parse command line arguments, and place them in a Command struct 9 | * @param argc number of arguments 10 | * @param argv arguments 11 | * @param inStream an incoming stream (not implemented yet) 12 | * @param cmd the Command struct to allocate 13 | * @param request not sure what this is for yet 14 | * @returns true(1) on success, false(0) otherwise 15 | */ 16 | int cli_parse(int argc, char** argv, FILE* inStream, struct Command** cmd, struct Request* request) { 17 | *cmd = (struct Command*) malloc(sizeof(struct Command)); 18 | if (*cmd == NULL) { 19 | libp2p_logger_error("parse", "Unable to allocate memory for the command structure.\n"); 20 | return 0; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /repo/fsrepo/lmdb_cursor.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ipfs/repo/fsrepo/lmdb_cursor.h" 4 | 5 | /** 6 | * Create a new lmdb_trans_cursor struct 7 | * @returns a newly allocated trans_cursor struct 8 | */ 9 | struct lmdb_trans_cursor* lmdb_trans_cursor_new() { 10 | struct lmdb_trans_cursor* out = (struct lmdb_trans_cursor*) malloc(sizeof(struct lmdb_trans_cursor)); 11 | if (out != NULL) { 12 | out->environment = NULL; 13 | out->cursor = NULL; 14 | out->parent_transaction = NULL; 15 | out->transaction = NULL; 16 | out->database = NULL; 17 | } 18 | return out; 19 | } 20 | 21 | /*** 22 | * Clean up resources from a lmdb_trans_cursor struct 23 | * @param in the cursor 24 | * @returns true(1) 25 | */ 26 | int lmdb_trans_cursor_free(struct lmdb_trans_cursor* in) { 27 | if (in != NULL) { 28 | free(in); 29 | } 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /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(int argc, 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/namesys/publisher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/cid/cid.h" 4 | #include "ipfs/core/ipfs_node.h" 5 | #include "ipfs/namesys/pb.h" 6 | 7 | char* ipns_entry_data_for_sig (struct ipns_entry *entry); 8 | int ipns_selector_func (int *idx, struct ipns_entry ***recs, char *k, char **vals); 9 | int ipns_select_record (int *idx, struct ipns_entry **recs, char **vals); 10 | // ipns_validate_ipns_record implements ValidatorFunc and verifies that the 11 | // given 'val' is an IpnsEntry and that that entry is valid. 12 | int ipns_validate_ipns_record (char *k, char *val); 13 | 14 | /** 15 | * Store the hash locally, and notify the network 16 | * 17 | * @param local_node the context 18 | * @param path the "/ipfs/" or "/ipns" path 19 | * @returns true(1) on success, false(0) otherwise 20 | */ 21 | int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, char* path); 22 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/addresses.h: -------------------------------------------------------------------------------- 1 | #ifndef addresses_h 2 | #define addresses_h 3 | 4 | #include "libp2p/utils/linked_list.h" 5 | #include "swarm.h" 6 | 7 | struct Addresses { 8 | // list of strings in format "/family/address/type/port" 9 | struct Libp2pLinkedList* swarm_head; 10 | // info for api connection 11 | char* api; 12 | // info for http gateway 13 | char* gateway; 14 | }; 15 | 16 | /** 17 | * initialize the Addresses struct with data. Must add the SwarmAddresses later 18 | * @param addresses the struct 19 | * @returns true(1) on success, otherwise false(0) 20 | */ 21 | int repo_config_addresses_new(struct Addresses** addresses); 22 | 23 | /** 24 | * clear any memory allocated by a address_new call 25 | * @param addresses the struct 26 | * @returns true(1) 27 | */ 28 | int repo_config_addresses_free(struct Addresses* addresses); 29 | 30 | #endif /* addresses_h */ 31 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/swarm.h: -------------------------------------------------------------------------------- 1 | #ifndef swarm_h 2 | #define swarm_h 3 | 4 | struct SwarmAddresses { 5 | int num_addresses; 6 | char** addresses; 7 | }; 8 | 9 | /** 10 | * add addresses to the SwarmAddresses struct 11 | * @param swarm_addresses the structure 12 | * @param addresses the array of addresses to store 13 | * @param array_length the number of elements in addresses array 14 | * @returns true(1) on success 15 | */ 16 | int repo_config_swarm_address_init(struct SwarmAddresses* swarm_addresses, char** addresses, int array_length); 17 | 18 | int repo_config_swarm_address_new(struct SwarmAddresses** swarm_addresses); 19 | /*** 20 | * free up memory from repo_config_swarm_address_new 21 | * @param swarm_addresses the structure 22 | * @returns true(1) 23 | */ 24 | int repo_config_swarm_address_free(struct SwarmAddresses* swarm_addresses); 25 | 26 | #endif /* swarm_h */ 27 | -------------------------------------------------------------------------------- /include/ipfs/util/errs.h: -------------------------------------------------------------------------------- 1 | #ifndef IPFS_ERRS_H 2 | #define IPFS_ERRS_H 3 | 4 | extern char *Err[]; 5 | 6 | enum { 7 | ErrAllocFailed = 1, 8 | ErrNULLPointer, 9 | ErrUnknow, 10 | ErrPipe, 11 | ErrPoll, 12 | ErrPublishFailed, 13 | ErrResolveFailed, 14 | ErrResolveRecursion, 15 | ErrExpiredRecord, 16 | ErrUnrecognizedValidity, 17 | ErrInvalidProquint, 18 | ErrInvalidDomain, 19 | ErrInvalidDNSLink, 20 | ErrBadPath, 21 | ErrNoComponents, 22 | ErrCidDecode, 23 | ErrNoLink, 24 | ErrNoLinkFmt, 25 | ErrInvalidParam, 26 | ErrResolveLimit, 27 | ErrInvalidSignature, 28 | ErrInvalidSignatureFmt, 29 | ErrNoRecord, 30 | ErrCidDecodeFailed, 31 | ErrOffline 32 | } ErrsIdx; 33 | #endif // IPFS_ERRS_H 34 | -------------------------------------------------------------------------------- /test/scripts/test_6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to start a deamon and have an api client do a name publish 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | post 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.txt; 22 | } 23 | 24 | function body { 25 | create_hello_world; 26 | eval "$IPFS" add hello.txt 27 | check_failure_with_exit "add hello.txt" $? 28 | 29 | #start the daemon 30 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 31 | daemon_id=$! 32 | sleep 5 33 | 34 | eval "$IPFS" name publish QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH 35 | check_failure_with_exit "name publish" $? 36 | 37 | kill -9 $daemon_id 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /include/ipfs/importer/resolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/merkledag/node.h" 4 | #include "ipfs/core/ipfs_node.h" 5 | 6 | /** 7 | * Implements a resover. EOM 8 | */ 9 | 10 | /** 11 | * Interogate the path and the current node, looking 12 | * for the desired node. 13 | * @param path the current path 14 | * @param from the current node (or NULL if it is the first call) 15 | * @returns what we are looking for, or NULL if it wasn't found 16 | */ 17 | struct HashtableNode* ipfs_resolver_get(const char* path, struct HashtableNode* from, const struct IpfsNode* ipfs_node); 18 | 19 | /** 20 | * Interrogate the path, looking for the peer 21 | * @param path the peer path to search for 22 | * @param ipfs_node the context 23 | * @returns the MultiAddress that relates to the path, or NULL if not found 24 | */ 25 | struct Libp2pPeer* ipfs_resolver_find_peer(const char* path, const struct IpfsNode* ipfs_node); 26 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | /*** 24 | * Parse the command line 25 | * @param argc the number of arguments 26 | * @param argv the actual arguments 27 | * @returns a command structure 28 | */ 29 | struct Command* ipfs_cmd_parse_command_line(int argc, char** argv); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/ipfs/unixfs/format.h: -------------------------------------------------------------------------------- 1 | enum UnixFSFormatType { RAW, UNIXFS_FILE, DIRECTORY, METADATA, SYMLINK }; 2 | 3 | struct UnixFSData { 4 | enum UnixFSFormatType type; 5 | unsigned char* data; 6 | size_t data_length; 7 | }; 8 | 9 | struct FSNode { 10 | unsigned char* data; 11 | size_t data_size; 12 | size_t* blocksizes; 13 | size_t subtotal; 14 | enum UnixFSFormatType type; 15 | }; 16 | 17 | /** 18 | * Copy data into a new struct 19 | * @param type the type of data 20 | * @param data the acutal data 21 | * @param data_length the length of the data array 22 | * @param result where the struct will be stored 23 | * @returns true(1) on success 24 | */ 25 | int ipfs_unixfs_format_new(enum UnixFSFormatType type, const unsigned char* data, size_t data_length, struct UnixFSData** result); 26 | 27 | /** 28 | * Free memory allocated by _new 29 | * @param data the struct 30 | * @returns true(1) on success 31 | */ 32 | int ipfs_unixfs_format_free(struct UnixFSData* data); 33 | -------------------------------------------------------------------------------- /util/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ipfs/util/time.h" 5 | 6 | int ipfs_util_time_parse_RFC3339 (struct timespec *ts, char *s) 7 | { 8 | char *r; 9 | struct tm tm; 10 | 11 | if (!ts || !s || strlen(s) != 35) { 12 | return 1; 13 | } 14 | r = strptime (s, "%Y-%m-%dT%H:%M:%S", &tm); 15 | if (!r || *r != '.') { 16 | return 2; 17 | } 18 | ts->tv_sec = mktime(&tm); 19 | ts->tv_nsec = atoll(++r); 20 | return 0; 21 | } 22 | 23 | char *ipfs_util_time_format_RFC3339 (struct timespec *ts) 24 | { 25 | char buf[31], *ret; 26 | 27 | ret = malloc(36); 28 | if (!ret) { 29 | return NULL; 30 | } 31 | 32 | if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.%%09dZ00:00", gmtime(&(ts->tv_sec))) != sizeof(buf)-1 || 33 | snprintf(ret, 36, buf, ts->tv_nsec) != 35) { 34 | free (ret); 35 | return NULL; 36 | } 37 | return ret; 38 | } 39 | -------------------------------------------------------------------------------- /test/scripts/test_4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to start a deamon and have an api client do a name resolve 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | post 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.txt; 22 | } 23 | 24 | function body { 25 | create_hello_world; 26 | eval "$IPFS" add hello.txt 27 | check_failure_with_exit "add hello.txt" $? 28 | 29 | #start the daemon 30 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 31 | daemon_id=$! 32 | sleep 5 33 | 34 | eval "$IPFS" name publish QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH 35 | check_failure_with_exit "name publish" $? 36 | 37 | eval "$IPFS" name resolve /ipns/QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4 38 | check_failure_with_exit "name resolve" $? 39 | 40 | kill -9 $daemon_id 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /repo/config/addresses.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ipfs/repo/config/addresses.h" 6 | 7 | char* alloc_and_copy(char* source) { 8 | unsigned long strLen = strlen(source); 9 | char* result = malloc(sizeof(char) * (strLen + 1)); 10 | if (result != NULL) { 11 | strncpy(result, source, strLen); 12 | result[strLen] = 0; 13 | } 14 | return result; 15 | } 16 | 17 | int repo_config_addresses_new(struct Addresses** addresses) { 18 | *addresses = (struct Addresses*)malloc(sizeof(struct Addresses)); 19 | if (*addresses == NULL) 20 | return 0; 21 | 22 | struct Addresses* addr = *addresses; 23 | 24 | // allocate memory to store api and gateway 25 | addr->api = NULL; 26 | addr->gateway = NULL; 27 | addr->swarm_head = NULL; 28 | 29 | return 1; 30 | } 31 | 32 | int repo_config_addresses_free(struct Addresses* addresses) { 33 | free(addresses->api); 34 | free(addresses->gateway); 35 | libp2p_utils_linked_list_free(addresses->swarm_head); 36 | free(addresses); 37 | return 1; 38 | } 39 | -------------------------------------------------------------------------------- /include/ipfs/commands/command_option.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDS_COMMAND_OPTION_H__ 2 | #define __COMMANDS_COMMAND_OPTION_H__ 3 | 4 | #include 5 | 6 | enum Kind { invalid, boolean, integer, unsignedInt, decimal, str }; 7 | 8 | struct CommandOption { 9 | char** names; 10 | int name_count; 11 | enum Kind kind; 12 | char* description; 13 | int default_int_val; 14 | int default_bool_val; 15 | uint32_t default_uint_val; 16 | float default_float_val; 17 | char* default_string_val; 18 | }; 19 | 20 | /*** 21 | * Allocate the resources needed for a command option 22 | * @param option the CommandOption to initialize 23 | * @param description a description of this CommandOption 24 | * @returns true(1) on success 25 | */ 26 | int commands_command_option_init(struct CommandOption* option, char* description); 27 | 28 | /*** 29 | * Cleans up the resources of a CommandOption 30 | * @param option the CommandOption to clean up 31 | * @returns true(1) 32 | */ 33 | int commands_command_option_free(struct CommandOption* option); 34 | 35 | #endif /* option_h */ 36 | -------------------------------------------------------------------------------- /test/scripts/test_9.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to retrieve binary file from running daemon 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | rm -Rf /tmp/ipfs_1 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.bin; 22 | rm hello2.bin; 23 | } 24 | 25 | function body { 26 | create_binary_file 256; 27 | eval "$IPFS" add hello.bin 28 | check_failure_with_exit "add hello.bin" $? 29 | 30 | #start the daemon 31 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 32 | daemon_id=$! 33 | sleep 5 34 | 35 | eval "$IPFS" cat QmX4zpwaE7CSgZZsULgoB3gXYC6hh7RN19bEfWxw7sL8Xx > hello2.bin 36 | check_failure_with_exit "cat" $? 37 | 38 | # file size should be 256 39 | actualsize=$(wc -c < hello2.bin) 40 | if [ $actualsize -ne 256 ]; then 41 | echo '*** Failure *** file size incorrect' 42 | fi 43 | 44 | kill -9 $daemon_id 45 | } 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/ipfs/core/net.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libp2p/net/stream.h" 4 | 5 | struct IpfsListener { 6 | char* conCh; 7 | char* protocol; 8 | }; 9 | 10 | /** 11 | * Do a socket accept 12 | * @param listener the listener 13 | * @param stream the returned stream 14 | * @returns true(1) on success, false(0) otherwise 15 | */ 16 | int ipfs_core_net_accept(struct IpfsListener* listener, struct Stream* stream); 17 | 18 | /** 19 | * Listen using a particular protocol 20 | * @param node the node 21 | * @param protocol the protocol to use 22 | * @param listener the results 23 | * @returns true(1) on success, false(0) otherwise 24 | */ 25 | int ipfs_core_net_listen(struct IpfsNode* node, char* protocol, struct IpfsListener* listener); 26 | 27 | /*** 28 | * Dial a peer 29 | * @param node this node 30 | * @param peer_id who to dial 31 | * @param protocol the protocol to use 32 | * @param stream the resultant stream 33 | * @returns true(1) on success, otherwise false(0) 34 | */ 35 | int ipsf_core_net_dial(struct IpfsNode* node, char* peer_id, char* protocol, struct Stream* stream); 36 | -------------------------------------------------------------------------------- /include/ipfs/dnslink/dnslink.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSLINK_H 2 | #define DNSLINK_H 3 | 4 | #include "ipfs/util/errs.h" 5 | 6 | // DefaultDepthLimit controls how many dns links to resolve through before 7 | // returning. Users can override this default. 8 | #ifndef DefaultDepthLimit 9 | #define DefaultDepthLimit 16 10 | #endif 11 | // MaximumDepthLimit governs the max number of recursive resolutions. 12 | #ifndef MaximumDepthLimit 13 | #define MaximumDepthLimit 256 14 | #endif 15 | 16 | #ifndef IPFS_DNSLINK_C 17 | extern int (*ipfs_dnslink_lookup_txt)(char ***, char *); 18 | #endif // IPFS_DNSLINK_C 19 | 20 | int ipfs_dns (int argc, char **argv); 21 | int ipfs_dnslink_resolve (char **p, char *domain); 22 | int ipfs_dnslink_resolve_n (char **p, char *d, int depth); 23 | int ipfs_dnslink_resolv_lookupTXT(char ***txt, char *domain); 24 | int ipfs_dnslink_resolve_once (char ***p, char *domain); 25 | int ipfs_dnslink_parse_txt (char **path, char *txt); 26 | int ipfs_dnslink_parse_link_domain (char **domain, char**rest, char *txt); 27 | #endif // DNSLINK_H 28 | -------------------------------------------------------------------------------- /test/scripts/test_1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to retrieve large binary file from running daemon 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | rm -Rf /tmp/ipfs_1 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.bin; 22 | rm hello2.bin; 23 | } 24 | 25 | function body { 26 | retVal=0 27 | create_binary_file 300000; 28 | eval "$IPFS" add hello.bin 29 | check_failure_with_exit "add hello.bin" $? 30 | 31 | #start the daemon 32 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 33 | daemon_id=$! 34 | sleep 5 35 | 36 | eval "$IPFS" cat QmQY3qveNvosAgRhcgVVgkPPLZv4fpWuxhL3pfihzgKtTf > hello2.bin 37 | check_failure "cat" $? 38 | 39 | # file size should be 300000 40 | actualsize=$(wc -c < hello2.bin) 41 | if [ $actualsize -ne 300000 ]; then 42 | echo '*** Failure *** file size incorrect' 43 | let retVal=1 44 | fi 45 | 46 | kill -9 $daemon_id 47 | return $retVal 48 | } 49 | -------------------------------------------------------------------------------- /namesys/proquint_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "ipfs/namesys/namesys.h" 9 | 10 | int main(void) { 11 | char *r, *s; 12 | int i; 13 | char *p[] = {"lusab-babad", "gutih-tugad", "gutuk-bisog", "mudof-sakat", 14 | "haguz-biram", "mabiv-gibot", "natag-lisaf", "tibup-zujah", 15 | "tobog-higil", "todah-vobij", "sinid-makam", "budov-kuras", 16 | NULL}; 17 | 18 | for (i = 0 ; p[i] ; i++) { 19 | r = ipfs_proquint_decode (p[i]); 20 | if (r) { 21 | struct in_addr ip_addr; 22 | memcpy (&(ip_addr.s_addr), r, sizeof(ip_addr.s_addr)); 23 | printf ("%s\t%s", p[i], inet_ntoa(ip_addr)); 24 | s = ipfs_proquint_encode(r, sizeof(ip_addr.s_addr)); 25 | free (r); 26 | if (s) { 27 | printf ("\t%s", s); 28 | free (s); 29 | } 30 | printf("\n"); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /test/scripts/test_7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to add and retrieve binary file from running daemon 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | rm -Rf /tmp/ipfs_1 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.bin; 22 | rm hello2.bin; 23 | } 24 | 25 | function body { 26 | create_binary_file 256; 27 | 28 | #start the daemon 29 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 30 | daemon_id=$! 31 | sleep 5 32 | 33 | # add file 34 | eval "$IPFS" add hello.bin 35 | check_failure_with_exit "add hello.bin" $? 36 | sleep 5 37 | 38 | # retrieve file 39 | eval "$IPFS" cat QmX4zpwaE7CSgZZsULgoB3gXYC6hh7RN19bEfWxw7sL8Xx > hello2.bin 40 | check_failure_with_exit "cat" $? 41 | 42 | # file size should be 256 43 | actualsize=$(wc -c < hello2.bin) 44 | if [ $actualsize -ne 256 ]; then 45 | echo '*** Failure *** file size incorrect' 46 | fi 47 | 48 | kill -9 $daemon_id 49 | } 50 | -------------------------------------------------------------------------------- /test/scripts/test_8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to add and retrieve binary file from running daemon 5 | # 6 | #### 7 | 8 | source ./test_helpers.sh 9 | 10 | IPFS="../../main/ipfs --config /tmp/ipfs_1" 11 | 12 | function pre { 13 | rm -Rf /tmp/ipfs_1 14 | eval "$IPFS" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | } 18 | 19 | function post { 20 | rm -Rf /tmp/ipfs_1; 21 | rm hello.bin; 22 | rm hello2.bin; 23 | } 24 | 25 | function body { 26 | create_binary_file 256; 27 | 28 | #start the daemon 29 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 30 | daemon_id=$! 31 | sleep 5 32 | 33 | # add file 34 | eval "$IPFS" add hello.bin 35 | check_failure_with_exit "add hello.bin" $? 36 | sleep 5 37 | 38 | # retrieve file 39 | eval "$IPFS" cat QmX4zpwaE7CSgZZsULgoB3gXYC6hh7RN19bEfWxw7sL8Xx > hello2.bin 40 | check_failure_with_exit "cat" $? 41 | 42 | # file size should be 256 43 | actualsize=$(wc -c < hello2.bin) 44 | if [ $actualsize -ne 256 ]; then 45 | echo '*** Failure *** file size incorrect' 46 | fi 47 | 48 | kill -9 $daemon_id 49 | } 50 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /util/errs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *Err[] = { 4 | NULL, 5 | "ErrAllocFailed", 6 | "ErrNULLPointer", 7 | "ErrUnknow", 8 | "ErrPipe", 9 | "ErrPoll", 10 | "Could not publish name." 11 | "Could not resolve name.", 12 | "Could not resolve name (recursion limit exceeded).", 13 | "expired record", 14 | "unrecognized validity type", 15 | "not a valid proquint string", 16 | "not a valid domain name", 17 | "not a valid dnslink entry", 18 | // ErrBadPath is returned when a given path is incorrectly formatted 19 | "invalid 'ipfs ref' path", 20 | // Paths after a protocol must contain at least one component 21 | "path must contain at least one component", 22 | "TODO: ErrCidDecode", 23 | NULL, 24 | "no link named %s under %s", 25 | "ErrInvalidParam", 26 | // ErrResolveLimit is returned when a recursive resolution goes over 27 | // the limit. 28 | "resolve depth exceeded", 29 | NULL, 30 | "Invalid value. Not signed by PrivateKey corresponding to %s", 31 | "no usable records in given set", 32 | "failed to decode empty key constant", 33 | "routing system in offline mode" 34 | }; 35 | -------------------------------------------------------------------------------- /commands/command.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ipfs/commands/command.h" 4 | 5 | int commands_command_init(struct Command* cmd) { 6 | // allocate memory for Argument array 7 | cmd->arguments = malloc(cmd->argument_count * sizeof(struct Argument*)); 8 | if (cmd->arguments == NULL) 9 | return 0; 10 | // allocate memory for each argument 11 | for(int i = 0; i < cmd->argument_count; i++) 12 | cmd->arguments[i] = malloc(sizeof(struct Argument)); 13 | 14 | // allocate memory for CommandOption array 15 | cmd->options = malloc(cmd->option_count * sizeof(struct CommandOption*)); 16 | if (cmd->options == NULL) 17 | return 0; 18 | // allocate memory for each CommandOption 19 | for(int i = 0; i < cmd->option_count; i++) 20 | cmd->options[i] = malloc(sizeof(struct CommandOption)); 21 | return 1; 22 | } 23 | 24 | int commands_command_free(struct Command* cmd) { 25 | // arguments 26 | for(int i = 0; i < cmd->argument_count; i++) 27 | commands_argument_free(cmd->arguments[i]); 28 | free(cmd->arguments); 29 | 30 | //command options 31 | for(int i = 0; i < cmd->option_count; i++) 32 | commands_command_option_free(cmd->options[i]); 33 | free(cmd->options); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /include/ipfs/repo/init.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libp2p/utils/vector.h" 4 | 5 | /** 6 | * Make an IPFS directory at the passed in path 7 | * @param path the path 8 | * @param swarm_port the port that the swarm will run on 9 | * @param bootstrap_peers a Vector of MultiAddress of fellow peers 10 | * @param peer_id the peer id generated 11 | * @returns true(1) on success, false(0) on failure 12 | */ 13 | int make_ipfs_repository(const char* path, int swarm_port, struct Libp2pVector* bootstrap_peers, char **peer_id); 14 | 15 | /** 16 | * Initialize a repository, called from the command line 17 | * @param argc number of arguments 18 | * @param argv arguments 19 | * @returns true(1) on success 20 | */ 21 | int ipfs_repo_init(int argc, char** argv); 22 | 23 | /** 24 | * Get the correct repo directory. Looks in all the appropriate places 25 | * for the ipfs directory. 26 | * @param argc number of command line arguments 27 | * @param argv command line arguments 28 | * @param repo_dir the results. This will point to the [IPFS_PATH]/.ipfs directory 29 | * @returns true(1) if the directory is there, false(0) if it is not. 30 | */ 31 | int ipfs_repo_get_directory(int argc, char** argv, char** repo_dir); 32 | 33 | -------------------------------------------------------------------------------- /include/ipfs/namesys/pb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef int32_t IpnsEntry_ValidityType; 5 | 6 | struct ipns_entry { 7 | char *value; 8 | char *signature; 9 | int32_t *validityType; 10 | char *validity; 11 | uint64_t *sequence; 12 | uint64_t *ttl; 13 | struct routingResolver *cache; // cache and eol should be the last items. 14 | struct timespec *eol; 15 | }; 16 | struct namesys_pb { 17 | // TODO 18 | struct ipns_entry *IpnsEntry; 19 | }; 20 | 21 | // setting an EOL says "this record is valid until..." 22 | const static IpnsEntry_ValidityType IpnsEntry_EOL = 0; 23 | 24 | /* 25 | static char *IpnsEntry_ValidityType_name[] = { 26 | "EOL", 27 | NULL 28 | }; 29 | */ 30 | 31 | int IpnsEntry_ValidityType_value (char *s); 32 | struct ipns_entry* ipfs_namesys_pb_new_ipns_entry (); 33 | char* ipfs_namesys_pb_get_validity (struct ipns_entry*); 34 | char* ipns_entry_data_for_sig(struct ipns_entry*); 35 | char* ipfs_ipns_entry_get_signature(struct ipns_entry*); 36 | int ipfs_namesys_pb_get_value (char**, struct ipns_entry*); 37 | IpnsEntry_ValidityType ipfs_namesys_pb_get_validity_type (struct ipns_entry*); 38 | void ipfs_namesys_ipnsentry_reset (struct ipns_entry *m); 39 | -------------------------------------------------------------------------------- /namesys/pb.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ipfs/namesys/routing.h" 4 | #include "ipfs/namesys/pb.h" 5 | 6 | /* 7 | int IpnsEntry_ValidityType_value (char *s) 8 | { 9 | int r; 10 | 11 | if (!s) { 12 | return -1; // invalid. 13 | } 14 | 15 | for (r = 0 ; IpnsEntry_ValidityType_name[r] ; r++) { 16 | if (strcmp (IpnsEntry_ValidityType_name[r], s) == 0) { 17 | return r; // found 18 | } 19 | } 20 | 21 | return -1; // not found. 22 | } 23 | */ 24 | 25 | struct ipns_entry* ipfs_namesys_pb_new_ipns_entry () 26 | { 27 | return calloc(1, sizeof (struct ipns_entry)); 28 | } 29 | 30 | void ipfs_namesys_ipnsentry_reset (struct ipns_entry *m) 31 | { 32 | if (m) { 33 | // ipns_entry is an struct of pointers, 34 | // so we can access as an array of pointers. 35 | char **a = (char **)m; 36 | int i, l = (sizeof (struct ipns_entry) / sizeof (void*)) - 2; // avoid last 2 pointers, cache and eol. 37 | for (i = 0 ; i < l ; i++) { 38 | if (a[i]) { 39 | free (a[i]); // free allocated pointers, 40 | a[i] = NULL; // and mark as free. 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /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 | unsigned char outgoing[outgoing_length]; 16 | unsigned 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C-IPFS 2 | IPFS implementation in C, (not just an API client library). 3 | 4 | ## Quick start for users: 5 | * **ipfs init** to create an ipfs repository on your machine 6 | * **ipfs add MyFile.txt** to add a file to the repository, will return with a hash that can be used to retrieve the file. 7 | * **ipfs cat _hash_** to retrieve a file from the repository 8 | 9 | ## For techies (ipfs spec docs): 10 | * [getting started](https://github.com/ipfs/specs/blob/master/overviews/implement-ipfs.md) 11 | * [specifications](https://github.com/ipfs/specs) 12 | * [getting started](https://github.com/ipfs/community/issues/177) 13 | * [libp2p](https://github.com/libp2p/specs) 14 | 15 | ## Prerequisites: To compile the C version you will need, all included as submodules: 16 | * [lmdb](https://github.com/jmjatlanta/lmdb) 17 | * [c-protobuf](https://github.com/Agorise/c-protobuf) 18 | * [c-multihash](https://github.com/Agorise/c-multihash) 19 | * [c-multiaddr](https://github.com/Agorise/c-multiaddr) 20 | * [c-libp2p](https://github.com/Agorise/c-libp2p) 21 | 22 | And of course this project at https://github.com/Agorise/c-ipfs 23 | 24 | ## How to compile the C version: 25 | ``` 26 | git submodule update --init --recursive 27 | make all 28 | ``` 29 | -------------------------------------------------------------------------------- /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/repo/fsrepo/lmdb_datastore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "lmdb.h" 4 | #include "libp2p/db/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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 AGORISE, LTD. 4 | An International Business Company, Cyprus Reg# ΗΕ375959 5 | 6 | Contains works from BitShares Munich IVS 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /unixfs/format.c.old: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ipfs/unixfs/format.h" 6 | 7 | 8 | /** 9 | * Copy data into a new struct 10 | * @param type the type of data 11 | * @param data the acutal data 12 | * @param data_length the length of the data array 13 | * @param result where the struct will be stored 14 | * @returns true(1) on success 15 | */ 16 | int ipfs_unixfs_format_new(enum UnixFSFormatType type, const unsigned char* data, 17 | size_t data_length, struct UnixFSData** result) { 18 | struct UnixFSData* new_struct = (struct UnixFSData*)malloc(sizeof(struct UnixFSData)); 19 | if (new_struct == NULL) 20 | return 0; 21 | 22 | new_struct->data = (unsigned char*) malloc(sizeof(unsigned char) * data_length); 23 | if (new_struct->data == NULL) { 24 | free (new_struct); 25 | return 0; 26 | } 27 | memcpy(new_struct->data, data, data_length); 28 | new_struct->type = type; 29 | new_struct->data_length = data_length; 30 | return 1; 31 | } 32 | 33 | /** 34 | * Free memory allocated by _new 35 | * @param data the struct 36 | * @returns true(1) on success 37 | */ 38 | int ipfs_unixfs_format_free(struct UnixFSData* unixfs_data) { 39 | free(unixfs_data->data); 40 | free(unixfs_data); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /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 (ipfs_isdomain_is_domain (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 | -------------------------------------------------------------------------------- /test/scripts/test_5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #### 4 | # Attempt to start 2 deamons and have an api client of server A ask for a file from server B 5 | #### 6 | 7 | source ./test_helpers.sh 8 | 9 | IPFS1="../../main/ipfs --config /tmp/ipfs_1" 10 | IPFS2="../../main/ipfs --config /tmp/ipfs_2" 11 | 12 | function pre { 13 | post 14 | eval "$IPFS1" init; 15 | check_failure_with_exit "pre" $? 16 | cp ../config.test1.wo_journal /tmp/ipfs_1/config 17 | 18 | eval "$IPFS2" init; 19 | check_failure_with_exit "pre ipfs2" $? 20 | cp ../config.test2.wo_journal /tmp/ipfs_2/config 21 | } 22 | 23 | function post { 24 | rm -Rf /tmp/ipfs_1; 25 | rm -Rf /tmp/ipfs_2; 26 | rm hello.txt; 27 | } 28 | 29 | function body { 30 | create_hello_world; 31 | eval "$IPFS1" add hello.txt 32 | check_failure_with_exit "add hello.txt" $? 33 | 34 | #start the daemons 35 | eval "../../main/ipfs --config /tmp/ipfs_1 daemon &" 36 | daemon_id_1=$! 37 | eval "../../main/ipfs --config /tmp/ipfs_2 daemon &" 38 | daemon_id_2=$! 39 | sleep 5 40 | 41 | #A client of server 2 wants the file at server 1 42 | eval "$IPFS2" cat QmYAXgX8ARiriupMQsbGXtKdDyGzWry1YV3sycKw1qqmgH 43 | retVal=$? 44 | check_failure "cat" $retVal 45 | 46 | kill -9 $daemon_id_1 47 | kill -9 $daemon_id_2 48 | exit $retVal 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /include/ipfs/exchange/bitswap/engine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | //#include "ipfs/exchange/bitswap/bitswap.h" we must forward declare here, as BitswapContext has a reference to BitswapEngine 5 | 6 | struct BitswapContext; 7 | 8 | struct BitswapEngine { 9 | int shutting_down; 10 | pthread_t wantlist_processor_thread; 11 | pthread_t peer_request_processor_thread; 12 | }; 13 | 14 | /*** 15 | * Allocate resources for a BitswapEngine 16 | * @returns a new struct BitswapEngine 17 | */ 18 | struct BitswapEngine* ipfs_bitswap_engine_new(); 19 | 20 | /*** 21 | * Deallocate resources from struct BitswapEngine 22 | * @param engine the engine to free 23 | * @returns true(1) 24 | */ 25 | int ipfs_bitswap_engine_free(struct BitswapEngine* engine); 26 | 27 | /** 28 | * Starts the bitswap engine that processes queue items. There 29 | * should only be one of these per ipfs instance. 30 | * 31 | * @param context the context 32 | * @returns true(1) on success, false(0) otherwise 33 | */ 34 | int ipfs_bitswap_engine_start(const struct BitswapContext* context); 35 | 36 | /*** 37 | * Shut down the engine 38 | * 39 | * @param context the context 40 | * @returns true(1) on success, false(0) otherwise 41 | */ 42 | int ipfs_bitswap_engine_stop(const struct BitswapContext* context); 43 | -------------------------------------------------------------------------------- /core/net.c: -------------------------------------------------------------------------------- 1 | 2 | #include "ipfs/core/net.h" 3 | 4 | /** 5 | * Do a socket accept 6 | * @param listener the listener 7 | * @returns true(1) on success, false(0) otherwise 8 | */ 9 | int ipfs_core_net_accept(struct IpfsListener listener) { 10 | //TODO: Implement this 11 | return 0; 12 | } 13 | 14 | /** 15 | * Listen using a particular protocol 16 | * @param node the node 17 | * @param protocol the protocol to use 18 | * @param listener the results 19 | * @returns true(1) on success, false(0) otherwise 20 | */ 21 | int ipfs_core_net_listen(struct IpfsNode* node, char* protocol, struct IpfsListener* listener){ 22 | // TODO: Implement this 23 | return 0; 24 | } 25 | 26 | /*** 27 | * Dial a peer 28 | * @param node this node 29 | * @param peer_id who to dial (null terminated string) 30 | * @param protocol the protocol to use 31 | * @param stream the resultant stream 32 | * @returns true(1) on success, otherwise false(0) 33 | */ 34 | int ipsf_core_net_dial(const struct IpfsNode* node, const char* peer_id, const char* protocol, struct Stream* stream) { 35 | //TODO: Implement this 36 | // get the multiaddress from the peerstore 37 | struct Libp2pPeer* peer = libp2p_peerstore_get_peer(node->peerstore, peer_id, strlen(peer_id)); 38 | // attempt to connect 39 | 40 | // attempt to use the protocol passed in 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /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 ipfs_namesys_base_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 (ipfs_path_segments_length(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 | -------------------------------------------------------------------------------- /test/scripts/test_helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ##### 4 | # global to keep track of failures 5 | ##### 6 | failure_count=0 7 | 8 | ##### 9 | # Functions to help with test scripts 10 | ##### 11 | 12 | #### 13 | # Create a text file "hello.txt" that contains "Hello, World!" 14 | #### 15 | function create_hello_world { 16 | echo 'Hello, World!' > hello.txt 17 | } 18 | 19 | #### 20 | # Create a binary file 21 | ### 22 | function create_binary_file { 23 | rm hello.bin 24 | num_bytes=$1 25 | if [ $num_bytes -eq 0 ]; then 26 | num_bytes=255; 27 | fi 28 | exec ./generate_file hello.bin $num_bytes 29 | } 30 | 31 | #### 32 | # Checks the return code and displays message if return code is not 0 33 | # Param $1 name of function 34 | # Param $2 return code 35 | #### 36 | function check_failure() { 37 | FUNC=$1; 38 | RESULT=$2; 39 | if [ $RESULT -ne 0 ]; then 40 | echo "***Failure*** in $FUNC. The return value was $RESULT"; 41 | fi 42 | return $RESULT 43 | } 44 | 45 | #### 46 | # Checks the return code and displays message if return code is not 0 47 | # Param $1 name of function 48 | # Param $2 return code 49 | #### 50 | function check_failure_with_exit() { 51 | FUNC=$1; 52 | RESULT=$2; 53 | if [ $RESULT -ne 0 ]; then 54 | echo "***Failure*** in $FUNC. The return value was $RESULT"; 55 | exit $RESULT 56 | fi 57 | return $RESULT 58 | } 59 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/identity.h: -------------------------------------------------------------------------------- 1 | #ifndef __REPO_CONFIG_IDENTITY_H__ 2 | #define __REPO_CONFIG_IDENTITY_H__ 3 | 4 | #include "libp2p/crypto/rsa.h" 5 | #include "libp2p/peer/peer.h" 6 | 7 | struct Identity { 8 | struct Libp2pPeer* peer; // a Peer object 9 | struct RsaPrivateKey private_key; // a private key 10 | }; 11 | 12 | /*** 13 | * initializes a new keypair, and puts it in the Identity struct 14 | */ 15 | int repo_config_identity_init(struct Identity* identity, unsigned long num_bits_for_keypair); 16 | 17 | /*** 18 | * Build a RsaPrivateKey struct from a base64 string of the private key 19 | * @param identity where to put the new struct 20 | * @param base64 the base 64 encoded private key in DER format 21 | * @returns true(1) on success 22 | */ 23 | int repo_config_identity_build_private_key(struct Identity* identity, const char* base64); 24 | 25 | /*** 26 | * Frees resources held by Identity 27 | * @param identity the identity that we're cleaning up 28 | * @returns true(0) 29 | */ 30 | int repo_config_identity_free(struct Identity* identity); 31 | 32 | /*** 33 | * Initializes a new identity struct that will need to be identity_free'd 34 | * @param identity the identity to allocate memory for 35 | * @returns true(1) on success 36 | */ 37 | int repo_config_identity_new(struct Identity** identity); 38 | 39 | #endif /* identity_h */ 40 | -------------------------------------------------------------------------------- /include/ipfs/pin/pin.h: -------------------------------------------------------------------------------- 1 | #ifndef IPFS_PIN_H 2 | #define IPFS_PIN_H 3 | 4 | #include "ipfs/util/errs.h" 5 | 6 | #ifdef IPFS_PIN_C 7 | const char *ipfs_pin_linkmap[] = { 8 | "recursive", 9 | "direct", 10 | "indirect", 11 | "internal", 12 | "not pinned", 13 | "any", 14 | "all" 15 | }; 16 | #else // IPFS_PIN_C 17 | extern const char *ipfs_pin_map[]; 18 | #endif // IPFS_PIN_C 19 | enum { 20 | Recursive = 0, 21 | Direct, 22 | Indirect, 23 | Internal, 24 | NotPinned, 25 | Any, 26 | All 27 | }; 28 | 29 | typedef int PinMode; 30 | 31 | struct Pinned { 32 | struct Cid *Key; 33 | PinMode Mode; 34 | struct Cid *Via; 35 | }; 36 | 37 | int ipfs_pin_init (); 38 | // Return pointer to string or NULL if invalid. 39 | char *ipfs_pin_mode_to_string (PinMode mode); 40 | // Return array index or -1 if fail. 41 | PinMode ipfs_string_to_pin_mode (char *str); 42 | int ipfs_pin_is_pinned (struct Pinned *p); 43 | // Find out if the child is in the hash. 44 | int ipfs_pin_has_child (struct FSRepo *ds, 45 | unsigned char *hash, size_t hash_size, 46 | unsigned char *child, size_t child_size); 47 | #endif // IPFS_PIN_H 48 | -------------------------------------------------------------------------------- /test/core/test_node.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helper.h" 5 | #include "ipfs/core/ipfs_node.h" 6 | 7 | int test_node_peerstore() { 8 | int retVal = 0; 9 | const char *repo_path = "/tmp/test1"; 10 | char* peer_id = NULL; 11 | struct IpfsNode *local_node = NULL; 12 | struct Libp2pPeer* peer = NULL; 13 | 14 | if (!drop_and_build_repository(repo_path, 4001, NULL, &peer_id)) 15 | goto exit; 16 | 17 | if (!ipfs_node_online_new(repo_path, &local_node)) 18 | goto exit; 19 | 20 | // add a peer to the peerstore 21 | peer = libp2p_peer_new(); 22 | if (peer == NULL) 23 | goto exit; 24 | 25 | peer->id_size = strlen(peer_id); 26 | peer->id = malloc(peer->id_size); 27 | memcpy(peer->id, peer_id, peer->id_size); 28 | 29 | if (!libp2p_peerstore_add_peer(local_node->peerstore, peer)) 30 | goto exit; 31 | 32 | // add a second peer by changing the id a bit 33 | char tmp = peer->id[3]; 34 | char tmp2 = peer->id[4]; 35 | char tmp3 = peer->id[5]; 36 | peer->id[3] = tmp2; 37 | peer->id[4] = tmp3; 38 | peer->id[5] = tmp; 39 | 40 | if (!libp2p_peerstore_add_peer(local_node->peerstore, peer)) 41 | goto exit; 42 | 43 | 44 | retVal = 1; 45 | exit: 46 | if (peer_id != NULL) 47 | free(peer_id); 48 | if (peer != NULL) 49 | libp2p_peer_free(peer); 50 | if (local_node != NULL) 51 | ipfs_node_free(local_node); 52 | 53 | return retVal; 54 | } 55 | -------------------------------------------------------------------------------- /include/ipfs/journal/journal_entry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * A journal entry protobuf 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | struct JournalEntry { 11 | unsigned long long timestamp; 12 | uint8_t pin; 13 | uint8_t *hash; 14 | size_t hash_size; 15 | }; 16 | 17 | struct JournalEntry* ipfs_journal_entry_new(); 18 | 19 | int ipfs_journal_entry_free(struct JournalEntry* entry); 20 | 21 | /** 22 | * Determine the maximum size of a protobuf'd JournalEntry 23 | */ 24 | int ipfs_journal_entry_encode_size(struct JournalEntry* entry); 25 | 26 | /*** 27 | * Protobuf the journal entry 28 | * @param entry the JournalEntry to protobuf 29 | * @param buffer where to place the results 30 | * @param max_buffer_size the amount of memory allocated for the buffer 31 | * @param bytes_used the amount of the buffer used 32 | * @returns true(1) on success, false(0) otherwise 33 | */ 34 | int ipfs_journal_entry_encode(struct JournalEntry* entry, uint8_t *buffer, size_t max_buffer_size, size_t *bytes_used); 35 | 36 | /*** 37 | * Turn a protobuf'd JournalEntry and turn it into a real JournalEntry 38 | * @param incoming the incoming bytes 39 | * @param incoming_size the size of the incoming buffer 40 | * @param results where to put the new JournalEntry 41 | * @returns true(1) on success, false(0) otherwise 42 | */ 43 | int ipfs_journal_entry_decode(uint8_t *incoming, size_t incoming_size, struct JournalEntry **results); 44 | -------------------------------------------------------------------------------- /test/storage/test_blocks.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/blocks/block.h" 2 | 3 | int test_blocks_new() { 4 | const unsigned char* input = (const unsigned char*)"Hello, World!"; 5 | int retVal = 0; 6 | struct Block* block = ipfs_block_new(); 7 | if (block == NULL) 8 | return 0; 9 | 10 | retVal = ipfs_blocks_block_add_data(input, strlen((const char*)input) + 1, block); 11 | if (retVal == 0) { 12 | ipfs_block_free(block); 13 | return 0; 14 | } 15 | 16 | // now examine the block 17 | if (strcmp((const char*)block->data, (const char*)input) != 0) { 18 | ipfs_block_free(block); 19 | return 0; 20 | } 21 | 22 | if (block->data_length != strlen((const char*)input) + 1) { 23 | ipfs_block_free(block); 24 | return 0; 25 | } 26 | 27 | if (block->cid->codec != CID_DAG_PROTOBUF) { 28 | ipfs_block_free(block); 29 | return 0; 30 | } 31 | 32 | if (block->cid->version != 0) { 33 | ipfs_block_free(block); 34 | return 0; 35 | } 36 | 37 | if (block->cid->hash_length != 32) { 38 | ipfs_block_free(block); 39 | return 0; 40 | } 41 | 42 | 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 }; 43 | for(int i = 0; i < 32; i++) { 44 | if (block->cid->hash[i] != result_hash[i]) { 45 | ipfs_block_free(block); 46 | return 0; 47 | } 48 | } 49 | 50 | retVal = ipfs_block_free(block); 51 | 52 | return 1; 53 | } 54 | -------------------------------------------------------------------------------- /include/ipfs/importer/importer.h: -------------------------------------------------------------------------------- 1 | #ifndef __IPFS_IMPORTER_IMPORTER_H__ 2 | #define __IPFS_IMPORTER_IMPORTER_H__ 3 | 4 | #include "ipfs/cmd/cli.h" 5 | #include "ipfs/merkledag/node.h" 6 | #include "ipfs/core/ipfs_node.h" 7 | 8 | /** 9 | * Creates a node based on an incoming file or directory 10 | * NOTE: this can be called recursively for directories 11 | * NOTE: When this function completes, parent_node will be either: 12 | * 1) the complete file, in the case of a small file (<256k-ish) 13 | * 2) a node with links to the various pieces of a large file 14 | * 3) a node with links to files and directories if 'fileName' is a directory 15 | * @param root_dir the directory for where to look for the file 16 | * @param file_name the file (or directory) to import 17 | * @param parent_node the root node (has links to others in case this is a large file and is split) 18 | * @param fs_repo the ipfs repository 19 | * @param bytes_written number of bytes written to disk 20 | * @param recursive true if we should navigate directories 21 | * @returns true(1) on success 22 | */ 23 | int ipfs_import_file(const char* root, const char* fileName, struct HashtableNode** parent_node, struct IpfsNode *local_node, size_t* bytes_written, int recursive); 24 | 25 | /** 26 | * called from the command line 27 | * @param argc the number of arguments 28 | * @param argv the arguments 29 | */ 30 | int ipfs_import_files(struct CliArguments* args); 31 | 32 | #endif /* INCLUDE_IPFS_IMPORTER_IMPORTER_H_ */ 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-std=c99 2 | DEBUG = true 3 | export DEBUG 4 | 5 | all: 6 | cd c-libp2p; make all; 7 | cd lmdb/libraries/liblmdb; make all; 8 | cd blocks; make all; 9 | cd cid; make all; 10 | cd cmd; make all; 11 | cd commands; make all; 12 | cd core; make all; 13 | cd exchange; make all; 14 | cd importer; make all; 15 | cd journal; make all; 16 | cd merkledag; make all; 17 | cd multibase; make all; 18 | cd pin; make all; 19 | cd repo; make all; 20 | cd flatfs; make all; 21 | cd datastore; make all; 22 | cd thirdparty; make all; 23 | cd unixfs; make all; 24 | cd routing; make all; 25 | cd dnslink; make all; 26 | cd namesys; make all; 27 | cd path; make all; 28 | cd util; make all; 29 | cd main; make all; 30 | cd test; make all; 31 | 32 | clean: 33 | cd c-libp2p; make clean; 34 | cd lmdb/libraries/liblmdb; make clean; 35 | cd blocks; make clean; 36 | cd cid; make clean; 37 | cd cmd; make clean; 38 | cd commands; make clean; 39 | cd core; make clean; 40 | cd exchange; make clean; 41 | cd importer; make clean; 42 | cd journal; make clean; 43 | cd merkledag; make clean; 44 | cd multibase; make clean; 45 | cd pin; make clean; 46 | cd repo; make clean; 47 | cd flatfs; make clean; 48 | cd datastore; make clean; 49 | cd thirdparty; make clean; 50 | cd unixfs; make clean; 51 | cd main; make clean; 52 | cd routing; make clean; 53 | cd dnslink; make clean; 54 | cd namesys; make clean; 55 | cd path; make clean; 56 | cd util; make clean; 57 | cd test; make clean; 58 | 59 | rebuild: clean all 60 | -------------------------------------------------------------------------------- /repo/config/swarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ipfs/repo/config/swarm.h" 6 | 7 | 8 | int repo_config_swarm_address_init(struct SwarmAddresses* swarm_addresses, char** addresses, int array_length) { 9 | // allocate memory for the addresses array 10 | swarm_addresses->addresses = malloc(sizeof(char*) * array_length); 11 | if (swarm_addresses->addresses == NULL) 12 | return 0; 13 | 14 | // copy in all the strings 15 | for(int i = 0; i < array_length; i++) { 16 | char* newString = malloc(sizeof(char) * (strlen(addresses[i]) + 1)); 17 | if (newString == NULL) 18 | return 0; 19 | strncpy(newString, addresses[i], strlen(addresses[i])); 20 | newString[strlen(addresses[i])] = 0; 21 | swarm_addresses->addresses[i] = newString; 22 | } 23 | 24 | swarm_addresses->num_addresses = array_length; 25 | 26 | return 1; 27 | } 28 | 29 | int repo_config_swarm_address_new(struct SwarmAddresses** swarm_addresses) { 30 | *swarm_addresses = (struct SwarmAddresses*)malloc(sizeof(struct SwarmAddresses)); 31 | if (*swarm_addresses == NULL) 32 | return 0; 33 | 34 | (*swarm_addresses)->num_addresses = 0; 35 | (*swarm_addresses)->addresses = NULL; 36 | return 1; 37 | } 38 | 39 | int repo_config_swarm_address_free(struct SwarmAddresses* swarm_addresses) { 40 | if (swarm_addresses->addresses != NULL) { 41 | for (int i = 0; i < swarm_addresses->num_addresses; i++) { 42 | free(swarm_addresses->addresses[i]); 43 | } 44 | free(swarm_addresses->addresses); 45 | } 46 | free(swarm_addresses); 47 | return 1; 48 | } 49 | -------------------------------------------------------------------------------- /cmd/cli.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ipfs/cmd/cli.h" 4 | 5 | int cli_is_switch(int argc, char** argv, int index) { 6 | char* to_test = argv[index]; 7 | if (to_test[0] == '-') { 8 | if (strcmp(to_test, "-c") == 0 || strcmp(to_test, "--config") == 0) { 9 | return 2; 10 | } 11 | return 1; 12 | } 13 | return 0; 14 | } 15 | 16 | 17 | int cli_get_verb_index(struct CliArguments* args) { 18 | for(int i = 1; i < args->argc; i++) { 19 | int advance_by_more_than_one = cli_is_switch(args->argc, args->argv, i); 20 | if (advance_by_more_than_one == 0) { 21 | // this is the verb 22 | return i; 23 | } else { 24 | if (advance_by_more_than_one == 2) { 25 | // skip the next one 26 | i++; 27 | } 28 | } 29 | } 30 | return 0; 31 | } 32 | 33 | char* cli_get_config_dir(struct CliArguments* args) { 34 | for (int i = 1; i < args->argc; i++) { 35 | if (args->argv[i][0] == '-') { 36 | char* param = args->argv[i]; 37 | if ((strcmp(param, "-c") == 0 || strcmp(param, "--config") == 0) && args->argc > i + 1) { 38 | return args->argv[i+1]; 39 | } 40 | } 41 | } 42 | return NULL; 43 | } 44 | 45 | 46 | struct CliArguments* cli_arguments_new(int argc, char** argv) { 47 | struct CliArguments* args = (struct CliArguments*) malloc(sizeof(struct CliArguments)); 48 | if (args != NULL) { 49 | args->argc = argc; 50 | args->argv = argv; 51 | args->verb_index = cli_get_verb_index(args); 52 | args->config_dir = cli_get_config_dir(args); 53 | } 54 | return args; 55 | } 56 | 57 | void cli_arguments_free(struct CliArguments* args) { 58 | free(args); 59 | } 60 | -------------------------------------------------------------------------------- /main/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -g3 -Wall -std=c11 3 | LFLAGS = -L../c-libp2p -L../c-libp2p/c-multihash -L../c-libp2p/c-multiaddr -lp2p -lm -lmultihash -lmultiaddr -lpthread -lresolv -lcurl 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 = main.o \ 6 | ../blocks/block.o ../blocks/blockstore.o \ 7 | ../cid/cid.o \ 8 | ../cmd/ipfs/init.o \ 9 | ../cmd/*.o \ 10 | ../commands/argument.o ../commands/command_option.o ../commands/command.o ../commands/cli/parse.o \ 11 | ../core/*.o \ 12 | ../datastore/ds_helper.o \ 13 | ../datastore/key.o \ 14 | ../dnslink/*.o \ 15 | ../exchange/bitswap/*.o \ 16 | ../flatfs/flatfs.o \ 17 | ../importer/importer.o ../importer/exporter.o ../importer/resolver.o \ 18 | ../journal/*.o \ 19 | ../path/path.o \ 20 | ../merkledag/merkledag.o ../merkledag/node.o \ 21 | ../multibase/multibase.o \ 22 | ../namesys/*.o \ 23 | ../pin/pin.o \ 24 | ../repo/init.o \ 25 | ../repo/fsrepo/*.o \ 26 | ../repo/config/*.o \ 27 | ../routing/*.o \ 28 | ../thirdparty/ipfsaddr/ipfs_addr.o \ 29 | ../unixfs/unixfs.o \ 30 | ../c-libp2p/c-protobuf/protobuf.o ../c-libp2p/c-protobuf/varint.o \ 31 | ../util/errs.o \ 32 | ../util/time.o \ 33 | ../util/thread_pool.o 34 | 35 | %.o: %.c $(DEPS) 36 | $(CC) -c -o $@ $< $(CFLAGS) 37 | 38 | ipfs: $(OBJS) 39 | $(CC) -o $@ $^ $(LFLAGS) ../lmdb/libraries/liblmdb/liblmdb.a 40 | 41 | all: ipfs 42 | 43 | clean: 44 | rm -f *.o 45 | rm -f ipfs 46 | -------------------------------------------------------------------------------- /include/ipfs/exchange/bitswap/want_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/blocks/block.h" 4 | #include "ipfs/cid/cid.h" 5 | #include "ipfs/exchange/bitswap/bitswap.h" 6 | #include "wantlist_queue.h" 7 | 8 | /*** 9 | * Add a Cid to the local wantlist 10 | * @param context the context 11 | * @param cid the Cid 12 | * @returns the added WantListQueueEntry 13 | */ 14 | struct WantListQueueEntry* ipfs_bitswap_want_manager_add(const struct BitswapContext* context, const struct Cid* cid, const struct WantListSession* session); 15 | 16 | /*** 17 | * Checks to see if the requested block has been received 18 | * @param context the context 19 | * @param cid the Cid 20 | * @returns true(1) if it has been received, false(0) otherwise 21 | */ 22 | int ipfs_bitswap_want_manager_received(const struct BitswapContext* context, const struct Cid* cid); 23 | 24 | /*** 25 | * retrieve a block from the WantManager. 26 | * @param context the context 27 | * @param cid the Cid to get 28 | * @param block a pointer to the block that will be allocated 29 | * @returns true(1) on success, false(0) otherwise 30 | */ 31 | int ipfs_bitswap_want_manager_get_block(const struct BitswapContext* context, const struct Cid* cid, struct Block** block); 32 | 33 | /*** 34 | * We no longer are requesting this block, so remove it from the queue 35 | * NOTE: This is reference counted, as another process may have asked for it. 36 | * @param context the context 37 | * @param cid the Cid 38 | * @returns true(1) on success, false(0) otherwise. 39 | */ 40 | int ipfs_bitswap_want_manager_remove(const struct BitswapContext* context, const struct Cid* cid); 41 | -------------------------------------------------------------------------------- /include/ipfs/journal/journal_message.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "libp2p/utils/vector.h" 7 | 8 | struct JournalMessage { 9 | unsigned long long current_epoch; 10 | unsigned long long start_epoch; 11 | unsigned long long end_epoch; 12 | struct Libp2pVector* journal_entries; 13 | }; 14 | 15 | struct JournalMessage* ipfs_journal_message_new(); 16 | int ipfs_journal_message_free(struct JournalMessage* message); 17 | 18 | /** 19 | * Determine the maximum size of a protobuf'd JournalMessage 20 | * @param message the JournalMessage 21 | * @returns the maximum size of this message in bytes if it were protobuf'd 22 | */ 23 | int ipfs_journal_message_encode_size(struct JournalMessage* message); 24 | 25 | /*** 26 | * Protobuf the journal message 27 | * @param message the JournalMessage to protobuf 28 | * @param buffer where to place the results 29 | * @param max_buffer_size the amount of memory allocated for the buffer 30 | * @param bytes_used the amount of the buffer used 31 | * @returns true(1) on success, false(0) otherwise 32 | */ 33 | int ipfs_journal_message_encode(struct JournalMessage* entry, uint8_t *buffer, size_t max_buffer_size, size_t *bytes_used); 34 | 35 | /*** 36 | * Turn a protobuf'd JournalMessage and turn it into a real JournalMessage 37 | * @param incoming the incoming bytes 38 | * @param incoming_size the size of the incoming buffer 39 | * @param results where to put the new JournalMessage 40 | * @returns true(1) on success, false(0) otherwise 41 | */ 42 | int ipfs_journal_message_decode(const uint8_t *incoming, size_t incoming_size, struct JournalMessage **results); 43 | -------------------------------------------------------------------------------- /core/client_api.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ipfs/core/client_api.h" 12 | #include "multiaddr/multiaddr.h" 13 | 14 | /** 15 | * Determine if the API is running (by attempting to connect to the port) 16 | * @param local_node the context 17 | * @returns true(1) on success, false(0) otherwise 18 | */ 19 | int api_running(struct IpfsNode* local_node) { 20 | struct MultiAddress* my_multiaddress = multiaddress_new_from_string(local_node->repo->config->addresses->api); 21 | char* ip = NULL; 22 | int portno = 0; 23 | 24 | if (my_multiaddress == NULL) { 25 | return 0; 26 | } 27 | 28 | portno = multiaddress_get_ip_port(my_multiaddress); 29 | multiaddress_get_ip_address(my_multiaddress, &ip); 30 | 31 | multiaddress_free(my_multiaddress); 32 | 33 | if (ip == NULL) 34 | return 0; 35 | 36 | int sockfd; 37 | struct sockaddr_in serv_addr; 38 | struct hostent *server; 39 | 40 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 41 | if (sockfd < 0) { 42 | free(ip); 43 | return 0; 44 | } 45 | 46 | server = gethostbyname(ip); 47 | free(ip); 48 | 49 | if (server == NULL) { 50 | return 0; 51 | } 52 | 53 | memset(&serv_addr, 0, sizeof(struct sockaddr_in)); 54 | serv_addr.sin_family = AF_INET; 55 | memmove(&serv_addr.sin_addr.s_addr, server->h_addr_list[0], server->h_length); 56 | serv_addr.sin_port = htons(portno); 57 | int retVal = connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)); 58 | close(sockfd); 59 | return retVal >= 0; 60 | } 61 | -------------------------------------------------------------------------------- /include/ipfs/merkledag/merkledag.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * Merkledag methods 3 | */ 4 | #ifndef __IPFS_MERKLEDAG_H__ 5 | #define __IPFS_MERKLEDAG_H__ 6 | 7 | #include "ipfs/merkledag/node.h" 8 | #include "ipfs/repo/fsrepo/fs_repo.h" 9 | 10 | /*** 11 | * Adds a node to the dagService and blockService 12 | * @param node the node to add 13 | * @param fs_repo the repo to add to 14 | * @param bytes_written the number of bytes written 15 | * @returns true(1) on success 16 | */ 17 | int ipfs_merkledag_add(struct HashtableNode* node, struct FSRepo* fs_repo, size_t* bytes_written); 18 | 19 | /*** 20 | * Retrieves a node from the datastore based on the cid 21 | * @param cid the key to look for 22 | * @param node the node to be created 23 | * @param fs_repo the repository 24 | * @returns true(1) on success 25 | */ 26 | int ipfs_merkledag_get(const unsigned char* hash, size_t hash_size, struct HashtableNode** node, const struct FSRepo* fs_repo); 27 | 28 | /*** 29 | * Retrieves a node from the datastore based on the multihash 30 | * @param multihash the base58 encoded multihash (should start with Qm) as a null terminated string 31 | * @param node the node to be created 32 | * @param fs_repo the repository 33 | * @returns true(1) on success 34 | */ 35 | int ipfs_merkledag_get_by_multihash(const unsigned char* multihash, size_t multihash_length, struct HashtableNode** node, const struct FSRepo* fs_repo); 36 | 37 | /*** 38 | * Convert the data within a block to a HashtableNode 39 | * @param block the block 40 | * @param node_ptr where to put the results 41 | * @returns true(1) on success, false(0) otherwise 42 | */ 43 | int ipfs_merkledag_convert_block_to_node(struct Block* block, struct HashtableNode** node_ptr); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O0 -I../include -I../c-libp2p/include -I../c-libp2p/c-multihash/include -I../c-libp2p/c-multiaddr/include -I../c-libp2p/c-protobuf -I../lmdb/libraries/liblmdb -g3 -Wall -std=c11 3 | LFLAGS = -L../c-libp2p -L../c-libp2p/c-multihash -L../c-libp2p/c-multiaddr -lp2p -lm -lmultihash -lmultiaddr -lpthread -lcurl 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 test_helper.o \ 6 | ../blocks/block.o ../blocks/blockstore.o \ 7 | ../cid/cid.o \ 8 | ../cmd/cli.o \ 9 | ../cmd/ipfs/init.o \ 10 | ../commands/argument.o ../commands/command_option.o ../commands/command.o ../commands/cli/parse.o \ 11 | ../core/*.o \ 12 | ../datastore/ds_helper.o \ 13 | ../exchange/bitswap/*.o \ 14 | ../flatfs/flatfs.o \ 15 | ../importer/importer.o ../importer/exporter.o ../importer/resolver.o \ 16 | ../journal/*.o \ 17 | ../merkledag/merkledag.o ../merkledag/node.o \ 18 | ../multibase/multibase.o \ 19 | ../namesys/pb.o \ 20 | ../namesys/publisher.o \ 21 | ../namesys/resolver.o \ 22 | ../namesys/name.o \ 23 | ../repo/init.o \ 24 | ../repo/fsrepo/*.o \ 25 | ../repo/config/*.o \ 26 | ../routing/offline.o \ 27 | ../routing/online.o \ 28 | ../routing/k_routing.o \ 29 | ../routing/supernode.o \ 30 | ../thirdparty/ipfsaddr/ipfs_addr.o \ 31 | ../unixfs/unixfs.o \ 32 | ../util/thread_pool.o \ 33 | ../c-libp2p/c-protobuf/protobuf.o ../c-libp2p/c-protobuf/varint.o 34 | 35 | %.o: %.c $(DEPS) 36 | $(CC) -c -o $@ $< $(CFLAGS) 37 | 38 | test_ipfs: $(OBJS) 39 | $(CC) -o $@ $^ $(LFLAGS) ../lmdb/libraries/liblmdb/liblmdb.a 40 | 41 | all: test_ipfs 42 | 43 | clean: 44 | rm -f *.o 45 | rm -f test_ipfs 46 | 47 | rebuild: clean all 48 | -------------------------------------------------------------------------------- /include/ipfs/datastore/ds_helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Some code to help with the datastore / blockstore interface 5 | */ 6 | 7 | #include 8 | #include "ipfs/blocks/block.h" 9 | #include "libp2p/db/datastore.h" 10 | 11 | /** 12 | * Generate a key based on the passed in binary_array 13 | * @param binary_array what to base the key on 14 | * @param array_length the size of the binary array 15 | * @param results where the key will be put 16 | * @param max_results_length the size of the results buffer 17 | * @param results_length the length of the generated key 18 | * @returns true(1) on success 19 | */ 20 | int ipfs_datastore_helper_ds_key_from_binary(const unsigned char* binary_array, size_t array_length, 21 | unsigned char* results, size_t max_results_length, size_t* results_length); 22 | 23 | /** 24 | * Generate a binary array based on the passed in datastore key 25 | * @param ds_key the base32 encoded key 26 | * @param key_length the length of the base32 "string" 27 | * @param binary_array where to put the decoded value 28 | * @param max_binary_array_length the memory size of binary_array 29 | * @param completed_binary_array_length the length of what was written to the binary_array 30 | * @returns true(1) on success 31 | */ 32 | int ipfs_datastore_helper_binary_from_ds_key(const unsigned char* ds_key, size_t key_length, unsigned char* binary_array, 33 | size_t max_binary_array_length, size_t* completed_binary_array_length); 34 | 35 | /*** 36 | * Add a record in the datastore based on a block 37 | * @param block the block 38 | * @param datastore the Datastore 39 | * @reutrns true(1) on success, false(0) otherwise 40 | */ 41 | int ipfs_datastore_helper_add_block_to_datastore(struct Block* block, struct Datastore* datastore); 42 | -------------------------------------------------------------------------------- /include/ipfs/namesys/routing.h: -------------------------------------------------------------------------------- 1 | #ifndef IPNS_NAMESYS_ROUTING_H 2 | #define IPNS_NAMESYS_ROUTING_H 3 | 4 | #include "mh/multihash.h" 5 | #include "ipfs/util/time.h" 6 | #include "ipfs/namesys/pb.h" 7 | 8 | #define DefaultResolverCacheTTL 60 // a minute 9 | 10 | struct cacheEntry { 11 | char *key; 12 | char *value; 13 | struct timespec eol; 14 | }; 15 | 16 | struct routingResolver { 17 | int cachesize; 18 | int next; 19 | struct cacheEntry **data; 20 | }; 21 | 22 | struct libp2p_routing_value_store { // dummy declaration, not implemented yet. 23 | void *missing; 24 | }; 25 | 26 | char* ipfs_routing_cache_get (char *key, struct ipns_entry *ientry); 27 | void ipfs_routing_cache_set (char *key, char *value, struct ipns_entry *ientry); 28 | struct routingResolver* ipfs_namesys_new_routing_resolver (struct libp2p_routing_value_store *route, int cachesize); 29 | // ipfs_namesys_routing_resolve implements Resolver. 30 | int ipfs_namesys_routing_resolve (char **path, char *name, struct namesys_pb *pb); 31 | // ipfs_namesys_routing_resolve_n implements Resolver. 32 | int ipfs_namesys_routing_resolve_n (char **path, char *name, int depth, struct namesys_pb *pb); 33 | // ipfs_namesys_routing_resolve_once implements resolver. Uses the IPFS 34 | // routing system to resolve SFS-like names. 35 | int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char *prefix, struct namesys_pb *pb); 36 | int ipfs_namesys_routing_check_EOL (struct timespec *ts, struct namesys_pb *pb); 37 | 38 | int ipfs_namesys_routing_get_value (char*, char*); 39 | int ipfs_namesys_routing_getpublic_key (char*, unsigned char* multihash, size_t multihash_size); 40 | #endif // IPNS_NAMESYS_ROUTING_H 41 | -------------------------------------------------------------------------------- /include/ipfs/journal/journal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "libp2p/conn/session.h" 6 | #include "ipfs/core/ipfs_node.h" 7 | #include "libp2p/net/protocol.h" 8 | 9 | /** 10 | * The journal protocol attempts to keep a journal in sync with other (approved) nodes 11 | */ 12 | 13 | /*** 14 | * See if we can handle this message 15 | * @param incoming the incoming message 16 | * @param incoming_size the size of the incoming message 17 | * @returns true(1) if the protocol in incoming is something we can handle. False(0) otherwise. 18 | */ 19 | int ipfs_journal_can_handle(const struct StreamMessage* msg); 20 | 21 | /** 22 | * Clean up resources used by this handler 23 | * @param context the context to clean up 24 | * @returns true(1) 25 | */ 26 | int ipfs_journal_shutdown_handler(void* context); 27 | 28 | /*** 29 | * Handles a message 30 | * @param incoming the message 31 | * @param incoming_size the size of the message 32 | * @param session_context details of the remote peer 33 | * @param protocol_context in this case, an IpfsNode 34 | * @returns 0 if the caller should not continue looping, <0 on error, >0 on success 35 | */ 36 | int ipfs_journal_handle_message(const struct StreamMessage* msg, struct Stream* stream, void* protocol_context) ; 37 | 38 | /*** 39 | * Build the protocol handler struct for the Journal protocol 40 | * @param local_node what to stuff in the context 41 | * @returns the protocol handler 42 | */ 43 | struct Libp2pProtocolHandler* ipfs_journal_build_protocol_handler(const struct IpfsNode* local_node); 44 | 45 | /*** 46 | * Send a journal message to a remote peer 47 | * @param replication_peer the peer to send it to 48 | * @returns true(1) on success, false(0) otherwise. 49 | */ 50 | int ipfs_journal_sync(struct IpfsNode* local_node, struct ReplicationPeer* replication_peer); 51 | -------------------------------------------------------------------------------- /repo/config/bootstrap_peers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ipfs/repo/config/bootstrap_peers.h" 5 | #include "multiaddr/multiaddr.h" 6 | 7 | int repo_config_bootstrap_peers_retrieve(struct Libp2pVector** list) { 8 | 9 | /* 10 | char* default_bootstrap_addresses[] = { 11 | "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io 12 | "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune.i.ipfs.io 13 | "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io 14 | "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus.i.ipfs.io 15 | "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io 16 | "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io 17 | "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io 18 | "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury.i.ipfs.io 19 | "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter.i.ipfs.io 20 | }; 21 | */ 22 | *list = libp2p_utils_vector_new(1); 23 | 24 | /* 25 | for(int i = 0; i < 9; i++) { 26 | struct MultiAddress* currAddr = multiaddress_new_from_string(default_bootstrap_addresses[i]); 27 | libp2p_utils_vector_add(*list, currAddr); 28 | } 29 | */ 30 | return 1; 31 | } 32 | 33 | int repo_config_bootstrap_peers_free(struct Libp2pVector* list) { 34 | if (list != NULL) { 35 | for(int i = 0; i < list->total; i++) { 36 | struct MultiAddress* currAddr = (struct MultiAddress*)libp2p_utils_vector_get(list, i); 37 | multiaddress_free(currAddr); 38 | } 39 | libp2p_utils_vector_free(list); 40 | } 41 | return 1; 42 | } 43 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/core/test_compat_go.h: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | #include "libp2p/utils/logger.h" 4 | #include "ipfs/core/daemon.h" 5 | #include "ipfs/core/swarm.h" 6 | 7 | // forward declarations 8 | int ipfs_swarm_connect(struct IpfsNode* local_node, const char* address); 9 | 10 | 11 | int test_compat_go_join_swarm() { 12 | int retVal = 0; 13 | char* ipfs_path1 = "/tmp/ipfs_1"; 14 | char* config_file1 = "config.test1.wo_journal"; 15 | pthread_t daemon_thread; 16 | struct FSRepo* fs_repo = NULL; 17 | 18 | /* 19 | libp2p_logger_add_class("test_api"); 20 | libp2p_logger_add_class("identify"); 21 | libp2p_logger_add_class("null"); 22 | libp2p_logger_add_class("swarm"); 23 | libp2p_logger_add_class("secio"); 24 | */ 25 | libp2p_logger_add_class("dialer"); 26 | libp2p_logger_add_class("yamux"); 27 | libp2p_logger_add_class("multistream"); 28 | libp2p_logger_add_class("threadsafe_buffer"); 29 | 30 | // Here is the connection information for the GO version: 31 | char* remote_string = "/ip4/10.211.55.2/tcp/4001/ipfs/QmacSE6bCZiAu7nrYkhPATaSoL2q9BszkKzbX6fCiXuBGA"; 32 | 33 | // build repo 34 | if (!drop_build_open_repo(ipfs_path1, &fs_repo, config_file1)) { 35 | ipfs_repo_fsrepo_free(fs_repo); 36 | libp2p_logger_error("test_api", "Unable to drop and build repository at %s\n", ipfs_path1); 37 | goto exit; 38 | } 39 | ipfs_repo_fsrepo_free(fs_repo); 40 | // start daemon 41 | pthread_create(&daemon_thread, NULL, test_daemon_start, (void*)ipfs_path1); 42 | sleep(3); 43 | 44 | // try to connect to a remote swarm 45 | struct IpfsNode *local_node = NULL; 46 | ipfs_node_offline_new(ipfs_path1, &local_node); 47 | if (!ipfs_swarm_connect(local_node, remote_string)) { 48 | libp2p_logger_error("test_api", "Unable to do swarm connect.\n"); 49 | goto exit; 50 | } 51 | 52 | // see what the remote will do 53 | sleep(20); 54 | 55 | retVal = 1; 56 | exit: 57 | ipfs_daemon_stop(); 58 | pthread_join(daemon_thread, NULL); 59 | return retVal; 60 | } 61 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: gcc 3 | dist: trusty 4 | 5 | before_install: 6 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 7 | - sudo apt-get update 8 | 9 | install: 10 | - sudo apt-get -y install make gcc libcurl4-gnutls-dev gcc-7 11 | 12 | script: 13 | - git submodule update --init --recursive 14 | - export CC=gcc-7 15 | - make all 16 | - mkdir -p appdir/usr/bin ; cp ./main/ipfs appdir/usr/bin/ 17 | - mkdir -p appdir/usr/share/applications ; cp ipfs.desktop appdir/usr/share/applications/ 18 | - mkdir -p appdir/usr/share/icons/hicolor/512x512/apps ; wget -c "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Ipfs-logo-1024-ice-text.png/512px-Ipfs-logo-1024-ice-text.png" -O appdir/usr/share/icons/512x512/scalable/apps/ipfs.png 19 | - export LD_LIBRARY_PATH=./c-libp2p/:$LD_LIBRARY_PATH 20 | - export VERSION=$(git rev-parse --short HEAD) # linuxdeployqt uses this for naming the file 21 | # mkdir -p appdir/usr/optional/ ; wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so -O ./appdir/usr/optional/exec.so 22 | # mkdir -p appdir/usr/optional/libstdc++/ ; cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./appdir/usr/optional/libstdc++/ 23 | # ( cd appdir ; rm AppRun ; wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun ; chmod a+x AppRun) 24 | - ./linuxdeployqt-continuous-x86_64.AppImage appdir/usr/share/applications/*.desktop -appimage 25 | 26 | after_success: 27 | - find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq 28 | - # curl --upload-file c-ipfs*.AppImage https://transfer.sh/c-ipfs-git.$(git rev-parse --short HEAD)-x86_64.AppImage 29 | - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh 30 | - bash upload.sh c-ipfs*.AppImage* 31 | 32 | branches: 33 | except: 34 | - # Do not build tags that we create when we upload to GitHub Releases 35 | - /^(?i:continuous)/ 36 | -------------------------------------------------------------------------------- /test/repo/test_repo_bootstrap_peers.h: -------------------------------------------------------------------------------- 1 | #ifndef test_repo_bootstrap_peers_h 2 | #define test_repo_bootstrap_peers_h 3 | 4 | //#include 5 | 6 | #include "ipfs/repo/config/bootstrap_peers.h" 7 | 8 | int test_repo_bootstrap_peers_init() { 9 | 10 | char* default_bootstrap_addresses[] = { 11 | "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io 12 | "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune.i.ipfs.io 13 | "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io 14 | "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus.i.ipfs.io 15 | "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io 16 | "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io 17 | "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io 18 | "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury.i.ipfs.io 19 | "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter.i.ipfs.io 20 | }; 21 | 22 | struct Libp2pVector* list; 23 | int retVal = 1; 24 | repo_config_bootstrap_peers_retrieve(&list); 25 | /* 26 | if ( list->total != 9) { 27 | printf("Size does not equal 9 in test_repo_bootstrap_peers_init\n"); 28 | retVal = 0; 29 | } 30 | */ 31 | for(int i = 0; i < list->total; i++) { 32 | unsigned long strLen = strlen(default_bootstrap_addresses[i]); 33 | struct MultiAddress* currAddr = (struct MultiAddress*)libp2p_utils_vector_get(list, i); 34 | if (strncmp(currAddr->string, default_bootstrap_addresses[i], strLen) != 0) 35 | printf("The value of element %d is: %s\n", i, currAddr->string); 36 | } 37 | repo_config_bootstrap_peers_free(list); 38 | return retVal; 39 | } 40 | 41 | #endif /* test_repo_bootstrap_peers_h */ 42 | -------------------------------------------------------------------------------- /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/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 | char *jsmn_simple_parser(char *full_json, int json_len, char *key); 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* __JSMN_H_ */ 78 | -------------------------------------------------------------------------------- /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/blocks/block.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * IPFS has the notion of storage blocks. 3 | * Raw data with a multihash key (the Cid) 4 | */ 5 | 6 | #ifndef __IPFS_BLOCKS_BLOCK_H__ 7 | #define __IPFS_BLOCKS_BLOCK_H__ 8 | 9 | #include "ipfs/cid/cid.h" 10 | 11 | struct Block { 12 | struct Cid* cid; 13 | unsigned char* data; 14 | size_t data_length; 15 | }; 16 | 17 | /*** 18 | * Create a new block 19 | * @returns a new allocated Block struct 20 | */ 21 | struct Block* ipfs_block_new(); 22 | 23 | int ipfs_blocks_block_add_data(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_block_free(struct Block* block); 31 | 32 | /** 33 | * Determine the approximate size of an encoded block 34 | * @param block the block to measure 35 | * @returns the approximate size needed to encode the protobuf 36 | */ 37 | size_t ipfs_blocks_block_protobuf_encode_size(const struct Block* block); 38 | 39 | /** 40 | * Encode the Block into protobuf format 41 | * @param block the block to encode 42 | * @param buffer the buffer to fill 43 | * @param max_buffer_size the max size of the buffer 44 | * @param bytes_written the number of bytes used 45 | * @returns true(1) on success 46 | */ 47 | int ipfs_blocks_block_protobuf_encode(const struct Block* block, unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written); 48 | 49 | /*** 50 | * Decode from a protobuf stream into a Block struct 51 | * @param buffer the buffer to pull from 52 | * @param buffer_length the length of the buffer 53 | * @param block the block to fill 54 | * @returns true(1) on success 55 | */ 56 | int ipfs_blocks_block_protobuf_decode(const unsigned char* buffer, const size_t buffer_length, struct Block** block); 57 | 58 | /*** 59 | * Make a copy of a block 60 | * @param original the original 61 | * @returns a new Block that is a copy 62 | */ 63 | struct Block* ipfs_block_copy(struct Block* original); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /include/ipfs/core/ipfs_node.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "libp2p/peer/peerstore.h" 5 | #include "libp2p/peer/providerstore.h" 6 | #include "libp2p/swarm/swarm.h" 7 | #include "ipfs/blocks/blockstore.h" 8 | #include "ipfs/exchange/exchange.h" 9 | #include "ipfs/repo/config/identity.h" 10 | #include "ipfs/repo/fsrepo/fs_repo.h" 11 | #include "ipfs/routing/routing.h" 12 | 13 | /*** 14 | * Holds information about the local node 15 | */ 16 | 17 | /*** 18 | * Modes: 19 | * MODE_OFFLINE: Do everything yourself 20 | * MODE_API_AVAILABLE: If you want to, the API is running 21 | * MODE_ONLINE: You are the API 22 | */ 23 | enum NodeMode { MODE_OFFLINE, MODE_API_AVAILABLE, MODE_ONLINE }; 24 | 25 | struct IpfsNode { 26 | /*** 27 | * Modes: 28 | * MODE_OFFLINE: Do everything yourself 29 | * MODE_API_AVAILABLE: If you want to, the API is running 30 | * MODE_ONLINE: You are the API 31 | */ 32 | enum NodeMode mode; 33 | struct Identity* identity; 34 | struct FSRepo* repo; 35 | struct Peerstore* peerstore; 36 | struct ProviderStore* providerstore; 37 | struct IpfsRouting* routing; 38 | struct Blockstore* blockstore; 39 | struct Exchange* exchange; 40 | struct Libp2pVector* protocol_handlers; 41 | struct ApiContext* api_context; 42 | struct Dialer* dialer; 43 | struct SwarmContext* swarm; 44 | //struct Pinner pinning; // an interface 45 | //struct Mount** mounts; 46 | // TODO: Add more here 47 | }; 48 | 49 | /*** 50 | * build an online IpfsNode 51 | * @param repo_path where the IPFS repository directory is 52 | * @param node the completed IpfsNode struct 53 | * @returns true(1) on success 54 | */ 55 | int ipfs_node_online_new(const char* repo_path, struct IpfsNode** node); 56 | 57 | /*** 58 | * build an offline IpfsNode 59 | * @param repo_path where the IPFS repository directory is 60 | * @param node the completed IpfsNode struct 61 | * @returns true(1) on success 62 | */ 63 | int ipfs_node_offline_new(const char* repo_path, struct IpfsNode** node); 64 | 65 | /*** 66 | * Free resources from the creation of an IpfsNode 67 | * @param node the node to free 68 | * @returns true(1) 69 | */ 70 | int ipfs_node_free(struct IpfsNode* node); 71 | -------------------------------------------------------------------------------- /test/test_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Helpers for testing 3 | */ 4 | 5 | /*** 6 | * Drop a repository by deleting the directory 7 | * @param path the path of the repository 8 | * @returns true(1) on success, false(0) otherwise 9 | */ 10 | int drop_repository(const char* path); 11 | 12 | /** 13 | * Create a new repository in the directory, erasing old one 14 | * NOTE: base directory must already exist 15 | */ 16 | int drop_and_build_repository(const char* dir, int swarm_port, struct Libp2pVector* bootstrap_peers, char** peer_id); 17 | 18 | /*** 19 | * Drop a repository and build a new one 20 | * @param path where to create it 21 | * @param fs_repo the results 22 | * @returns true(1) on success, otherwise false(0) 23 | */ 24 | int drop_build_and_open_repo(const char* path, struct FSRepo** fs_repo); 25 | 26 | /*** 27 | * Drop a repository and build a new one with the specified config file 28 | * @param path where to create it 29 | * @param fs_repo the results 30 | * @param config_file_to_copy where to find the config file to copy 31 | * @returns true(1) on success, otherwise false(0) 32 | */ 33 | int drop_build_open_repo(const char* path, struct FSRepo** fs_repo, const char* config_file_to_copy); 34 | 35 | /*** 36 | * Helper to create a test file in the OS 37 | * @pram fileName the resultant file name 38 | * @param bytes the data that goes in the file 39 | * @param num_bytes the size of the buffer 40 | */ 41 | int create_file(const char* fileName, unsigned char* bytes, size_t num_bytes); 42 | 43 | /*** 44 | * Create a buffer with some bytes 45 | * @param buffer where to put the bytes 46 | * @param num_bytes how much to fill of the buffer 47 | */ 48 | int create_bytes(unsigned char* buffer, size_t num_bytes); 49 | 50 | /*** 51 | * Start a daemon (usefull in a separate thread) 52 | * @param arg a char string of the repo path 53 | * @returns NULL 54 | */ 55 | void* test_daemon_start(void* arg); 56 | 57 | /** 58 | * Determine if a file exists in the blockstore 59 | * @param dir the directory of the blockstore 60 | * @param filename the file name (a base32 hash) 61 | * @returns true(1) if the file exists, false(0) otherwise 62 | */ 63 | int have_file_in_blockstore(const char* dir, const char* filename); 64 | -------------------------------------------------------------------------------- /include/ipfs/importer/exporter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/cmd/cli.h" 4 | #include "ipfs/core/ipfs_node.h" 5 | 6 | /** 7 | * Pull bytes from the hashtable 8 | */ 9 | 10 | /** 11 | * get a file by its hash, and write the data to a file 12 | * @param hash the base58 multihash of the cid 13 | * @param file_name the file name to write to 14 | * @returns true(1) on success 15 | */ 16 | int ipfs_exporter_to_file(const unsigned char* hash, const char* file_name, struct IpfsNode* local_node); 17 | 18 | /*** 19 | * Retrieve a protobuf'd Node from the router 20 | * @param local_node the context 21 | * @param hash the hash to retrieve 22 | * @param hash_size the length of the hash 23 | * @param result a place to store the Node 24 | * @returns true(1) on success, otherwise false(0) 25 | */ 26 | int ipfs_exporter_get_node(struct IpfsNode* local_node, const unsigned char* hash, const size_t hash_size, struct HashtableNode** result); 27 | 28 | int ipfs_exporter_object_get(int argc, char** argv); 29 | 30 | /*** 31 | * Called from the command line with ipfs cat [hash]. Retrieves the object pointed to by hash, and displays its block data (links and data elements) 32 | * @param argc number of arguments 33 | * @param argv arguments 34 | * @param output_file where to stream the results 35 | * @returns true(1) on success 36 | */ 37 | int ipfs_exporter_object_cat(struct CliArguments* args, FILE* output_file); 38 | 39 | /** 40 | * Retrieves the object pointed to by hash and displays the raw data 41 | * @param local_node the local node 42 | * @param hash the hash to use 43 | * @param hash_size the length of the hash 44 | * @param file the file descrptor to write to 45 | * @returns true(1) on success, false(0) otherwise 46 | */ 47 | int ipfs_exporter_object_cat_to_file(struct IpfsNode *local_node, unsigned char* hash, int hash_size, FILE* file); 48 | 49 | /** 50 | * rebuild a file based on this HashtableNode, traversing links 51 | * @param node the HashtableNode to start with 52 | * @param local_node the context 53 | * @param file the filestream to fill 54 | * @returns true(1) on success, false(0) otherwise 55 | */ 56 | int ipfs_exporter_cat_node(struct HashtableNode* node, struct IpfsNode* local_node, FILE *file); 57 | -------------------------------------------------------------------------------- /test/exchange/test_bitswap_request_queue.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ipfs/exchange/bitswap/peer_request_queue.h" 3 | 4 | /*** 5 | * Create a queue, do some work, free the queue, make sure valgrind likes it. 6 | */ 7 | int test_bitswap_peer_request_queue_new() { 8 | int retVal = 0; 9 | struct PeerRequestQueue* queue = NULL; 10 | struct PeerRequest* request = NULL; 11 | 12 | // create a queue 13 | queue = ipfs_bitswap_peer_request_queue_new(); 14 | if (queue == NULL) 15 | goto exit; 16 | 17 | // add a request 18 | request = ipfs_bitswap_peer_request_new(); 19 | if (request == NULL) 20 | goto exit; 21 | ipfs_bitswap_peer_request_queue_add(queue, request); 22 | 23 | retVal = 1; 24 | exit: 25 | // clean up 26 | ipfs_bitswap_peer_request_queue_free(queue); 27 | return retVal; 28 | } 29 | 30 | int test_bitswap_peer_request_queue_find() { 31 | return 0; 32 | /* 33 | int retVal = 0; 34 | struct PeerRequestQueue* queue = NULL; 35 | struct PeerRequest* request1 = NULL; 36 | struct PeerRequest* request2 = NULL; 37 | struct PeerRequestEntry* foundRequestEntry = NULL; 38 | 39 | // create a queue 40 | queue = ipfs_bitswap_peer_request_queue_new(); 41 | if (queue == NULL) 42 | goto exit; 43 | 44 | // add a request 45 | request1 = ipfs_bitswap_peer_request_new(); 46 | if (request1 == NULL) 47 | goto exit; 48 | request1->peer_id = 1; 49 | ipfs_bitswap_peer_request_queue_add(queue, request1); 50 | 51 | // add a second request 52 | request2 = ipfs_bitswap_peer_request_new(); 53 | if (request2 == NULL) 54 | goto exit; 55 | request2->peer_id = 2; 56 | ipfs_bitswap_peer_request_queue_add(queue, request2); 57 | 58 | // find the first 59 | foundRequestEntry = ipfs_bitswap_peer_request_queue_find_entry(queue, request1); 60 | if (foundRequestEntry == NULL) 61 | goto exit; 62 | if (foundRequestEntry->current->peer_id != 1) 63 | goto exit; 64 | 65 | // find the second 66 | foundRequestEntry = ipfs_bitswap_peer_request_queue_find_entry(queue, request2); 67 | if (foundRequestEntry == NULL) 68 | goto exit; 69 | if (foundRequestEntry->current->peer_id != 2) 70 | goto exit; 71 | 72 | retVal = 1; 73 | exit: 74 | // clean up 75 | ipfs_bitswap_peer_request_queue_free(queue); 76 | return retVal; 77 | */ 78 | } 79 | -------------------------------------------------------------------------------- /repo/config/gateway.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ipfs/repo/config/gateway.h" 6 | 7 | char* alloc_and_fill(char* source) { 8 | char* newString = malloc(sizeof(char) * (strlen(source) + 1)); 9 | if (newString != NULL) { 10 | strncpy(newString, source, strlen(source)); 11 | newString[strlen(source)] = 0; 12 | } 13 | return newString; 14 | } 15 | 16 | int repo_config_gateway_http_header_init(struct HTTPHeaders* http_headers, char** headers, char** values, int num_elements) { 17 | // allocate memory for array 18 | http_headers->headers = malloc(sizeof(struct HTTPHeader*) * num_elements); 19 | if (http_headers->headers == NULL) { 20 | http_headers->num_elements = 0; 21 | return 0; 22 | } 23 | 24 | // now fill in the array 25 | for(int i = 0; i < num_elements; i++) { 26 | http_headers->headers[i] = malloc(sizeof(struct HTTPHeader)); 27 | if (http_headers->headers[i] == NULL) { 28 | http_headers->num_elements = i; 29 | return 0; 30 | } 31 | http_headers->headers[i]->header = alloc_and_fill(headers[i]); 32 | http_headers->headers[i]->value = alloc_and_fill(values[i]); 33 | } 34 | 35 | http_headers->num_elements = num_elements; 36 | return 1; 37 | } 38 | 39 | int repo_config_gateway_new(struct Gateway** gateway) { 40 | *gateway = (struct Gateway*)malloc(sizeof(struct Gateway)); 41 | if (*gateway == NULL) 42 | return 0; 43 | (*gateway)->http_headers = (struct HTTPHeaders*)malloc(sizeof(struct HTTPHeaders)); 44 | if ((*gateway)->http_headers == NULL) { 45 | free(*gateway); 46 | return 0; 47 | } 48 | (*gateway)->http_headers->num_elements = 0; 49 | (*gateway)->http_headers->headers = NULL; 50 | return 1; 51 | } 52 | 53 | int repo_config_gateway_free(struct Gateway* gateway) { 54 | if (gateway->http_headers != NULL) { 55 | for(int i = 0; i < gateway->http_headers->num_elements; i++) { 56 | struct HTTPHeader* currHeader = gateway->http_headers->headers[i]; 57 | free(currHeader->header); 58 | free(currHeader->value); 59 | free(currHeader); 60 | } 61 | if (gateway->http_headers->headers != NULL) 62 | free(gateway->http_headers->headers); // from init 63 | free(gateway->http_headers); // from new 64 | } 65 | free(gateway); // from new 66 | return 1; 67 | } 68 | -------------------------------------------------------------------------------- /test/core/test_null.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ipfs/importer/importer.h" 4 | 5 | int test_null_add_provider() { 6 | int retVal = 0; 7 | char* peer_id_1; 8 | char* peer_id_2; 9 | struct IpfsNode *local_node2 = NULL; 10 | pthread_t thread1, thread2; 11 | int thread1_started = 0, thread2_started = 0; 12 | struct MultiAddress* ma_peer1; 13 | char* ipfs_path = "/tmp/test1"; 14 | 15 | // create peer 1 that will be the "server" for this test 16 | os_utils_setenv("IPFS_PATH", ipfs_path, 1); 17 | drop_and_build_repository(ipfs_path, 4001, NULL, &peer_id_1); 18 | char multiaddress_string[255]; 19 | sprintf(multiaddress_string, "/ip4/127.0.0.1/tcp/4001/ipfs/%s", peer_id_1); 20 | ma_peer1 = multiaddress_new_from_string(multiaddress_string); 21 | // start the daemon in a separate thread 22 | if (pthread_create(&thread1, NULL, test_daemon_start, (void*)ipfs_path) < 0) 23 | goto exit; 24 | thread1_started = 1; 25 | 26 | // create peer 2 that will be the "client" for this test 27 | ipfs_path = "/tmp/test2"; 28 | os_utils_setenv("IPFS_PATH", ipfs_path, 1); 29 | struct Libp2pVector* ma_vector = libp2p_utils_vector_new(1); 30 | libp2p_utils_vector_add(ma_vector, ma_peer1); 31 | drop_and_build_repository(ipfs_path, 4002, ma_vector, &peer_id_2); 32 | // add a file, to prime the connection to peer 1 33 | //TODO: Find a better way to do this... 34 | size_t bytes_written = 0; 35 | ipfs_node_online_new(ipfs_path, &local_node2); 36 | struct HashtableNode* node = NULL; 37 | ipfs_import_file(NULL, "/home/parallels/ipfstest/hello_world.txt", &node, local_node2, &bytes_written, 0); 38 | ipfs_node_free(local_node2); 39 | // start the daemon in a separate thread 40 | if (pthread_create(&thread2, NULL, test_daemon_start, (void*)ipfs_path) < 0) 41 | goto exit; 42 | thread2_started = 1; 43 | // wait for everything to start up 44 | // JMJ debugging 45 | sleep(60); 46 | 47 | //TODO: verify that the server (peer 1) has the client and his file 48 | 49 | retVal = 1; 50 | exit: 51 | if (local_node2 != NULL) 52 | ipfs_node_free(local_node2); 53 | if (ma_peer1 != NULL) 54 | multiaddress_free(ma_peer1); 55 | ipfs_daemon_stop(); 56 | if (thread1_started) 57 | pthread_join(thread1, NULL); 58 | if (thread2_started) 59 | pthread_join(thread2, NULL); 60 | return retVal; 61 | } 62 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /core/swarm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "libp2p/utils/logger.h" 5 | #include "ipfs/core/ipfs_node.h" 6 | #include "ipfs/core/swarm.h" 7 | #include "ipfs/core/http_request.h" 8 | 9 | /*** 10 | * Connect to a swarm 11 | * @param local_node the local node 12 | * @param address the address of the remote 13 | * @returns true(1) on success, false(0) otherwise 14 | */ 15 | int ipfs_swarm_connect(struct IpfsNode* local_node, const char* address) { 16 | char* response = NULL; 17 | size_t response_size; 18 | // use the API to connect 19 | struct HttpRequest* request = ipfs_core_http_request_new(); 20 | if (request == NULL) 21 | return 0; 22 | request->command = "swarm"; 23 | request->sub_command = "connect"; 24 | libp2p_utils_vector_add(request->arguments, address); 25 | int retVal = ipfs_core_http_request_get(local_node, request, &response, &response_size); 26 | if (response != NULL && response_size > 0) { 27 | fwrite(response, 1, response_size, stdout); 28 | free(response); 29 | } 30 | ipfs_core_http_request_free(request); 31 | return retVal; 32 | } 33 | 34 | /*** 35 | * Handle command line swarm call 36 | */ 37 | int ipfs_swarm (struct CliArguments* args) { 38 | int retVal = 0; 39 | struct IpfsNode* client_node = NULL; 40 | 41 | if (args->argc < (args->verb_index + 2)) { 42 | libp2p_logger_error("swarm", "Not enough command line arguments. Should be \"swarm connect\" or \"swarm disconnect\" etc.\n"); 43 | goto exit; 44 | } 45 | 46 | // make sure API is running 47 | if (!ipfs_node_offline_new(args->config_dir, &client_node)) { 48 | libp2p_logger_error("swarm", "Unable to create offline node.\n"); 49 | goto exit; 50 | } 51 | if (client_node->mode != MODE_API_AVAILABLE) { 52 | libp2p_logger_error("swarm", "API must be running.\n"); 53 | goto exit; 54 | } 55 | 56 | const char* which = args->argv[args->verb_index + 1]; 57 | const char* path = args->argv[args->verb_index + 2]; 58 | // determine what we're doing 59 | if (strcmp(which, "connect") == 0) { 60 | retVal = ipfs_swarm_connect(client_node, path); 61 | } else if (strcmp(which, "disconnect") == 0) { 62 | libp2p_logger_error("swarm", "Swarm disconnect not implemented yet.\n"); 63 | retVal = 0; 64 | } else { 65 | libp2p_logger_error("swarm", "Nothing useful found on command line. Should be \"swarm connect\" or \"swarm disconnect\".\n"); 66 | goto exit; 67 | } 68 | 69 | exit: 70 | // shut everything down 71 | ipfs_node_free(client_node); 72 | 73 | return retVal; 74 | } 75 | -------------------------------------------------------------------------------- /include/ipfs/namesys/namesys.h: -------------------------------------------------------------------------------- 1 | #ifndef NAMESYS_H 2 | #define NAMESYS_H 3 | 4 | #define DefaultDepthLimit 32 5 | 6 | #include "ipfs/util/errs.h" 7 | 8 | typedef struct s_resolvers { 9 | char *protocol; 10 | int (*func)(char**, char*); 11 | } resolvers; 12 | 13 | // Resolver provides path resolution to IPFS 14 | // It has a pointer to a DAGService, which is uses to resolve nodes. 15 | // TODO: now that this is more modular, try to unify this code with the 16 | // the resolvers in namesys 17 | typedef struct s_resolver { 18 | //DAGService DAG; 19 | //NodeLink *lnk; 20 | // resolveOnce looks up a name once (without recursion). 21 | int (*resolveOnce) (char **, char *); 22 | } resolver; 23 | 24 | //TODO ciPrivKey from c-libp2p-crypto 25 | typedef void* ciPrivKey; 26 | 27 | typedef struct s_publishers { 28 | char *protocol; 29 | int (*func) (ciPrivKey, char*); 30 | int (*func_eol) (ciPrivKey, char*, time_t); 31 | } publishers; 32 | 33 | typedef struct s_mpns { 34 | resolvers *resolver; 35 | publishers *publisher; 36 | } mpns; 37 | 38 | typedef struct s_tlds { 39 | char *str; 40 | int condition; 41 | } tlds; 42 | 43 | int ipfs_namesys_resolve(char **path, char *name); 44 | int ipfs_namesys_resolve_n(char **path, char *name, int depth); 45 | int ipfs_namesys_resolve_once (char **path, char *name); 46 | int ipfs_namesys_publish (char *proto, ciPrivKey name, char *value); 47 | int ipfs_namesys_publish_with_eol (char *proto, ciPrivKey name, char *value, time_t eol); 48 | 49 | int ipfs_proquint_is_proquint(char *str); 50 | char *ipfs_proquint_encode(char *buf, int size); 51 | char *ipfs_proquint_decode(char *str); 52 | int ipfs_proquint_resolve_once (char **p, char *name); 53 | 54 | int ipfs_isdomain_match_string (char *d); 55 | int ipfs_isdomain_is_icann_tld(char *s); 56 | int ipfs_isdomain_is_extended_tld (char *s); 57 | int ipfs_isdomain_is_tld (char *s); 58 | int ipfs_isdomain_is_domain (char *s); 59 | 60 | typedef struct s_DNSResolver { 61 | // TODO 62 | int (*lookupTXT) (char ***, char *); 63 | } DNSResolver; 64 | 65 | int ipfs_dns_resolver_resolve_once (char **path, char *name); 66 | int ipfs_dns_work_domain (int output, DNSResolver *r, char *name); 67 | int ipfs_dns_parse_entry (char **path, char *txt); 68 | int ipfs_dns_try_parse_dns_link(char **path, char *txt); 69 | #endif //NAMESYS_H 70 | -------------------------------------------------------------------------------- /core/bootstrap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "libp2p/peer/peer.h" 4 | #include "libp2p/utils/logger.h" 5 | #include "ipfs/routing/routing.h" 6 | #include "ipfs/core/ipfs_node.h" 7 | #include "ipfs/thirdparty/ipfsaddr/ipfs_addr.h" 8 | #include "multiaddr/multiaddr.h" 9 | 10 | /*** 11 | * Begin to connect to the swarm 12 | */ 13 | /* 14 | void *ipfs_bootstrap_swarm(void* param) { 15 | //TODO: 16 | struct IpfsNode* local_node = (struct IpfsNode*)param; 17 | // read the config file and get the bootstrap peers 18 | for(int i = 0; i < local_node->repo->config->peer_addresses.num_peers; i++) { // loop through the peers 19 | struct IPFSAddr* ipfs_addr = local_node->repo->config->peer_addresses.peers[i]; 20 | struct MultiAddress* ma = multiaddress_new_from_string(ipfs_addr->entire_string); 21 | // get the id 22 | char* ptr; 23 | if ( (ptr = strstr(ipfs_addr->entire_string, "/ipfs/")) != NULL) { // look for the peer id 24 | ptr += 6; 25 | if (ptr[0] == 'Q' && ptr[1] == 'm') { // things look good 26 | struct Libp2pPeer* peer = libp2p_peer_new_from_data(ptr, strlen(ptr), ma); 27 | libp2p_peerstore_add_peer(local_node->peerstore, peer); 28 | } 29 | // TODO: attempt to connect to the peer 30 | 31 | } // we have a good peer ID 32 | 33 | } 34 | return (void*)1; 35 | } 36 | */ 37 | 38 | /*** 39 | * Announce to the network all of the files that I have in storage 40 | * @param local_node the context 41 | */ 42 | /* 43 | void ipfs_bootstrap_announce_files(struct IpfsNode* local_node) { 44 | struct Datastore* db = local_node->repo->config->datastore; 45 | if (!db->datastore_cursor_open(db)) 46 | return; 47 | unsigned char* key = NULL; 48 | int key_size = 0; 49 | enum DatastoreCursorOp op = CURSOR_FIRST; 50 | while (db->datastore_cursor_get(&key, &key_size, NULL, 0, op, db)) { 51 | libp2p_logger_debug("bootstrap", "Announcing a file to the world.\n"); 52 | local_node->routing->Provide(local_node->routing, key, key_size); 53 | op = CURSOR_NEXT; 54 | free(key); 55 | } 56 | 57 | // close cursor 58 | db->datastore_cursor_close(db); 59 | 60 | return; 61 | } 62 | */ 63 | 64 | /*** 65 | * connect to the swarm 66 | * NOTE: This fills in the IpfsNode->routing struct 67 | * 68 | * @param param the IpfsNode information 69 | * @returns nothing useful 70 | */ 71 | /* 72 | void *ipfs_bootstrap_routing(void* param) { 73 | struct IpfsNode* local_node = (struct IpfsNode*)param; 74 | local_node->routing = ipfs_routing_new_online(local_node, &local_node->identity->private_key, NULL); 75 | local_node->routing->Bootstrap(local_node->routing); 76 | ipfs_bootstrap_announce_files(local_node); 77 | return (void*)2; 78 | } 79 | */ 80 | -------------------------------------------------------------------------------- /exchange/bitswap/want_manager.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ipfs/exchange/bitswap/want_manager.h" 4 | #include "ipfs/exchange/bitswap/wantlist_queue.h" 5 | 6 | /*** 7 | * Add a Cid to the wantlist 8 | * @param context the context 9 | * @param cid the Cid 10 | * @returns the added entry 11 | */ 12 | struct WantListQueueEntry* ipfs_bitswap_want_manager_add(const struct BitswapContext* context, const struct Cid* cid, const struct WantListSession* session) { 13 | // add if not there, and increment reference count 14 | return ipfs_bitswap_wantlist_queue_add(context->localWantlist, cid, session); 15 | } 16 | 17 | /*** 18 | * Checks to see if the requested block has been received 19 | * @param context the context 20 | * @param cid the Cid 21 | * @returns true(1) if it has been received, false(0) otherwise 22 | */ 23 | int ipfs_bitswap_want_manager_received(const struct BitswapContext* context, const struct Cid* cid) { 24 | // find the entry 25 | struct WantListQueueEntry* entry = ipfs_bitswap_wantlist_queue_find(context->localWantlist, cid); 26 | // check the status 27 | if (entry != NULL && entry->block != NULL) { 28 | return 1; 29 | } 30 | return 0; 31 | } 32 | 33 | /*** 34 | * retrieve a block from the WantManager. NOTE: a call to want_manager_received should be done first 35 | * @param context the context 36 | * @param cid the Cid to get 37 | * @param block a pointer to the block that will be allocated 38 | * @returns true(1) on success, false(0) otherwise 39 | */ 40 | int ipfs_bitswap_want_manager_get_block(const struct BitswapContext* context, const struct Cid* cid, struct Block** block) { 41 | struct WantListQueueEntry* entry = ipfs_bitswap_wantlist_queue_find(context->localWantlist, cid); 42 | if (entry != NULL && entry->block != NULL) { 43 | // return a copy of the block 44 | *block = ipfs_block_copy(entry->block); 45 | if ( (*block) != NULL) { 46 | return 1; 47 | } 48 | } 49 | return 0; 50 | } 51 | 52 | /*** 53 | * We no longer are requesting this block, so remove it from the queue 54 | * NOTE: This is reference counted, as another process may have asked for it. 55 | * @param context the context 56 | * @param cid the Cid 57 | * @returns true(1) on success, false(0) otherwise. 58 | */ 59 | int ipfs_bitswap_want_manager_remove(const struct BitswapContext* context, const struct Cid* cid) { 60 | // decrement the reference count 61 | // if it is zero, remove the entry (lock first) 62 | struct WantListSession session; 63 | session.type = WANTLIST_SESSION_TYPE_LOCAL; 64 | session.context = (void*) context->ipfsNode; 65 | return ipfs_bitswap_wantlist_queue_remove(context->localWantlist, cid, &session); 66 | } 67 | -------------------------------------------------------------------------------- /test/repo/test_repo_fsrepo.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/repo/fsrepo/fs_repo.h" 2 | #include "../test_helper.h" 3 | 4 | int test_repo_fsrepo_open_config() { 5 | struct FSRepo* fs_repo = NULL; 6 | 7 | const char* path = "/tmp/.ipfs"; 8 | 9 | if (!drop_build_and_open_repo(path, &fs_repo)) 10 | return 0; 11 | 12 | if (!ipfs_repo_fsrepo_free(fs_repo)) 13 | return 0; 14 | 15 | return 1; 16 | } 17 | 18 | int test_repo_fsrepo_build() { 19 | const char* path = "/tmp/.ipfs"; 20 | char* peer_id = NULL; 21 | 22 | int retVal = drop_and_build_repository(path, 4001, NULL, &peer_id); 23 | if (peer_id != NULL) 24 | free(peer_id); 25 | return retVal; 26 | } 27 | 28 | int test_repo_fsrepo_write_read_block() { 29 | struct Block* block = NULL; 30 | struct FSRepo* fs_repo = NULL; 31 | int retVal = 0; 32 | 33 | // freshen the repository 34 | retVal = drop_build_and_open_repo("/tmp/.ipfs", &fs_repo); 35 | if (retVal == 0) 36 | return 0; 37 | 38 | // make some data 39 | size_t data_size = 10000; 40 | unsigned char data[data_size]; 41 | 42 | int counter = 0; 43 | for(int i = 0; i < data_size; i++) { 44 | data[i] = counter++; 45 | if (counter > 15) 46 | counter = 0; 47 | } 48 | 49 | // create and write the block 50 | block = ipfs_block_new(); 51 | if (block == NULL) { 52 | ipfs_repo_fsrepo_free(fs_repo); 53 | return 0; 54 | } 55 | retVal = ipfs_blocks_block_add_data(data, data_size, block); 56 | if (retVal == 0) { 57 | ipfs_repo_fsrepo_free(fs_repo); 58 | return 0; 59 | } 60 | 61 | size_t bytes_written; 62 | retVal = ipfs_repo_fsrepo_block_write(block, fs_repo, &bytes_written); 63 | if (retVal == 0) { 64 | ipfs_repo_fsrepo_free(fs_repo); 65 | ipfs_block_free(block); 66 | return 0; 67 | } 68 | 69 | // retrieve the block 70 | struct Block* results; 71 | retVal = ipfs_repo_fsrepo_block_read(block->cid->hash, block->cid->hash_length, &results, fs_repo); 72 | if (retVal == 0) { 73 | ipfs_repo_fsrepo_free(fs_repo); 74 | ipfs_block_free(block); 75 | return 0; 76 | } 77 | 78 | // compare the two blocks 79 | retVal = 1; 80 | if (block->data_length != results->data_length || block->data_length != data_size) { 81 | printf("block data is of different length: %lu vs %lu\n", results->data_length, block->data_length); 82 | retVal = 0; 83 | } 84 | 85 | for(size_t i = 0; i < block->data_length; i++) { 86 | if (block->data[i] != results->data[i]) { 87 | printf("Data is different at position %lu. Should be %02x but is %02x\n", i, block->data[i], results->data[i]); 88 | retVal = 0; 89 | break; 90 | } 91 | } 92 | 93 | ipfs_repo_fsrepo_free(fs_repo); 94 | ipfs_block_free(block); 95 | ipfs_block_free(results); 96 | return retVal; 97 | } 98 | -------------------------------------------------------------------------------- /include/ipfs/core/api.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ipfs/core/ipfs_node.h" 5 | 6 | #ifdef __x86_64__ 7 | #define INT_TYPE uint64_t 8 | #else 9 | #define INT_TYPE uint32_t 10 | #endif 11 | 12 | #define MAX_READ (32*1024) // 32k 13 | #define MAX_CHUNK (32*1024) // 32k 14 | 15 | struct ApiContext { 16 | int socket; 17 | uint32_t ipv4; 18 | uint16_t port; 19 | int max_conns; 20 | int timeout; 21 | pthread_mutex_t conns_lock; 22 | int conns_count; 23 | pthread_t api_thread; 24 | struct s_conns { 25 | int socket; 26 | uint32_t ipv4; 27 | uint16_t port; 28 | pthread_t pthread; 29 | } **conns; 30 | }; 31 | 32 | struct s_request { 33 | char *buf; 34 | size_t size; 35 | 36 | int method; 37 | int path; 38 | int request; 39 | int query; 40 | int http_ver; 41 | int header; 42 | int body; 43 | size_t body_size; 44 | int boundary; 45 | size_t boundary_size; 46 | }; 47 | 48 | #define API_V0_START "/api/v0/" 49 | 50 | #define WEBUI_ADDR "/ipfs/QmPhnvn747LqwPYMJmQVorMaGbMSgA7mRRoyyZYz3DoZRQ/" 51 | 52 | #define HTTP_301 "HTTP/1.1 301 Moved Permanently\r\n" \ 53 | "Location: %s\r\n" \ 54 | "Content-Type: text/html\r\n\r\n" \ 55 | "Moved Permanently.\r\n\r\n" 56 | 57 | #define HTTP_302 "HTTP/1.1 302 Found\r\n" \ 58 | "Content-Type: text/html\r\n" \ 59 | "Connection: close\r\n" \ 60 | "Location: %s\r\n" \ 61 | "X-Ipfs-Path: %s\r\n\r\n" \ 62 | "Found.\r\n\r\n" 63 | 64 | #define HTTP_400 "HTTP/1.1 400 Bad Request\r\n" \ 65 | "Content-Type: text/plain\r\n" \ 66 | "Connection: close\r\n\r\n" \ 67 | "400 Bad Request" 68 | 69 | #define HTTP_404 "HTTP/1.1 404 Not Found\r\n" \ 70 | "Content-Type: text/plain\r\n" \ 71 | "Connection: close\r\n\r\n" \ 72 | "404 page not found" 73 | 74 | #define HTTP_500 "HTTP/1.1 500 Internal server error\r\n" \ 75 | "Content-Type: text/plain\r\n" \ 76 | "Connection: close\r\n\r\n" \ 77 | "500 Internal server error" 78 | 79 | #define HTTP_501 "HTTP/1.1 501 Not Implemented\r\n" \ 80 | "Content-Type: text/plain\r\n" \ 81 | "Connection: close\r\n\r\n" \ 82 | "501 Not Implemented" 83 | 84 | #define write_cstr(f,s) write(f,s,sizeof(s)-1) 85 | #define write_str(f,s) write(f,s,strlen(s)) 86 | 87 | #define cstrstart(a,b) (memcmp(a,b,sizeof(b)-1)==0) 88 | #define strstart(a,b) (memcmp(a,b,strlen(b))==0) 89 | 90 | int api_send_resp_chunks(int fd, void *buf, size_t size); 91 | void *api_connection_thread (void *ptr); 92 | void api_connections_cleanup (struct IpfsNode* node); 93 | void *api_listen_thread (void *ptr); 94 | int api_start (struct IpfsNode* local_node, int max_conns, int timeout); 95 | int api_stop (struct IpfsNode* local_node); 96 | -------------------------------------------------------------------------------- /core/daemon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "libp2p/net/p2pnet.h" 7 | #include "libp2p/peer/peerstore.h" 8 | #include "ipfs/core/daemon.h" 9 | #include "ipfs/core/null.h" // for ipfs_null_shutdown 10 | #include "ipfs/core/ipfs_node.h" 11 | #include "ipfs/core/bootstrap.h" 12 | #include "ipfs/repo/fsrepo/fs_repo.h" 13 | #include "ipfs/repo/init.h" 14 | #include "libp2p/utils/logger.h" 15 | 16 | int ipfs_daemon_start(char* repo_path) { 17 | int count_pths = 0, retVal = 0; 18 | pthread_t work_pths[MAX]; 19 | struct IpfsNodeListenParams listen_param; 20 | struct MultiAddress* ma = NULL; 21 | 22 | libp2p_logger_info("daemon", "Initializing daemon for %s...\n", repo_path); 23 | 24 | struct IpfsNode* local_node = NULL; 25 | if (!ipfs_node_online_new(repo_path, &local_node)) 26 | goto exit; 27 | 28 | // Set null router param 29 | ma = multiaddress_new_from_string(local_node->repo->config->addresses->swarm_head->item); 30 | listen_param.port = multiaddress_get_ip_port(ma); 31 | listen_param.ipv4 = 0; // ip 0.0.0.0, all interfaces 32 | listen_param.local_node = local_node; 33 | 34 | // Create pthread for swarm listener. 35 | if (pthread_create(&work_pths[count_pths++], NULL, local_node->routing->Listen, &listen_param)) { 36 | libp2p_logger_error("daemon", "Error creating thread for ipfs null listen\n"); 37 | goto exit; 38 | } 39 | 40 | local_node->routing->Bootstrap(local_node->routing); 41 | 42 | libp2p_logger_info("daemon", "Daemon for %s is ready on port %d\n", listen_param.local_node->identity->peer->id, listen_param.port); 43 | 44 | // Wait for pthreads to finish. 45 | while (count_pths) { 46 | if (pthread_join(work_pths[--count_pths], NULL)) { 47 | libp2p_logger_error("daemon", "Error joining thread\n"); 48 | goto exit; 49 | } 50 | } 51 | 52 | retVal = 1; 53 | exit: 54 | libp2p_logger_debug("daemon", "Cleaning up daemon processes for %s\n", repo_path); 55 | // clean up 56 | if (ma != NULL) 57 | multiaddress_free(ma); 58 | if (local_node != NULL) { 59 | ipfs_node_free(local_node); 60 | } 61 | return retVal; 62 | 63 | } 64 | 65 | int ipfs_daemon_stop() { 66 | return ipfs_null_shutdown(); 67 | } 68 | 69 | int ipfs_daemon (int argc, char **argv) 70 | { 71 | char* repo_path = NULL; 72 | 73 | libp2p_logger_add_class("daemon"); 74 | if (!ipfs_repo_get_directory(argc, argv, &repo_path)) { 75 | libp2p_logger_error("daemon", "Unable to open repo: %s\n", repo_path); 76 | return 0; 77 | } 78 | 79 | return ipfs_daemon_start(repo_path); 80 | } 81 | -------------------------------------------------------------------------------- /include/ipfs/exchange/exchange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * This is the definition of an "Exchange" 4 | * 5 | * Anything that implements the Exchange interface can be used as 6 | * an IPFS block exchange protocol. 7 | */ 8 | #include "ipfs/blocks/block.h" 9 | #include "ipfs/cid/cid.h" 10 | #include "libp2p/utils/vector.h" 11 | 12 | /** 13 | * These are methods that the local IPFS daemon (or client) 14 | * call to communicate with the local repository or network 15 | */ 16 | 17 | struct Exchange { 18 | /** 19 | * Retrieve a block from peers within the deadline enforced 20 | * by the context 21 | * 22 | * NOTE: Shouldn't the block parameter be a callback (function pointer)? 23 | * Otherwise, this function is going to block. Is that what we want? 24 | * 25 | * @param context the context 26 | * @param cid the hash of the block to retrieve 27 | * @param block a pointer to the block (allocated by this method if return is true) 28 | * @returns true(1) on success, false(0) otherwise 29 | */ 30 | int (*GetBlock)(struct Exchange* exchange, struct Cid* cid, struct Block** block); 31 | 32 | /** 33 | * Retrieve a block from peers asynchronously 34 | * 35 | * @param context the context 36 | * @param cid the hash of the block to retrieve 37 | * @param queue_entry the queue entry to watch 38 | * @returns true(1) on success, false(0) otherwise 39 | */ 40 | int (*GetBlockAsync)(struct Exchange* exchange, struct Cid* cid, struct Block** block); 41 | 42 | /** 43 | * Retrieve several blocks 44 | * @param context the context 45 | * @param Cids a vector of hashes for the blocks to be retrieved 46 | * @param blocks a pointer to a vector of retrieved blocks (will be NULL on error) 47 | * @returns true(1) on success, otherwise false(0) 48 | */ 49 | int (*GetBlocks)(struct Exchange* exchange, struct Libp2pVector* Cids, struct Libp2pVector** blocks); 50 | 51 | /** 52 | * Announces the existance of a block to this bitswap service. The service will 53 | * potentially notify its peers. 54 | * NOTE: This is mainly designed to announce blocks added by non-bitswap methods (i.e. the local user) 55 | * @param block the block being announced 56 | * @returns true(1) on success, false(0) if not 57 | */ 58 | int (*HasBlock)(struct Exchange* exchange, struct Block* block); 59 | 60 | /** 61 | * Determine if we're online 62 | * @returns true(1) if we're online 63 | */ 64 | int (*IsOnline)(struct Exchange*); 65 | 66 | /** 67 | * Close up the exchange, and go offline 68 | * @returns true(1); 69 | */ 70 | int (*Close)(struct Exchange*); 71 | 72 | /** 73 | * Used by each implementation to maintain state 74 | * (will be cast-ed to an implementation-specific structure) 75 | */ 76 | void* exchangeContext; 77 | }; 78 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/replication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libp2p/utils/vector.h" 4 | #include "libp2p/peer/peer.h" 5 | 6 | struct ReplicationPeer { 7 | struct Libp2pPeer* peer; 8 | unsigned long long lastConnect; 9 | unsigned long long lastJournalTime; 10 | }; 11 | 12 | struct Replication { 13 | int announce; 14 | int announce_minutes; 15 | struct Libp2pVector* replication_peers; 16 | }; 17 | 18 | /** 19 | * Allocate a new ReplicationPeer struct 20 | * @returns the new struct 21 | */ 22 | struct ReplicationPeer* repo_config_replication_peer_new(); 23 | 24 | /*** 25 | * Free the resources of a ReplicationPeer 26 | * @param rp the ReplicationPeer to free 27 | * @returns true(1) 28 | */ 29 | int repo_config_replication_peer_free(struct ReplicationPeer* rp); 30 | 31 | /*** 32 | * allocate memory and initialize the replication struct 33 | * @param replication a pointer to the struct to be allocated 34 | * @returns true(1) on success, false(0) otherwise 35 | */ 36 | int repo_config_replication_new(struct Replication** replication); 37 | 38 | /*** 39 | * Frees memory of a replication struct 40 | * @param replication the replication struct 41 | * @returns true(1); 42 | */ 43 | int repo_config_replication_free(struct Replication* replication); 44 | 45 | /*** 46 | * Determines if this peer is one of our approved replication nodes 47 | * @param replication the replication struct 48 | * @param peer the peer to examine 49 | * @returns true(1) if this peer should be kept syncronized, false(0) otherwise 50 | */ 51 | int repo_config_replication_approved_node(struct Replication* replication, struct Libp2pPeer* peer); 52 | 53 | /** 54 | * Determine the last time a replication was successful for this peer (at least we sent it something without error) 55 | * @param replication the replication struct 56 | * @param peer the peer to examine 57 | * @returns the time since the last replication, or the announce time if we have no record 58 | */ 59 | unsigned long long repo_config_replication_last_attempt(struct Replication* replication, struct Libp2pPeer* peer); 60 | 61 | /*** 62 | * Determine the last journal record time that was sent to this peer 63 | * @param replication the replication struct 64 | * @param peer the peer to examine 65 | * @returns the time of the last journal entry successfully sent 66 | */ 67 | unsigned long long repo_config_replication_last_journal_time(struct Replication* replication, struct Libp2pPeer* peer); 68 | 69 | /*** 70 | * Given a peer, return the ReplicationPeer record 71 | * @param replication the context 72 | * @param key the peer to look for 73 | * @returns the ReplicationPeer struct, or NULL if not found 74 | */ 75 | struct ReplicationPeer* repo_config_get_replication_peer(struct Replication* replication, struct Libp2pPeer* key); 76 | 77 | -------------------------------------------------------------------------------- /test/namesys/test_namesys.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helper.h" 5 | #include "ipfs/cid/cid.h" 6 | #include "ipfs/core/ipfs_node.h" 7 | #include "ipfs/namesys/publisher.h" 8 | #include "ipfs/namesys/resolver.h" 9 | 10 | int test_namesys_publisher_publish() { 11 | int retVal = 0; 12 | struct IpfsNode* local_node = NULL; 13 | char* hash_text = "/ipns/QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; 14 | char* repo_path = "/tmp/ipfs_1"; 15 | char* peer_id = NULL; 16 | 17 | if (!drop_and_build_repository(repo_path, 4001, NULL, &peer_id)) { 18 | libp2p_logger_error("test_publisher", "Unable to build repository at %s.\n", repo_path); 19 | goto exit; 20 | } 21 | 22 | // get a local node 23 | if (!ipfs_node_offline_new(repo_path, &local_node)) { 24 | libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n"); 25 | goto exit; 26 | } 27 | 28 | // attempt to publish 29 | if (!ipfs_namesys_publisher_publish(local_node, hash_text)) { 30 | libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text); 31 | goto exit; 32 | } 33 | 34 | retVal = 1; 35 | exit: 36 | ipfs_node_free(local_node); 37 | return retVal; 38 | } 39 | 40 | int test_namesys_resolver_resolve() { 41 | int retVal = 0; 42 | struct IpfsNode* local_node = NULL; 43 | char* hash_text = "QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; // the hash of a hello, world file 44 | char ipns_path[512] = ""; // the Peer ID of config.test1 45 | char* repo_path = "/tmp/ipfs_1"; 46 | char* peer_id = NULL; 47 | char* result = NULL; 48 | 49 | drop_and_build_repository(repo_path, 4001, NULL, &peer_id); 50 | 51 | // get a local node 52 | if (!ipfs_node_offline_new(repo_path, &local_node)) { 53 | libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n"); 54 | goto exit; 55 | } 56 | 57 | // set ipns_path 58 | sprintf(ipns_path, "/ipfs/%s", peer_id); 59 | 60 | // attempt to publish 61 | if (!ipfs_namesys_publisher_publish(local_node, hash_text)) { 62 | libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text); 63 | goto exit; 64 | } 65 | 66 | // attempt to retrieve 67 | if (!ipfs_namesys_resolver_resolve(local_node, ipns_path, 1, &result)) { 68 | libp2p_logger_error("test_namesys", "Could not resolve %s.\n", hash_text); 69 | goto exit; 70 | } 71 | 72 | if (strcmp(result, hash_text) != 0) { 73 | libp2p_logger_error("test_namesys", "Retrieve wrong result. %s should be %s.\n", result, hash_text); 74 | goto exit; 75 | } 76 | 77 | libp2p_logger_error("test_namesys", "Asked for %s and received %s. Success!\n", ipns_path, result); 78 | 79 | retVal = 1; 80 | exit: 81 | ipfs_node_free(local_node); 82 | if (result != NULL) 83 | free(result); 84 | return retVal; 85 | } 86 | -------------------------------------------------------------------------------- /test/storage/test_unixfs.h: -------------------------------------------------------------------------------- 1 | #include "ipfs/unixfs/unixfs.h" 2 | 3 | int test_unixfs_encode_decode() { 4 | struct UnixFS* unixfs = NULL; 5 | int retVal; 6 | 7 | // a directory 8 | retVal = ipfs_unixfs_new(&unixfs); 9 | unixfs->data_type = UNIXFS_DIRECTORY; 10 | 11 | // serialize 12 | size_t buffer_size = ipfs_unixfs_protobuf_encode_size(unixfs); 13 | unsigned char buffer[buffer_size]; 14 | size_t bytes_written = 0; 15 | 16 | retVal = ipfs_unixfs_protobuf_encode(unixfs, buffer, buffer_size, &bytes_written); 17 | if (retVal == 0) { 18 | ipfs_unixfs_free(unixfs); 19 | return 0; 20 | } 21 | 22 | // unserialize 23 | struct UnixFS* results = NULL; 24 | retVal = ipfs_unixfs_protobuf_decode(buffer, bytes_written, &results); 25 | if (retVal == 0) { 26 | ipfs_unixfs_free(unixfs); 27 | return 0; 28 | } 29 | 30 | // compare 31 | if (results->data_type != unixfs->data_type) { 32 | ipfs_unixfs_free(unixfs); 33 | ipfs_unixfs_free(results); 34 | return 0; 35 | } 36 | 37 | if (results->block_size_head != unixfs->block_size_head) { 38 | ipfs_unixfs_free(unixfs); 39 | ipfs_unixfs_free(results); 40 | return 0; 41 | } 42 | 43 | ipfs_unixfs_free(unixfs); 44 | ipfs_unixfs_free(results); 45 | return 1; 46 | } 47 | 48 | int test_unixfs_encode_smallfile() { 49 | struct UnixFS* unixfs = NULL; 50 | ipfs_unixfs_new(&unixfs); 51 | 52 | unsigned char bytes[] = { 53 | 0x54, 0x68, 0x69, 0x73, 0x20, 54 | 0x69, 0x73, 0x20, 0x74, 0x65, 55 | 0x78, 0x74, 0x20, 0x77, 0x69, 56 | 0x74, 0x68, 0x69, 0x6e, 0x20, 57 | 0x48, 0x65, 0x6c, 0x6c, 0x6f, 58 | 0x57, 0x65, 0x72, 0x6c, 0x64, 59 | 0x2e, 0x74, 0x78, 0x74, 0x0a }; 60 | unsigned char expected_results[] = { 61 | 0x08, 0x02, 0x12, 0x23, 62 | 0x54, 0x68, 0x69, 0x73, 0x20, 63 | 0x69, 0x73, 0x20, 0x74, 0x65, 64 | 0x78, 0x74, 0x20, 0x77, 0x69, 65 | 0x74, 0x68, 0x69, 0x6e, 0x20, 66 | 0x48, 0x65, 0x6c, 0x6c, 0x6f, 67 | 0x57, 0x65, 0x72, 0x6c, 0x64, 68 | 0x2e, 0x74, 0x78, 0x74, 0x0a 69 | }; 70 | 71 | unixfs->bytes = (unsigned char*)malloc(35); 72 | memcpy(unixfs->bytes, bytes, 35); 73 | unixfs->bytes_size = 35; 74 | unixfs->data_type = UNIXFS_FILE; 75 | 76 | size_t protobuf_size = 43; 77 | unsigned char protobuf[protobuf_size]; 78 | size_t bytes_written; 79 | ipfs_unixfs_protobuf_encode(unixfs, protobuf, protobuf_size, &bytes_written); 80 | 81 | int retVal = 1; 82 | 83 | if (bytes_written != 39) { 84 | printf("Length should be %lu, but is %lu\n", 41LU, bytes_written); 85 | retVal = 0; 86 | } 87 | 88 | for(int i = 0; i < bytes_written; i++) { 89 | if (expected_results[i] != protobuf[i]) { 90 | printf("Byte at position %d should be %02x but is %02x\n", i, expected_results[i], protobuf[i]); 91 | retVal = 0; 92 | } 93 | } 94 | 95 | ipfs_unixfs_free(unixfs); 96 | 97 | return retVal; 98 | } 99 | -------------------------------------------------------------------------------- /test/repo/test_repo_identity.h: -------------------------------------------------------------------------------- 1 | #ifndef test_repo_identity_h 2 | #define test_repo_identity_h 3 | 4 | #include 5 | 6 | #include "ipfs/repo/config/identity.h" 7 | #include "libp2p/crypto/encoding/base64.h" 8 | 9 | int test_repo_config_identity_new() { 10 | struct Identity* identity; 11 | int retVal = repo_config_identity_new(&identity); 12 | if (retVal == 0) 13 | return 0; 14 | 15 | retVal = repo_config_identity_init(identity, 2046); 16 | if (retVal == 0) 17 | return 0; 18 | 19 | // now examine it 20 | int privateKeySize = sizeof(identity->private_key); 21 | if (privateKeySize < 0) { 22 | printf("Private key structure size should be greater than 0\n"); 23 | return 0; 24 | } 25 | 26 | retVal = repo_config_identity_free(identity); 27 | 28 | return retVal; 29 | } 30 | 31 | // test this key 32 | int test_repo_config_identity_private_key() { 33 | const unsigned char* priv_b64 = (unsigned char*)"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="; 34 | size_t decoded_len = libp2p_crypto_encoding_base64_decode_size(strlen((char*)priv_b64)); 35 | unsigned char* out_buff = malloc(sizeof(char) * decoded_len); 36 | libp2p_crypto_encoding_base64_decode(priv_b64, strlen((char*)priv_b64), out_buff, decoded_len, &decoded_len); 37 | free(out_buff); 38 | // now test 39 | return 1; 40 | 41 | } 42 | 43 | #endif /* test_repo_identity_h */ 44 | -------------------------------------------------------------------------------- /include/ipfs/repo/fsrepo/journalstore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * Piggyback on the datastore to access the journal entries 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "lmdb.h" 10 | #include "libp2p/db/datastore.h" 11 | #include "ipfs/repo/fsrepo/lmdb_cursor.h" 12 | 13 | struct JournalRecord { 14 | unsigned long long timestamp; // the timestamp of the file 15 | int pin; // true if it is to be stored, false if it is to be deleted 16 | int pending; // true if we do not have this file yet 17 | uint8_t *hash; // the hash of the block (file) 18 | size_t hash_size; // the size of the hash 19 | }; 20 | 21 | struct JournalRecord* lmdb_journal_record_new(); 22 | 23 | int lmdb_journal_record_free(struct JournalRecord* rec); 24 | 25 | /** 26 | * Open a cursor to the journalstore table 27 | * @param db_handle a handle to the database (an MDB_env pointer) 28 | * @param cursor where to place the results 29 | * @returns true(1) on success, false(0) otherwise 30 | */ 31 | int lmdb_journalstore_cursor_open(void* db_handle, struct lmdb_trans_cursor **cursor, struct MDB_txn *trans_to_use); 32 | 33 | /** 34 | * Read a record from the cursor 35 | */ 36 | int lmdb_journalstore_cursor_get(struct lmdb_trans_cursor *cursor, enum DatastoreCursorOp op, struct JournalRecord** record); 37 | 38 | /*** 39 | * Write the record at the cursor 40 | * @param crsr the cursor 41 | * @param journal_record the record to write 42 | * @returns true(1) on success, false(0) otherwise 43 | */ 44 | int lmdb_journalstore_cursor_put(struct lmdb_trans_cursor *crsr, struct JournalRecord* journal_record); 45 | 46 | /** 47 | * Close the cursor 48 | */ 49 | int lmdb_journalstore_cursor_close(struct lmdb_trans_cursor *cursor, int commitTransaction); 50 | 51 | int journal_record_free(struct JournalRecord* rec); 52 | 53 | int lmdb_journalstore_journal_add(struct lmdb_trans_cursor *journalstore_cursor, struct JournalRecord *journalstore_record); 54 | 55 | /*** 56 | * Attempt to get a specific record identified by its timestamp and bytes 57 | * @param handle a handle to the database engine 58 | * @param journalstore_cursor the cursor (will be returned as a cursor that points to the record found 59 | * @param journalstore_record where to put the results (can pass null). If data is within the struct, will use it as search criteria 60 | * @returns true(1) on success, false(0) otherwise 61 | */ 62 | int lmdb_journalstore_get_record(void* handle, struct lmdb_trans_cursor *journalstore_cursor, struct JournalRecord **journalstore_record); 63 | 64 | /*** 65 | * Convert the JournalRec struct into a lmdb key and lmdb value 66 | * @param journal_record the record to convert 67 | * @param db_key where to store the key information 68 | * @param db_value where to store the value information 69 | */ 70 | int lmdb_journalstore_build_key_value_pair(const struct JournalRecord* journal_record, struct MDB_val* db_key, struct MDB_val *db_value); 71 | 72 | -------------------------------------------------------------------------------- /include/ipfs/core/http_request.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ipfs/core/ipfs_node.h" 4 | 5 | /*** 6 | * A name/value pair of http parameters 7 | */ 8 | struct HttpParam { 9 | char* name; // the name of the parameter 10 | char* value; // the value of the parameter 11 | }; 12 | 13 | /** 14 | * A struct to help with incoming http requests 15 | */ 16 | struct HttpRequest { 17 | char* command; // the command 18 | char* sub_command; // the sub command 19 | struct Libp2pVector* params; // a collection of HttpParam structs 20 | struct Libp2pVector* arguments; // a collection of chars that are arguments 21 | }; 22 | 23 | /*** 24 | * A struct to hold the response to be sent via http 25 | */ 26 | struct HttpResponse { 27 | char* content_type; // a const char, not dynamically allocated 28 | uint8_t* bytes; // dynamically allocated 29 | size_t bytes_size; 30 | }; 31 | 32 | /*** 33 | * Build a new HttpRequest 34 | * @returns the newly allocated HttpRequest struct 35 | */ 36 | struct HttpRequest* ipfs_core_http_request_new(); 37 | 38 | /*** 39 | * Clean up resources of a HttpRequest struct 40 | * @param request the struct to destroy 41 | */ 42 | void ipfs_core_http_request_free(struct HttpRequest* request); 43 | 44 | struct HttpResponse* ipfs_core_http_response_new(); 45 | 46 | void ipfs_core_http_response_free(struct HttpResponse* response); 47 | 48 | /*** 49 | * Build a new HttpParam 50 | * @returns a newly allocated HttpParam struct 51 | */ 52 | struct HttpParam* ipfs_core_http_param_new(); 53 | 54 | /*** 55 | * Clean up resources allocated by a HttpParam struct 56 | * @param param the struct to destroy 57 | */ 58 | void ipfs_core_http_param_free(struct HttpParam* param); 59 | 60 | /*** 61 | * Process the parameters passed in from an http request 62 | * @param local_node the context 63 | * @param request the request 64 | * @param response the response 65 | * @returns true(1) on success, false(0) otherwise. 66 | */ 67 | int ipfs_core_http_request_process(struct IpfsNode* local_node, struct HttpRequest* request, struct HttpResponse** response); 68 | 69 | /** 70 | * Do an HTTP Get to the local API 71 | * @param local_node the context 72 | * @param request the request 73 | * @param result the results 74 | * @param result_size the size of the results 75 | * @returns true(1) on success, false(0) on error 76 | */ 77 | int ipfs_core_http_request_get(struct IpfsNode* local_node, struct HttpRequest* request, char** result, size_t* result_size); 78 | 79 | /** 80 | * Do an HTTP Post to the local API 81 | * @param local_node the context 82 | * @param request the request 83 | * @param result the results 84 | * @param result_size the size of the results 85 | * @param data the array with post data 86 | * @param data_size the data length 87 | * @returns true(1) on success, false(0) on error 88 | */ 89 | int ipfs_core_http_request_post(struct IpfsNode* local_node, struct HttpRequest* request, char** result, size_t* result_size, char *data, size_t data_size); 90 | -------------------------------------------------------------------------------- /include/ipfs/repo/config/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H__ 2 | #define __CONFIG_H__ 3 | 4 | #include "libp2p/db/datastore.h" 5 | #include "identity.h" 6 | #include "swarm.h" 7 | #include "bootstrap_peers.h" 8 | #include "addresses.h" 9 | #include "gateway.h" 10 | #include "replication.h" 11 | 12 | struct MDNS { 13 | int enabled; 14 | int interval; 15 | }; 16 | 17 | struct Discovery { 18 | struct MDNS mdns; 19 | }; 20 | 21 | struct Mounts { 22 | char* ipfs; 23 | char* ipns; 24 | }; 25 | 26 | struct Ipns { 27 | int resolve_cache_size; 28 | }; 29 | 30 | struct Reprovider { 31 | char* interval; 32 | }; 33 | 34 | struct RepoConfig { 35 | struct Identity* identity; 36 | struct Datastore* datastore; 37 | struct Filestore* filestore; 38 | struct Addresses* addresses; 39 | struct Mounts mounts; 40 | struct Discovery discovery; 41 | struct Ipns ipns; 42 | struct Libp2pVector* bootstrap_peers; // MultiAddresses 43 | //struct tour tour; 44 | struct Gateway* gateway; 45 | //struct supernode_routing supernode_client_config; 46 | //struct api api; 47 | struct Reprovider reprovider; 48 | struct Replication* replication; 49 | }; 50 | 51 | /** 52 | * provide the full path of the config file, given the directory. 53 | * NOTE: This allocates memory for result. Make sure to clean up after yourself. 54 | * @param path the path to the config file (without the actual file name) 55 | * @param result the full filename including the path 56 | * @returns true(1) on success, false(0) otherwise 57 | */ 58 | int repo_config_get_file_name(char* path, char** result); 59 | 60 | /*** 61 | * Returns the path "extension" relative to the configuration root. 62 | * If an empty string is provided for config_root, the default root 63 | * is used. 64 | * @param config_root the path to the root of the configuration 65 | * @param extension the extension to add to the path 66 | * @param result the result of config_root with extension appended 67 | * @param max_len the max length of the result 68 | * @returns true(1) if everything went okay, false(0) otherwise 69 | */ 70 | int config_path(char* config_root, char* extension, char* result, int max_len); 71 | 72 | /*** 73 | * create a configuration based on the passed in parameters 74 | * @param config the configuration struct 75 | * @param num_bits_for_keypair number of bits for the key pair 76 | * @param swarm_port port for swarm 77 | * @param bootstrap_peers a vector of Multiaddress of fellow peers 78 | * @returns true(1) on success, otherwise 0 79 | */ 80 | int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, const char* repo_path, int swarm_port, struct Libp2pVector *bootstrap_peers); 81 | 82 | /*** 83 | * Initialize memory for a RepoConfig struct 84 | * @param config the structure to initialize 85 | * @returns true(1) on success 86 | */ 87 | int ipfs_repo_config_new(struct RepoConfig** config); 88 | 89 | /*** 90 | * free all resources that were allocated to store config information 91 | * @param config the config 92 | * @returns true(1) 93 | */ 94 | int ipfs_repo_config_free(struct RepoConfig* config); 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /test/core/test_ping.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../test_helper.h" 5 | #include "multiaddr/multiaddr.h" 6 | #include "libp2p/peer/peerstore.h" 7 | #include "libp2p/peer/peer.h" 8 | #include "libp2p/record/message.h" 9 | #include "ipfs/core/daemon.h" 10 | #include "ipfs/core/ipfs_node.h" 11 | #include "ipfs/repo/fsrepo/fs_repo.h" 12 | #include "libp2p/conn/dialer.h" 13 | #include "ipfs/core/daemon.h" 14 | 15 | /** 16 | * Testing connectivity with other nodes 17 | */ 18 | 19 | int test_ping() { 20 | int retVal = 0; 21 | struct FSRepo* fs_repo = NULL; 22 | struct KademliaMessage* message = NULL; 23 | //struct IpfsNode local_node; 24 | struct Libp2pPeer* remote_peer = NULL; 25 | struct Dialer* dialer = NULL; 26 | struct Stream* conn = NULL; 27 | unsigned char* protobuf = NULL; 28 | size_t protobuf_size = 0; 29 | 30 | // act like this is a normal node 31 | drop_build_and_open_repo("/tmp/.ipfs", &fs_repo); 32 | 33 | // create a new IpfsNode 34 | /* 35 | local_node.mode = MODE_ONLINE; 36 | local_node.peerstore = libp2p_peerstore_new(); 37 | local_node.repo = fs_repo; 38 | local_node.identity = fs_repo->config->identity; 39 | */ 40 | 41 | // build the ping message 42 | message = libp2p_message_new(); 43 | message->message_type = MESSAGE_TYPE_PING; 44 | protobuf_size = libp2p_message_protobuf_encode_size(message); 45 | protobuf = (unsigned char*)malloc(protobuf_size); 46 | libp2p_message_protobuf_encode(message, protobuf, protobuf_size, &protobuf_size); 47 | libp2p_message_free(message); 48 | message = NULL; 49 | // ping a known node with a ping record 50 | // create the connection 51 | remote_peer = libp2p_peer_new(); 52 | remote_peer->id = "QmdMZoaL4azVzEPHYVH6imn3iPYYv6L1fLcH7Vd1aLbfSD"; 53 | remote_peer->id_size = strlen(remote_peer->id); 54 | remote_peer->addr_head = libp2p_utils_linked_list_new(); 55 | remote_peer->addr_head->item = multiaddress_new_from_string("/ip4/192.168.43.234/tcp/4001/"); 56 | 57 | // connect using a dialer 58 | dialer = libp2p_conn_dialer_new(fs_repo->config->identity->peer, NULL, NULL, NULL); 59 | conn = libp2p_conn_dialer_get_connection(dialer, remote_peer->addr_head->item); 60 | 61 | //TODO: Dialer should know the protocol 62 | 63 | // send the record 64 | struct StreamMessage msg; 65 | msg.data = (uint8_t*)protobuf; 66 | msg.data_size = protobuf_size; 67 | conn->write(conn->stream_context, &msg); 68 | struct StreamMessage* incoming_message = NULL; 69 | conn->read(conn->stream_context, &incoming_message, 10); 70 | libp2p_message_protobuf_decode(incoming_message->data, incoming_message->data_size, &message); 71 | // verify the response 72 | if (message->message_type != MESSAGE_TYPE_PING) 73 | goto exit; 74 | 75 | // clean up 76 | retVal = 1; 77 | exit: 78 | ipfs_repo_fsrepo_free(fs_repo); 79 | return retVal; 80 | } 81 | 82 | int test_ping_remote() { 83 | char* argv[] = { "ipfs", "ping", "QmTjg669YQemhffXLrkA3as9jT8SzyRtWaLXHKwYN6wCBd" }; 84 | int argc = 3; 85 | 86 | return ipfs_ping(argc, argv); 87 | } 88 | -------------------------------------------------------------------------------- /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 8 | #include 9 | #include 10 | //#include 11 | #include 12 | 13 | #include "ipfs/cmd/ipfs/init.h" 14 | #include "ipfs/commands/argument.h" 15 | #include "ipfs/commands/request.h" 16 | #include "ipfs/commands/command.h" 17 | #include "libp2p/os/utils.h" 18 | 19 | 20 | int test_init_new_installation() { 21 | unlink("/tmp/.ipfs/config"); 22 | // do the minimum to get the .ipfs directory structure and config file built 23 | struct Request request; 24 | int retVal = ipfs_cmd_ipfs_init_command_new( &request.cmd ); 25 | if (retVal == 0) 26 | return 0; 27 | 28 | // build a request so it builds the repository in the /tmp directory 29 | request.invoc_context = (struct Context*)malloc(sizeof(struct Context)); 30 | request.invoc_context->config_root = "/tmp/.ipfs"; 31 | 32 | // run the methods 33 | 34 | retVal = request.cmd.pre_run(&request); 35 | if (retVal == 0) { 36 | free(request.invoc_context); 37 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 38 | return 0; 39 | } 40 | 41 | retVal = request.cmd.run(&request); 42 | if (retVal == 0) { 43 | free(request.invoc_context); 44 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 45 | return 0; 46 | } 47 | 48 | retVal = request.cmd.post_run(&request); 49 | if (retVal == 0) { 50 | free(request.invoc_context); 51 | ipfs_cmd_ipfs_init_command_free(&request.cmd); 52 | return 0; 53 | } 54 | 55 | // clean up 56 | ipfs_cmd_ipfs_init_command_free( &request.cmd ); 57 | free(request.invoc_context); 58 | 59 | // make sure the repository exists 60 | retVal = os_utils_file_exists("/tmp/.ipfs/config"); 61 | 62 | return retVal; 63 | } 64 | 65 | /*** 66 | * This is used for the command line interpreter, which is still in development 67 | */ 68 | int test_get_init_command() { 69 | struct Command cmd = { 0 }; 70 | int retVal = 1; 71 | // make sure its empty 72 | if (cmd.help_text.tagline != NULL) { 73 | fprintf(stderr, "short description should be null\n"); 74 | return 0; 75 | } 76 | // grab the stuff 77 | retVal = ipfs_cmd_ipfs_init_command_new(&cmd); 78 | 79 | if (!retVal) { 80 | fprintf(stderr, "Function call to get_init_command not successful. Return was %d\n", retVal); 81 | return retVal; 82 | } 83 | // make sure its right 84 | if (cmd.help_text.tagline == NULL) { 85 | fprintf(stderr, "short description is null\n"); 86 | retVal = 0; 87 | } else if (strcmp(cmd.help_text.tagline, "Initializes IPFS config file.") != 0) { 88 | fprintf(stderr, "short description is not null\n"); 89 | retVal = 0; 90 | } else if (cmd.argument_count != 1) { 91 | fprintf(stderr, "argument count should be 1"); 92 | retVal = 0; 93 | } else { 94 | struct Argument arg1 = *(cmd.arguments[0]); 95 | if (strncmp(arg1.name, "default-config", 14) != 0) { 96 | fprintf(stderr, "arg1 wrong name. Expected %s but got %s\n", "default_config", arg1.name); 97 | retVal = 0; 98 | } 99 | } 100 | ipfs_cmd_ipfs_init_command_free(&cmd); 101 | return retVal; 102 | } 103 | 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /test/config.test1.wo_journal: -------------------------------------------------------------------------------- 1 | { 2 | "Identity": { 3 | "PeerID": "QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4", 4 | "PrivKey": "CAASpgkwggSiAgEAAoIBAQCApYAN/RWPZqfuLp96dB7wyR11r58Yy2v7l0ebAW/Sq5zBtg6Jrvmg5Nwx9lLUWa75VmwC6B+70cbdE7g+668VknjkyDxODYimGMsMeAcr0IKRludPjSYThbP3UOmeQdu+5ifSBcJ9Atsr/b1kNSntEyixm33boUIv+m2VI5rU9I81bzbPsnBEx4I4BDduJB/tJ0SSCQs3SQJdFtj+XoypZeShtPW/L2p8K9q/GI6dLNxHIKqJwaED6gBhmlRHAA9hqV3RJZ1Hh9ztYa9IM1k13A7SjvedDIdqrAIlAAUW2uKO1HiAEyLCykPqZsm/y8f4tfsHjnSk3RpDhaNlRGX5AgMBAAECggEAKWcaQ2ZEXhaHzVwr71kX7B6N4KZY6b3uTtZtMTHRL1gT5zQUkbNCm8mMJHhGSBlk+tIZiQXz0Jq/Cb+i+H0ZqDOvvNHEtsocRHiOQMEQbcV5gCm04CFpM7dAKEReK5S+iD3CaxF3eoxExW+wWGPTznzwB9knNFw91Psf8XO4DPkBAZfe3prmiKBDg74Cy1hAzBHGp15/4oU9gyaZop0Oe1UA+NEeGCTZgDcIOLYbPjH6tRF0xw2Usuh2IiwkUqrdRWwO0ZlaBD9jSCxQ4evbgIAOtni0+qbbeIlXQGPn3XFSZjwsdS7b/CPe8Gbtoy+akuoHOV9Rje/0ZAJTN4KjQQKBgQDgH76D7yr57Tcga18EoWJcGJvvvt/m0NfjtSoz901uK60qf5MnNbUXYKF33j5XW9V9+WRde0IqxZkwDIAuk6Bx/oYqI/DgvQ/Me/8np4R7K6Tjb3PNtHCGNtuGU2qJthCcCZ629lej3y5bwLtwfhjUwHSRzwQXlnJnHa49KZ1AvQKBgQCS8XY9aA6cBaCk8WDoTxMVSrr5P0QMKWbgHqylsUvZsTCj07+Ob87gnZjyGgPfIn9pF9gMeuExyHj/+c1P54Z0dPBeL4KQx1UpvgyJTLuFe1csR2Q8qAp6GOiEojXJ0Tc4yUsVwSKmCCsW9f2EiXCP24TqwedllfKoazvbaJZD7QKBgCjugzvTNTUZ1qSMF3lgA/ev4uLBKGEeKR+EGaYN9000mtaVIAncLCuN0U9z/ky0D+SG5IaSGT54ggadcdePzJClHFmb4MUaokUFLE9Qr8hS6zVCSJL77kUExcjdeSqXXqcwtpTRnqXl/7BwHYto7B4G3AM5HJU2O8SLTiQLcpW9AoGASXYl4rUu+Jlnoo56ICnIJJDjwM/8OQhJwioTrhJhFUgcRQsLbS5AgtLHL+IJpXgdsnCVNkgIZVcQBwjft97LvVTpBm1CHRdKYD//DHUsGqN7BUv7tMdd1YS2WfiuY2MQ9HbN7uZLaC4VPLlmMOh1ObZJUQP3pzW7xq81kY9L8FECgYA92LvEamYLzbisdb6XvA6d5+jUXtt3v8/2e1tNKSUuvBCLxWy5IqObgHTCaCHJH8E/bAEmOVaxXdzpS484Q8Hbai+NBVjnPB/yINCN4WgScBRFr3691HeQ1ejeEKSzELg1QDau7jo7CSZFO1ZHCR01T7HZCrcuLaG7DxAx/Y+i8A==" 5 | }, 6 | "Datastore": { 7 | "Type": "lmdb", 8 | "Path": "/tmp/ipfs_1/datastore", 9 | "StorageMax": "10GB", 10 | "StorageGCWatermark": 90, 11 | "GCPeriod": "1h", 12 | "Params": null, 13 | "NoSync": false, 14 | "HashOnRead": false, 15 | "BloomFilterSize": 0 16 | }, 17 | "Addresses": { 18 | "Swarm": [ 19 | "/ip4/0.0.0.0/tcp/4001", 20 | "/ip6/::/tcp/4001" 21 | ], 22 | "API": "/ip4/127.0.0.1/tcp/5001", 23 | "Gateway": "/ip4/127.0.0.1/tcp/8080" 24 | }, 25 | "Mounts": { 26 | "IPFS": "/ipfs", 27 | "IPNS": "/ipns", 28 | "FuseAllowOther": false 29 | }, 30 | "Discovery": { 31 | "MDNS": { 32 | "Enabled": true, 33 | "Interval": 10 34 | } 35 | }, 36 | "Ipns": { 37 | "RepublishedPeriod": "", 38 | "RecordLifetime": "", 39 | "ResolveCacheSize": 128 40 | }, 41 | "Bootstrap": [ 42 | "/ip4/127.0.0.1/tcp/4002/ipfs/QmcDW1t4QQBGAs2HSig8xkUhPxFZzmewAeFdsmp6q6nyY5" 43 | ], 44 | "Tour": { 45 | "Last": "" 46 | }, 47 | "Gateway": { 48 | "HTTPHeaders": { 49 | "Access-Control-Allow-Origin": [ 50 | "*" 51 | ], 52 | "Access-Control-Allow-Methods": [ 53 | "GET" 54 | ], 55 | "Access-Control-Allow-Headers": [ 56 | "X-Requested-With" 57 | ] 58 | }, 59 | "RootRedirect": "" 60 | "Writable": false 61 | "PathPrefixes": [] 62 | }, 63 | "SupernodeRouting": { 64 | "Servers": null 65 | }, "API": { 66 | "HTTPHeaders": null 67 | }, 68 | "Swarm": { 69 | "AddrFilters": null 70 | }, 71 | "Replication": { 72 | "Announce": 1, 73 | "AnnounceMinutes": 60, 74 | "Peers": [ 75 | ] 76 | } 77 | } -------------------------------------------------------------------------------- /test/config.test2.wo_journal: -------------------------------------------------------------------------------- 1 | { 2 | "Identity": { 3 | "PeerID": "QmcDW1t4QQBGAs2HSig8xkUhPxFZzmewAeFdsmp6q6nyY5", 4 | "PrivKey": "CAASqQkwggSlAgEAAoIBAQDqghv+79zy4dcP+8GCSa9kfoD9zF1gpOO/gnfjLUd9BTzY1MXX7pzGsztRnLOFtuSAqZmg9iEgnrNbLpGqYdHxSRU7taHv2+aAjE4yU6epP9NWaS3kC06NRzpcH4M+sIXYheioEJrOb4OGnz5KZuAAmRu/0gg+HSHeZTVNz3cRgg1fvpeG68UGSjLhIXg4jYjCso0KOdTZDTKkVqFqDyKJOgDPEGF5sS024Z33Wpkn6+MTX0xIUfn4eKIJztmt7g7/2zi3OnsKmfj7lmh77R93F88hGN5i2g6/GYY6qfQ4HJ/RxEGzXtt+r+jNlV4zGFSAWfR7vBklkGnyL041ewRpAgMBAAECggEAQ/C8AakmfyuU7imHD6MfcGMCJgWOTBCZdwNqjmOw4XSiA0PpqbyUqTCGEAfxLt0k6G26d5q3UEcKOXGNfCpo85mz0B+4MdCowDdl9EiuO2elZ9SDGh14fY/URZpPoNrtfCSXmhFteD9wgJEkL9QMM8An/PPxtWUlSdRSlB92JJjWI5RiPx8u9jVNqsjp/t/Pe3oQ4HvuFXBmSjdRQh7uIvgKC28DMcuROZPRhCAcUcWSp8plYjXmEV1yxip+Bt/oFqS7+LivFc4GdoxdOHTqDE731EjQ3UqKas7CJCjpFE+dy7QnUQr2oN/teXVuNgSO82xZkkk514IrqymOB2mQHQKBgQD2O6ZYpygpcUJ2NeOuPbhHkGreRK3ms2H1n+AgSjHd9SGbaip133S8fMnlv2/4FPaav3/N1wNUR01Cgf6nENj8bUR8n4M0esr7GozN7ACKS1jnPU9vIWDSZMoiV1bhA8rsUSmG4NSS966mW9Gf4R8vGGMffKyFfWdGNBlurag+zwKBgQDzz2bJMDzfNQdA1zb7qs0UR+0ZiRCboHOEYz1UmRYs/409ILbbQ4fdC/JiWLZE4SdaMAVyKjwojbq4uaR7x8iZFYz6cehiC/wTMBOf6tZsaLcY7HmBgpqjCK6lyyYiHQ0/PCON1z3vHGNXz0GjR+sHqb5Fct5IE0TN3Ym+IkMXRwKBgQCpIOmuZQpyBMiI15UOvngQN8Mf7n6gQsBbbTgOFchQ06oEzRRjKFxPh0tKUob/GK8WNcj8Qt6Xie4oa4/Vgv33zLnI++usJVe8yEzEuIDafMyQ8IzaIUwW14H7upADOI6uaUUjztRUKmo8/D5tGb1IpPCY1RLPEgbYsrpxSjiRAwKBgQDpcSY7cIJ4PW/qd6ZfpZSi3JN6pbBPMnwowFSS0dlX0IBNjStIGgrWbX/xBnvOy75ALkaonyPmuH2WLbn+ArZhTS8lBTe52TvMq3W+4r3YIxNdO97DUGf7vm5qtG6YrzRl3ZE1WGgmsAm2o+13B39UYQSbvnZykHCKpJokgO24NQKBgQDbb3U0Xy5gceTR5XbYUkdkPj0kxEMtYzTXh30dztTld2dKDIbAtVe8t2zinNuLUCqpu5+lCCN3qiYCNWEB5NZp6jAra6wzz483clw30sMYdtwh1NnTqP+i6WbxXagSamwp2555Xc7n3BpnX68BpoTi2cmPjWHhBGFjoOTLxI4ZQQ==" 5 | }, 6 | "Datastore": { 7 | "Type": "lmdb", 8 | "Path": "/tmp/ipfs_2/datastore", 9 | "StorageMax": "10GB", 10 | "StorageGCWatermark": 90, 11 | "GCPeriod": "1h", 12 | "Params": null, 13 | "NoSync": false, 14 | "HashOnRead": false, 15 | "BloomFilterSize": 0 16 | }, 17 | "Addresses": { 18 | "Swarm": [ 19 | "/ip4/0.0.0.0/tcp/4002", 20 | "/ip6/::/tcp/4002" 21 | ], 22 | "API": "/ip4/127.0.0.1/tcp/5002", 23 | "Gateway": "/ip4/127.0.0.1/tcp/8080" 24 | }, 25 | "Mounts": { 26 | "IPFS": "/ipfs", 27 | "IPNS": "/ipns", 28 | "FuseAllowOther": false 29 | }, 30 | "Discovery": { 31 | "MDNS": { 32 | "Enabled": true, 33 | "Interval": 10 34 | } 35 | }, 36 | "Ipns": { 37 | "RepublishedPeriod": "", 38 | "RecordLifetime": "", 39 | "ResolveCacheSize": 128 40 | }, 41 | "Bootstrap": [ 42 | "/ip4/127.0.0.1/tcp/4001/ipfs/QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4" 43 | ], 44 | "Tour": { 45 | "Last": "" 46 | }, 47 | "Gateway": { 48 | "HTTPHeaders": { 49 | "Access-Control-Allow-Origin": [ 50 | "*" 51 | ], 52 | "Access-Control-Allow-Methods": [ 53 | "GET" 54 | ], 55 | "Access-Control-Allow-Headers": [ 56 | "X-Requested-With" 57 | ] 58 | }, 59 | "RootRedirect": "" 60 | "Writable": false 61 | "PathPrefixes": [] 62 | }, 63 | "SupernodeRouting": { 64 | "Servers": null 65 | }, "API": { 66 | "HTTPHeaders": null 67 | }, 68 | "Swarm": { 69 | "AddrFilters": null 70 | }, 71 | "Replication": { 72 | "Announce": 1, 73 | "AnnounceMinutes": 60, 74 | "Peers": [ 75 | ] 76 | } 77 | } -------------------------------------------------------------------------------- /include/ipfs/exchange/bitswap/bitswap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*** 4 | * Bitswap implements the "exchange" and "Libp2pProtocolHandler" interfaces 5 | * @see ../exchange.h 6 | * @see libp2p/net/protocol.h 7 | */ 8 | 9 | #include "libp2p/net/protocol.h" 10 | #include "ipfs/core/ipfs_node.h" 11 | #include "ipfs/exchange/exchange.h" 12 | #include "ipfs/exchange/bitswap/engine.h" 13 | #include "ipfs/exchange/bitswap/wantlist_queue.h" 14 | 15 | struct Libp2pProtocolHandler* ipfs_bitswap_build_protocol_handler(const struct IpfsNode* local_node); 16 | 17 | 18 | struct BitswapContext { 19 | struct IpfsNode* ipfsNode; 20 | struct WantListQueue* localWantlist; 21 | struct PeerRequestQueue* peerRequestQueue; 22 | struct BitswapEngine* bitswap_engine; 23 | }; 24 | 25 | /** 26 | * Start up the bitswap exchange 27 | * @param ipfsNode the context 28 | * @returns an Exchange struct that refers to the exchange 29 | */ 30 | struct Exchange* ipfs_bitswap_new(struct IpfsNode* ipfsNode); 31 | 32 | /*** 33 | * These are the implementation methods for the exchange "Interface" 34 | */ 35 | 36 | /*** 37 | * Checks to see if the Bitswap service is online 38 | * @param exhcnageContext a pointer to a BitswapContext 39 | * @reutrns true(1) if online, false(0) otherwise. 40 | */ 41 | int ipfs_bitswap_is_online(struct Exchange* exchange); 42 | 43 | /*** 44 | * Closes down the Bitswap network 45 | * @param exchangeContext a pointer to a BitswapContext 46 | * @returns true(1) 47 | */ 48 | int ipfs_bitswap_close(struct Exchange* exchange); 49 | 50 | /**** 51 | * Notify the BitswapNetwork that we have this block 52 | * @param exchangeContext a pointer to a BitswapContext 53 | * @block the block that we have 54 | * @reutrns true(1) if successful, false(0) if not. 55 | */ 56 | int ipfs_bitswap_has_block(struct Exchange* exchange, struct Block* block); 57 | 58 | /** 59 | * Retrieve a block from the BitswapNetwork 60 | * Note: This may pull the file from the local blockstore. 61 | * Note: If false(0) is returned, block will be NULL 62 | * 63 | * @param exchangeContext a pointer to a BitswapContext 64 | * @param cid the Cid of the block we're looking for 65 | * @param block a pointer to the block when we find it. 66 | * @returns true(1) on success, false(0) otherwise. 67 | */ 68 | int ipfs_bitswap_get_block(struct Exchange* exchange, struct Cid* cid, struct Block** block); 69 | 70 | /** 71 | * Retrieve a block from the BitswapNetwork 72 | * 73 | * @param exchangeContext a pointer to a BitswapContext 74 | * @param cid the Cid of the block we're looking for 75 | * @param queue a pointer to the queue that will change if the block arrives 76 | * @returns true(1) on success, false(0) otherwise. 77 | */ 78 | int ipfs_bitswap_get_block_async(struct Exchange* exchange, struct Cid* cid, struct Block** block); 79 | 80 | /*** 81 | * Retrieve a collection of blocks from the BitswapNetwork 82 | * Note: The return of false(0) means that not all blocks were found. 83 | * 84 | * @param exchangeContext a pointer to a BitswapContext 85 | * @param cids a collection of Cid structs 86 | * @param blocks a collection that contains the results. 87 | * @param true(1) on success, false(0) otherwise 88 | */ 89 | int ipfs_bitswap_get_blocks(struct Exchange* exchange, struct Libp2pVector* cids, struct Libp2pVector** blocks); 90 | -------------------------------------------------------------------------------- /test/config.test1: -------------------------------------------------------------------------------- 1 | { 2 | "Identity": { 3 | "PeerID": "QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4", 4 | "PrivKey": "CAASpgkwggSiAgEAAoIBAQCApYAN/RWPZqfuLp96dB7wyR11r58Yy2v7l0ebAW/Sq5zBtg6Jrvmg5Nwx9lLUWa75VmwC6B+70cbdE7g+668VknjkyDxODYimGMsMeAcr0IKRludPjSYThbP3UOmeQdu+5ifSBcJ9Atsr/b1kNSntEyixm33boUIv+m2VI5rU9I81bzbPsnBEx4I4BDduJB/tJ0SSCQs3SQJdFtj+XoypZeShtPW/L2p8K9q/GI6dLNxHIKqJwaED6gBhmlRHAA9hqV3RJZ1Hh9ztYa9IM1k13A7SjvedDIdqrAIlAAUW2uKO1HiAEyLCykPqZsm/y8f4tfsHjnSk3RpDhaNlRGX5AgMBAAECggEAKWcaQ2ZEXhaHzVwr71kX7B6N4KZY6b3uTtZtMTHRL1gT5zQUkbNCm8mMJHhGSBlk+tIZiQXz0Jq/Cb+i+H0ZqDOvvNHEtsocRHiOQMEQbcV5gCm04CFpM7dAKEReK5S+iD3CaxF3eoxExW+wWGPTznzwB9knNFw91Psf8XO4DPkBAZfe3prmiKBDg74Cy1hAzBHGp15/4oU9gyaZop0Oe1UA+NEeGCTZgDcIOLYbPjH6tRF0xw2Usuh2IiwkUqrdRWwO0ZlaBD9jSCxQ4evbgIAOtni0+qbbeIlXQGPn3XFSZjwsdS7b/CPe8Gbtoy+akuoHOV9Rje/0ZAJTN4KjQQKBgQDgH76D7yr57Tcga18EoWJcGJvvvt/m0NfjtSoz901uK60qf5MnNbUXYKF33j5XW9V9+WRde0IqxZkwDIAuk6Bx/oYqI/DgvQ/Me/8np4R7K6Tjb3PNtHCGNtuGU2qJthCcCZ629lej3y5bwLtwfhjUwHSRzwQXlnJnHa49KZ1AvQKBgQCS8XY9aA6cBaCk8WDoTxMVSrr5P0QMKWbgHqylsUvZsTCj07+Ob87gnZjyGgPfIn9pF9gMeuExyHj/+c1P54Z0dPBeL4KQx1UpvgyJTLuFe1csR2Q8qAp6GOiEojXJ0Tc4yUsVwSKmCCsW9f2EiXCP24TqwedllfKoazvbaJZD7QKBgCjugzvTNTUZ1qSMF3lgA/ev4uLBKGEeKR+EGaYN9000mtaVIAncLCuN0U9z/ky0D+SG5IaSGT54ggadcdePzJClHFmb4MUaokUFLE9Qr8hS6zVCSJL77kUExcjdeSqXXqcwtpTRnqXl/7BwHYto7B4G3AM5HJU2O8SLTiQLcpW9AoGASXYl4rUu+Jlnoo56ICnIJJDjwM/8OQhJwioTrhJhFUgcRQsLbS5AgtLHL+IJpXgdsnCVNkgIZVcQBwjft97LvVTpBm1CHRdKYD//DHUsGqN7BUv7tMdd1YS2WfiuY2MQ9HbN7uZLaC4VPLlmMOh1ObZJUQP3pzW7xq81kY9L8FECgYA92LvEamYLzbisdb6XvA6d5+jUXtt3v8/2e1tNKSUuvBCLxWy5IqObgHTCaCHJH8E/bAEmOVaxXdzpS484Q8Hbai+NBVjnPB/yINCN4WgScBRFr3691HeQ1ejeEKSzELg1QDau7jo7CSZFO1ZHCR01T7HZCrcuLaG7DxAx/Y+i8A==" 5 | }, 6 | "Datastore": { 7 | "Type": "lmdb", 8 | "Path": "/tmp/ipfs_1/datastore", 9 | "StorageMax": "10GB", 10 | "StorageGCWatermark": 90, 11 | "GCPeriod": "1h", 12 | "Params": null, 13 | "NoSync": false, 14 | "HashOnRead": false, 15 | "BloomFilterSize": 0 16 | }, 17 | "Addresses": { 18 | "Swarm": [ 19 | "/ip4/0.0.0.0/tcp/4001", 20 | "/ip6/::/tcp/4001" 21 | ], 22 | "API": "/ip4/127.0.0.1/tcp/5002", 23 | "Gateway": "/ip4/127.0.0.1/tcp/8080" 24 | }, 25 | "Mounts": { 26 | "IPFS": "/ipfs", 27 | "IPNS": "/ipns", 28 | "FuseAllowOther": false 29 | }, 30 | "Discovery": { 31 | "MDNS": { 32 | "Enabled": true, 33 | "Interval": 10 34 | } 35 | }, 36 | "Ipns": { 37 | "RepublishedPeriod": "", 38 | "RecordLifetime": "", 39 | "ResolveCacheSize": 128 40 | }, 41 | "Bootstrap": [ 42 | "/ip4/127.0.0.1/tcp/4002/ipfs/QmcDW1t4QQBGAs2HSig8xkUhPxFZzmewAeFdsmp6q6nyY5" 43 | ], 44 | "Tour": { 45 | "Last": "" 46 | }, 47 | "Gateway": { 48 | "HTTPHeaders": { 49 | "Access-Control-Allow-Origin": [ 50 | "*" 51 | ], 52 | "Access-Control-Allow-Methods": [ 53 | "GET" 54 | ], 55 | "Access-Control-Allow-Headers": [ 56 | "X-Requested-With" 57 | ] 58 | }, 59 | "RootRedirect": "" 60 | "Writable": false 61 | "PathPrefixes": [] 62 | }, 63 | "SupernodeRouting": { 64 | "Servers": null 65 | }, "API": { 66 | "HTTPHeaders": null 67 | }, 68 | "Swarm": { 69 | "AddrFilters": null 70 | }, 71 | "Replication": { 72 | "Announce": 1, 73 | "AnnounceMinutes": 60, 74 | "Peers": [ 75 | "/ip4/127.0.0.1/tcp/4002/ipfs/QmcDW1t4QQBGAs2HSig8xkUhPxFZzmewAeFdsmp6q6nyY5" 76 | ] 77 | } 78 | } -------------------------------------------------------------------------------- /test/config.test2: -------------------------------------------------------------------------------- 1 | { 2 | "Identity": { 3 | "PeerID": "QmcDW1t4QQBGAs2HSig8xkUhPxFZzmewAeFdsmp6q6nyY5", 4 | "PrivKey": "CAASqQkwggSlAgEAAoIBAQDqghv+79zy4dcP+8GCSa9kfoD9zF1gpOO/gnfjLUd9BTzY1MXX7pzGsztRnLOFtuSAqZmg9iEgnrNbLpGqYdHxSRU7taHv2+aAjE4yU6epP9NWaS3kC06NRzpcH4M+sIXYheioEJrOb4OGnz5KZuAAmRu/0gg+HSHeZTVNz3cRgg1fvpeG68UGSjLhIXg4jYjCso0KOdTZDTKkVqFqDyKJOgDPEGF5sS024Z33Wpkn6+MTX0xIUfn4eKIJztmt7g7/2zi3OnsKmfj7lmh77R93F88hGN5i2g6/GYY6qfQ4HJ/RxEGzXtt+r+jNlV4zGFSAWfR7vBklkGnyL041ewRpAgMBAAECggEAQ/C8AakmfyuU7imHD6MfcGMCJgWOTBCZdwNqjmOw4XSiA0PpqbyUqTCGEAfxLt0k6G26d5q3UEcKOXGNfCpo85mz0B+4MdCowDdl9EiuO2elZ9SDGh14fY/URZpPoNrtfCSXmhFteD9wgJEkL9QMM8An/PPxtWUlSdRSlB92JJjWI5RiPx8u9jVNqsjp/t/Pe3oQ4HvuFXBmSjdRQh7uIvgKC28DMcuROZPRhCAcUcWSp8plYjXmEV1yxip+Bt/oFqS7+LivFc4GdoxdOHTqDE731EjQ3UqKas7CJCjpFE+dy7QnUQr2oN/teXVuNgSO82xZkkk514IrqymOB2mQHQKBgQD2O6ZYpygpcUJ2NeOuPbhHkGreRK3ms2H1n+AgSjHd9SGbaip133S8fMnlv2/4FPaav3/N1wNUR01Cgf6nENj8bUR8n4M0esr7GozN7ACKS1jnPU9vIWDSZMoiV1bhA8rsUSmG4NSS966mW9Gf4R8vGGMffKyFfWdGNBlurag+zwKBgQDzz2bJMDzfNQdA1zb7qs0UR+0ZiRCboHOEYz1UmRYs/409ILbbQ4fdC/JiWLZE4SdaMAVyKjwojbq4uaR7x8iZFYz6cehiC/wTMBOf6tZsaLcY7HmBgpqjCK6lyyYiHQ0/PCON1z3vHGNXz0GjR+sHqb5Fct5IE0TN3Ym+IkMXRwKBgQCpIOmuZQpyBMiI15UOvngQN8Mf7n6gQsBbbTgOFchQ06oEzRRjKFxPh0tKUob/GK8WNcj8Qt6Xie4oa4/Vgv33zLnI++usJVe8yEzEuIDafMyQ8IzaIUwW14H7upADOI6uaUUjztRUKmo8/D5tGb1IpPCY1RLPEgbYsrpxSjiRAwKBgQDpcSY7cIJ4PW/qd6ZfpZSi3JN6pbBPMnwowFSS0dlX0IBNjStIGgrWbX/xBnvOy75ALkaonyPmuH2WLbn+ArZhTS8lBTe52TvMq3W+4r3YIxNdO97DUGf7vm5qtG6YrzRl3ZE1WGgmsAm2o+13B39UYQSbvnZykHCKpJokgO24NQKBgQDbb3U0Xy5gceTR5XbYUkdkPj0kxEMtYzTXh30dztTld2dKDIbAtVe8t2zinNuLUCqpu5+lCCN3qiYCNWEB5NZp6jAra6wzz483clw30sMYdtwh1NnTqP+i6WbxXagSamwp2555Xc7n3BpnX68BpoTi2cmPjWHhBGFjoOTLxI4ZQQ==" 5 | }, 6 | "Datastore": { 7 | "Type": "lmdb", 8 | "Path": "/tmp/ipfs_2/datastore", 9 | "StorageMax": "10GB", 10 | "StorageGCWatermark": 90, 11 | "GCPeriod": "1h", 12 | "Params": null, 13 | "NoSync": false, 14 | "HashOnRead": false, 15 | "BloomFilterSize": 0 16 | }, 17 | "Addresses": { 18 | "Swarm": [ 19 | "/ip4/0.0.0.0/tcp/4002", 20 | "/ip6/::/tcp/4002" 21 | ], 22 | "API": "/ip4/127.0.0.1/tcp/5002", 23 | "Gateway": "/ip4/127.0.0.1/tcp/8080" 24 | }, 25 | "Mounts": { 26 | "IPFS": "/ipfs", 27 | "IPNS": "/ipns", 28 | "FuseAllowOther": false 29 | }, 30 | "Discovery": { 31 | "MDNS": { 32 | "Enabled": true, 33 | "Interval": 10 34 | } 35 | }, 36 | "Ipns": { 37 | "RepublishedPeriod": "", 38 | "RecordLifetime": "", 39 | "ResolveCacheSize": 128 40 | }, 41 | "Bootstrap": [ 42 | "/ip4/127.0.0.1/tcp/4001/ipfs/QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4" 43 | ], 44 | "Tour": { 45 | "Last": "" 46 | }, 47 | "Gateway": { 48 | "HTTPHeaders": { 49 | "Access-Control-Allow-Origin": [ 50 | "*" 51 | ], 52 | "Access-Control-Allow-Methods": [ 53 | "GET" 54 | ], 55 | "Access-Control-Allow-Headers": [ 56 | "X-Requested-With" 57 | ] 58 | }, 59 | "RootRedirect": "" 60 | "Writable": false 61 | "PathPrefixes": [] 62 | }, 63 | "SupernodeRouting": { 64 | "Servers": null 65 | }, "API": { 66 | "HTTPHeaders": null 67 | }, 68 | "Swarm": { 69 | "AddrFilters": null 70 | }, 71 | "Replication": { 72 | "Announce": 1, 73 | "AnnounceMinutes": 60, 74 | "Peers": [ 75 | "/ip4/127.0.0.1/tcp/4001/ipfs/QmZVoAZGFfinB7MQQiDzB84kWaDPQ95GLuXdemJFM2r9b4" 76 | ] 77 | } 78 | } -------------------------------------------------------------------------------- /include/ipfs/unixfs/unixfs.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * A unix-like file system over IPFS blocks 3 | */ 4 | 5 | #pragma once 6 | 7 | /** 8 | * The protobuf info: 9 | * message Data { 10 | * enum DataType { 11 | * Raw = 0; 12 | * Directory = 1; 13 | * File = 2; 14 | * Metadata = 3; 15 | * Symlink = 4; 16 | * } 17 | * 18 | * required DataType Type = 1; 19 | * optional bytes Data = 2; 20 | * optional uint64 filesize = 3; 21 | * repeated uint64 blocksizes = 4; 22 | * } 23 | * 24 | * message Metadata { 25 | * optional string MimeType = 1; 26 | * } 27 | */ 28 | 29 | enum UnixFSDataType { 30 | UNIXFS_RAW, 31 | UNIXFS_DIRECTORY, 32 | UNIXFS_FILE, 33 | UNIXFS_METADATA, 34 | UNIXFS_SYMLINK 35 | }; 36 | 37 | struct UnixFSBlockSizeNode { 38 | size_t block_size; 39 | struct UnixFSBlockSizeNode* next; 40 | }; 41 | 42 | struct UnixFS { 43 | enum UnixFSDataType data_type; 44 | size_t bytes_size; // the size of the bytes array 45 | unsigned char* bytes; // an array of bytes 46 | size_t file_size; // when saving files that have been chunked 47 | struct UnixFSBlockSizeNode* block_size_head; // a linked list of block sizes 48 | unsigned char* hash; // not saved 49 | size_t hash_length; // not saved 50 | }; 51 | 52 | struct UnixFSMetaData { 53 | char* mime_type; 54 | }; 55 | 56 | /** 57 | * Allocate memory for a new UnixFS struct 58 | * @param obj the pointer to the new object 59 | * @returns true(1) on success 60 | */ 61 | int ipfs_unixfs_new(struct UnixFS** obj); 62 | 63 | /*** 64 | * Free the resources used by a UnixFS struct 65 | * @param obj the struct to free 66 | * @returns true(1) 67 | */ 68 | int ipfs_unixfs_free(struct UnixFS* obj); 69 | 70 | /*** 71 | * Write data to data section of a UnixFS stuct. NOTE: this also calculates a sha256 hash 72 | * @param data the data to write 73 | * @param data_length the length of the data 74 | * @param unix_fs the struct to add to 75 | * @returns true(1) on success 76 | */ 77 | int ipfs_unixfs_add_data(unsigned char* data, size_t data_length, struct UnixFS* unix_fs); 78 | 79 | int ipfs_unixfs_add_blocksize(const struct UnixFSBlockSizeNode* blocksize, struct UnixFS* unix_fs); 80 | 81 | /** 82 | * Protobuf functions 83 | */ 84 | 85 | /** 86 | * Calculate the max size of the protobuf before encoding 87 | * @param obj what will be encoded 88 | * @returns the size of the buffer necessary to encode the object 89 | */ 90 | size_t ipfs_unixfs_protobuf_encode_size(const struct UnixFS* obj); 91 | 92 | /*** 93 | * Encode a UnixFS object into protobuf format 94 | * @param incoming the incoming object 95 | * @param outgoing where the bytes will be placed 96 | * @param max_buffer_size the size of the outgoing buffer 97 | * @param bytes_written how many bytes were written in the buffer 98 | * @returns true(1) on success 99 | */ 100 | int ipfs_unixfs_protobuf_encode(const struct UnixFS* incoming, unsigned char* outgoing, size_t max_buffer_size, size_t* bytes_written); 101 | 102 | /*** 103 | * Decodes a protobuf array of bytes into a UnixFS object 104 | * @param incoming the array of bytes 105 | * @param incoming_size the length of the array 106 | * @param outgoing the UnixFS object 107 | */ 108 | int ipfs_unixfs_protobuf_decode(unsigned char* incoming, size_t incoming_size, struct UnixFS** outgoing); 109 | -------------------------------------------------------------------------------- /include/ipfs/exchange/bitswap/network.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * This implements the BitswapNetwork. Members of this network can fill requests and 3 | * smartly handle queues of local and remote requests. 4 | */ 5 | 6 | #include "libp2p/conn/session.h" 7 | #include "libp2p/peer/peer.h" 8 | #include "ipfs/exchange/bitswap/bitswap.h" 9 | #include "ipfs/exchange/bitswap/message.h" 10 | 11 | struct BitswapRouting { 12 | /** 13 | * Find the provider of a key asyncronously 14 | * @param context the session context 15 | * @param hash the key we're looking for 16 | * @param forWhat I have yet to research this 17 | * @param responseMethod a function pointer to call when results are found 18 | * @returns true(1) on success, otherwise false(0) 19 | */ 20 | int (*FindProviderAsync)(struct SessionContext* context, unsigned char* hash, int forWhat, void (*responseMethod)(void*)); 21 | 22 | /** 23 | * Provides the key to the network. Is this an announcement or a fill? 24 | * I think it is an announcement 25 | * @param context the session context 26 | * @param hash the hash to announce 27 | * @returns true(1) on success, false(0) on error 28 | */ 29 | int (*Provide)(struct SessionContext* context, unsigned char* hash); 30 | }; 31 | 32 | struct BitswapNetwork { 33 | /*** 34 | * Send a message to a particular peer 35 | * @param context the context 36 | * @param peerId the peer ID of who to send to 37 | * @param message the message to send 38 | * @returns true(1) on success, false(0) otherwise 39 | */ 40 | int (*SendMessage)(struct SessionContext* context, unsigned char* peerId, struct BitswapMessage* message); 41 | 42 | /** 43 | * The BitswapReceiver is who receives messages from the network 44 | * @param receiver the struct that contains function pointers for receiving messages 45 | * @returns true(1) on success, otherwise false(0) 46 | */ 47 | //TODO: Implement this 48 | //int (*SetDelegate)(struct BitswapReceiver* receiver); 49 | 50 | /** 51 | * Attempt a connection to a particular peer 52 | * @param context the session context 53 | * @param peerId the id of the peer 54 | * @returns true(1) on success, otherwise false(0) 55 | */ 56 | int (*ConnectTo)(struct SessionContext* context, unsigned char* peerId); 57 | 58 | /** 59 | * A pointer to the method that creates a new BitswapMessageSender 60 | * @param context the session context 61 | * @param peerId the peer id of whom we should send the message to. 62 | * @reutrns a pointer to the allocated struct that contains the initialized BitswapMessageSender or NULL if there was a problem 63 | */ 64 | struct BitswapMessageSender* (*NewMessageSender)(struct SessionContext* context, unsigned char* peerId); 65 | }; 66 | 67 | /**** 68 | * send a message to a particular peer 69 | * @param context the BitswapContext 70 | * @param peer the peer that is the recipient 71 | * @param message the message to send 72 | */ 73 | int ipfs_bitswap_network_send_message(const struct BitswapContext* context, struct Libp2pPeer* peer, const struct BitswapMessage* message); 74 | 75 | /*** 76 | * Handle a raw incoming bitswap message from the network 77 | * @param node us 78 | * @param sessionContext the connection context 79 | * @param bytes the message 80 | * @param bytes_size the size of the message 81 | * @returns true(1) on success, false(0) otherwise. 82 | */ 83 | int ipfs_bitswap_network_handle_message(const struct IpfsNode* node, const struct SessionContext* sessionContext, const uint8_t* bytes, size_t bytes_length); 84 | --------------------------------------------------------------------------------