diff --git a/Makefile b/Makefile index 4aa1e2f..778029a 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ all: cd os; make all; cd repo; make all; cd flatfs; make all; + cd datastore; make all; cd thirdparty; make all; cd test; make all; @@ -23,6 +24,7 @@ clean: cd os; make clean; cd repo; make clean; cd flatfs; make clean; + cd datastore; make clean; cd thirdparty; make clean; cd test; make clean; diff --git a/blocks/block.c b/blocks/block.c index 60401cf..6359442 100644 --- a/blocks/block.c +++ b/blocks/block.c @@ -4,6 +4,7 @@ #include +#include "libp2p/crypto/sha256.h" #include "ipfs/blocks/block.h" #include "ipfs/cid/cid.h" @@ -14,14 +15,31 @@ * @param block a pointer to the struct Block that will be created * @returns true(1) on success */ -int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block* block) { +int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block** block) { + + // allocate memory for structure + (*block) = (struct Block*)malloc(sizeof(struct Block)); + if ((*block) == NULL) + return 0; + + // cid char hash[32]; - ipfs_crypto_hashing_sha256(data, hash, 32); - ipfs_cid_new(0, hash, 32, CID_PROTOBUF, block->cid); + if (libp2p_crypto_hashing_sha256(data, hash, 32) == 0) { + free(*block); + return 0; + } + + if (ipfs_cid_new(0, hash, 32, CID_PROTOBUF, (*block)->cid) == 0) { + free(*block); + return 0; + } block->data = malloc(sizeof(unsigned char) * data_size); - if (block->data == NULL) + if (block->data == NULL) { + ipfs_ci_free((*block)->cid); + free(*block); return 0; + } memcpy(block->data, data, data_size); return 1; @@ -36,5 +54,6 @@ int ipfs_blocks_block_free(struct Block* block) { ipfs_cid_free(block->cid); if (block->data != NULL) free(block->data); + free(block); return 1; } diff --git a/blocks/blockstore.c b/blocks/blockstore.c index c4863f8..bd86ae0 100644 --- a/blocks/blockstore.c +++ b/blocks/blockstore.c @@ -37,5 +37,8 @@ int ipfs_blockstore_get(struct Cid* cid, struct Block* block) { * @returns true(1) on success */ int ipfs_blockstore_put(struct Block* block) { + // from blockstore.go line 118 + // TODO: Get Datastore key + // TODO: send to Put with key return 0; } diff --git a/cid/cid.c b/cid/cid.c index 4d9b395..15891b6 100644 --- a/cid/cid.c +++ b/cid/cid.c @@ -23,11 +23,17 @@ * @param cid where to put the results * @returns true(1) on success */ -int cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid* cid) { +int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** ptrToCid) { // allocate memory - cid->hash = malloc(sizeof(unsigned char) * hash_length); - if (cid->hash == NULL) + *ptrToCid = (struct Cid*)malloc(sizeof(struct Cid)); + struct Cid* cid = *ptrToCid; + if (cid == NULL) return 0; + cid->hash = malloc(sizeof(unsigned char) * hash_length); + if (cid->hash == NULL) { + free(cid); + return 0; + } // assign values cid->version = version; cid->codec = codec; @@ -43,9 +49,10 @@ int cid_new(int version, unsigned char* hash, size_t hash_length, const char cod * @param cid the struct * @returns 1 */ -int cid_free(struct Cid* cid) { +int ipfs_cid_free(struct Cid* cid) { if (cid->hash != NULL) free(cid->hash); + free(cid); return 1; } @@ -56,7 +63,7 @@ int cid_free(struct Cid* cid) { * @cid the Cid struct to fill * @return true(1) on success */ -int cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid* cid) { +int ipfs_cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid** cid) { int retVal = 0; if (incoming_length < 2) @@ -71,7 +78,7 @@ int cid_decode_from_string(const unsigned char* incoming, size_t incoming_length if (retVal == 0) return 0; // now we have the hash, build the object - return cid_new(0, hash, hash_length, CID_PROTOBUF, cid); + return ipfs_cid_new(0, hash, hash_length, CID_PROTOBUF, cid); } // TODO: finish this @@ -99,7 +106,7 @@ int cid_decode_from_string(const unsigned char* incoming, size_t incoming_length * @param incoming_size the size of the array * @param cid the Cid structure to fill */ -int cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid) { +int ipfs_cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid) { // this is a multihash if (incoming_size == 34 && incoming[0] == 18 && incoming[1] == 32) { cid->hash_length = mh_multihash_length(incoming, incoming_size); diff --git a/datastore/Makefile b/datastore/Makefile new file mode 100644 index 0000000..e8bfbec --- /dev/null +++ b/datastore/Makefile @@ -0,0 +1,18 @@ +CC = gcc +CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include + +ifdef DEBUG +CFLAGS += -g3 +endif + +LFLAGS = +DEPS = ../include/ipfsdatastore/ds_helper.h +OBJS = ds_helper.o + +%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +all: $(OBJS) + +clean: + rm -f *.o diff --git a/datastore/ds_helper.c b/datastore/ds_helper.c new file mode 100644 index 0000000..267ecea --- /dev/null +++ b/datastore/ds_helper.c @@ -0,0 +1,55 @@ +/** + * Some code to help with the datastore / blockstore interface + */ +#include "libp2p/crypto/encoding/base32.h" +#include "ipfs/datastore/ds_helper.h" +/** + * Generate a key based on the passed in binary_array + * @param binary_array what to base the key on + * @param array_length the size of the binary array + * @param results where the key will be put + * @param max_results_length the size of the results buffer + * @param results_length the length of the generated key + * @returns true(1) on success + */ +int ipfs_datastore_helper_ds_key_from_binary(unsigned char* binary_array, size_t array_length, + char* results, size_t max_results_length, size_t* results_length) { + + size_t encoded_length = libp2p_crypto_encoding_base32_encode_size(array_length); + if (encoded_length > max_results_length) + return 0; + + *results_length = max_results_length; + int retVal = libp2p_crypto_encoding_base32_encode(binary_array, array_length, results, results_length); + if (retVal == 0) { + *results_length = 0; + return 0; + } + + return 1; +} + +/** + * Generate a binary array based on the passed in datastore key + * @param ds_key the base32 encoded key + * @param key_length the length of the base32 "string" + * @param binary_array where to put the decoded value + * @param max_binary_array_length the memory size of binary_array + * @param completed_binary_array_length the length of what was written to the binary_array + * @returns true(1) on success + */ +int ipfs_datastore_helper_binary_from_ds_key(unsigned char* ds_key, size_t key_length, unsigned char* binary_array, + size_t max_binary_array_length, size_t* completed_binary_array_length) { + + size_t decoded_length = libp2p_crypto_encoding_base32_decode_size(key_length); + if (decoded_length > max_binary_array_length) + return 0; + + *completed_binary_array_length = max_binary_array_length; + int retVal = libp2p_crypto_encoding_base32_decode(ds_key, key_length, binary_array, completed_binary_array_length); + if (retVal == 0) { + *completed_binary_array_length = 0; + return 0; + } + return 1; +} diff --git a/include/ipfs/blocks/block.h b/include/ipfs/blocks/block.h index 28802c2..f51f6c4 100644 --- a/include/ipfs/blocks/block.h +++ b/include/ipfs/blocks/block.h @@ -17,7 +17,7 @@ struct Block { * @param block a pointer to the struct Block that will be created * @returns true(1) on success */ -int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block* block); +int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block** block); /*** * Free resources used by the creation of a block diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h index eedd560..1f1b168 100644 --- a/include/ipfs/cid/cid.h +++ b/include/ipfs/cid/cid.h @@ -33,14 +33,14 @@ struct Cid { * @param cid where to put the results * @returns true(1) on success */ -int cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid* cid); +int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** cid); /*** * Free the resources from a Cid * @param cid the struct * @returns 1 */ -int cid_free(struct Cid* cid); +int ipfs_cid_free(struct Cid* cid); /*** * Fill a Cid struct based on a base 58 encoded string @@ -49,7 +49,7 @@ int cid_free(struct Cid* cid); * @cid the Cid struct to fill * @return true(1) on success */ -int cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid* cid); +int ipfs_cid_decode_from_string(const unsigned char* incoming, size_t incoming_length, struct Cid** cid); /*** * Turn a multibase decoded string of bytes into a Cid struct @@ -57,6 +57,6 @@ int cid_decode_from_string(const unsigned char* incoming, size_t incoming_length * @param incoming_size the size of the array * @param cid the Cid structure to fill */ -int cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid); +int ipfs_cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid); #endif diff --git a/include/ipfs/datastore/ds_helper.h b/include/ipfs/datastore/ds_helper.h new file mode 100644 index 0000000..503af01 --- /dev/null +++ b/include/ipfs/datastore/ds_helper.h @@ -0,0 +1,33 @@ +/** + * Some code to help with the datastore / blockstore interface + */ +#ifndef __IPFS_DATASTORE_DS_HELPER_H__ +#define __IPFS_DATASTORE_DS_HELPER_H__ + +#include + +/** + * Generate a key based on the passed in binary_array + * @param binary_array what to base the key on + * @param array_length the size of the binary array + * @param results where the key will be put + * @param max_results_length the size of the results buffer + * @param results_length the length of the generated key + * @returns true(1) on success + */ +int ipfs_datastore_helper_ds_key_from_binary(unsigned char* binary_array, size_t array_length, + char* results, size_t max_results_length, size_t* results_length); + +/** + * Generate a binary array based on the passed in datastore key + * @param ds_key the base32 encoded key + * @param key_length the length of the base32 "string" + * @param binary_array where to put the decoded value + * @param max_binary_array_length the memory size of binary_array + * @param completed_binary_array_length the length of what was written to the binary_array + * @returns true(1) on success + */ +int ipfs_datastore_helper_binary_from_ds_key(unsigned char* ds_key, size_t key_length, unsigned char* binary_array, + size_t max_binary_array_length, size_t* completed_binary_array_length); + +#endif diff --git a/merkledag/merkledag.c b/merkledag/merkledag.c new file mode 100644 index 0000000..f1b441c --- /dev/null +++ b/merkledag/merkledag.c @@ -0,0 +1,15 @@ +/** + * A basic storage building block of the IPFS system + */ + +/*** + * Adds a node to the dagService and blockService + * @param node the node to add + * @returns true(1) on success + */ +int ipfs_merkledag_add(struct Node* node) { + // taken from merkledag.go line 59 + // TODO: put in blockstore + // TODO: call HasBlock (unsure why as yet) + +} diff --git a/test/Makefile b/test/Makefile index 66c920c..37d3fe4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,7 +8,7 @@ OBJS = testit.o ../cmd/ipfs/init.o ../commands/argument.o ../commands/command_op ../repo/config/bootstrap_peers.o ../repo/config/datastore.o ../repo/config/gateway.o \ ../repo/config/addresses.o ../repo/config/swarm.o ../repo/config/peer.o \ ../thirdparty/ipfsaddr/ipfs_addr.o ../cid/cid.o ../multibase/multibase.o \ - ../flatfs/flatfs.o + ../flatfs/flatfs.o ../datastore/ds_helper.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/test/cid/test_cid.h b/test/cid/test_cid.h index d239d01..aa28841 100644 --- a/test/cid/test_cid.h +++ b/test/cid/test_cid.h @@ -10,25 +10,25 @@ int test_cid_new_free() { - struct Cid cid; + struct Cid* cid; const unsigned char* hash = "ABC123"; - int retVal = cid_new(0, (unsigned char*)hash, strlen((char*)hash), CID_PROTOBUF, &cid); + int retVal = ipfs_cid_new(0, (unsigned char*)hash, strlen((char*)hash), CID_PROTOBUF, &cid); if (retVal == 0) return 0; - if (cid.version != 0) + if (cid->version != 0) return 0; - if (cid.codec != CID_PROTOBUF) + if (cid->codec != CID_PROTOBUF) return 0; - if (cid.hash_length != strlen((char*)hash)) + if (cid->hash_length != strlen((char*)hash)) return 0; - if (strncmp((char*)cid.hash, (char*)hash, 6) != 0) + if (strncmp((char*)cid->hash, (char*)hash, 6) != 0) return 0; - return cid_free(&cid); + return ipfs_cid_free(cid); } /*** @@ -53,7 +53,7 @@ int test_cid_cast_multihash() { // now call cast struct Cid cid; - retVal = cid_cast(multihash, multihash_size, &cid); + retVal = ipfs_cid_cast(multihash, multihash_size, &cid); if (retVal == 0) return 0; // check results @@ -90,7 +90,7 @@ int test_cid_cast_non_multihash() { // now call cast struct Cid cid; - int retVal = cid_cast(array, array_size, &cid); + int retVal = ipfs_cid_cast(array, array_size, &cid); if (retVal == 0) return 0; // check results diff --git a/test/storage/test_ds_helper.h b/test/storage/test_ds_helper.h new file mode 100644 index 0000000..e4981df --- /dev/null +++ b/test/storage/test_ds_helper.h @@ -0,0 +1,37 @@ +#include "ipfs/datastore/ds_helper.h" + +int test_ds_key_from_binary() { + size_t original_incoming_length = 10; + size_t incoming_length = original_incoming_length; + + unsigned char incoming[incoming_length + 5]; // give a little wiggle room + unsigned char* ptrIncoming = &incoming[0]; + + for(int i = 0; i < incoming_length; i++) { + incoming[i] = i; + } + + size_t outgoing_length = 100; + char outgoing[outgoing_length]; + char* ptrOutgoing = &outgoing[0]; + + memset(outgoing, 0, outgoing_length); + + int retVal = ipfs_datastore_helper_ds_key_from_binary(ptrIncoming, incoming_length, ptrOutgoing, outgoing_length, &outgoing_length); + if (retVal == 0) + return 0; + + // now undo it and see if we get the same thing back... + retVal = ipfs_datastore_helper_binary_from_ds_key(ptrOutgoing, outgoing_length, incoming, incoming_length + 5, &incoming_length); + if (retVal == 0) + return 0; + + if (original_incoming_length != incoming_length) + return 0; + + for(int i = 0; i < original_incoming_length; i++) { + if (incoming[i] != i) + return 0; + } + return 1; +} diff --git a/test/testit.c b/test/testit.c index 896c292..b005073 100644 --- a/test/testit.c +++ b/test/testit.c @@ -5,6 +5,7 @@ #include "cmd/ipfs/test_init.h" #include "cid/test_cid.h" #include "flatfs/test_flatfs.h" +#include "storage/test_ds_helper.h" int testit(const char* name, int (*func)(void)) { printf("Testing %s...\n", name); @@ -33,6 +34,7 @@ int main(int argc, char** argv) { counter += testit("test_flatfs_get_directory", test_flatfs_get_directory); counter += testit("test_flatfs_get_filename", test_flatfs_get_filename); counter += testit("test_flatfs_get_full_filename", test_flatfs_get_full_filename); + counter += testit("test_ds_key_from_binary", test_ds_key_from_binary); if (counter > 0) { printf("***** There were %d failed test(s) *****\n", counter); } else {