diff --git a/.cproject b/.cproject
index d05172c..a60437a 100644
--- a/.cproject
+++ b/.cproject
@@ -30,6 +30,7 @@
+
diff --git a/blocks/Makefile b/blocks/Makefile
index f830509..f64ebc1 100644
--- a/blocks/Makefile
+++ b/blocks/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/cid/Makefile b/cid/Makefile
index 08774d9..bb4c1ee 100644
--- a/cid/Makefile
+++ b/cid/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/cid/cid.c b/cid/cid.c
index 13a4ca1..3ee934f 100644
--- a/cid/cid.c
+++ b/cid/cid.c
@@ -10,8 +10,77 @@
#include "libp2p/crypto/encoding/base58.h"
#include "ipfs/multibase/multibase.h"
#include "mh/multihash.h"
-#include "multiaddr/varint.h"
+#include "varint.h"
+enum WireType ipfs_cid_message_fields[] = { WIRETYPE_VARINT, WIRETYPE_VARINT, WIRETYPE_LENGTH_DELIMITED };
+
+
+size_t ipfs_cid_protobuf_encode_size(struct Cid* cid) {
+ if (cid != NULL)
+ return 11+12+cid->hash_length+11;
+ return 0;
+}
+
+int ipfs_cid_protobuf_encode(struct Cid* cid, unsigned char* buffer, size_t buffer_length, size_t* bytes_written) {
+ size_t bytes_used;
+ *bytes_written = 0;
+ int retVal = 0;
+ if (cid != NULL) {
+ retVal = protobuf_encode_varint(1, ipfs_cid_message_fields[0], cid->version, buffer, buffer_length, &bytes_used);
+ *bytes_written += bytes_used;
+ retVal = protobuf_encode_varint(2, ipfs_cid_message_fields[1], cid->codec, &buffer[*bytes_written], buffer_length - (*bytes_written), &bytes_used);
+ *bytes_written += bytes_used;
+ retVal = protobuf_encode_length_delimited(3, ipfs_cid_message_fields[2], cid->hash, cid->hash_length, &buffer[*bytes_written], buffer_length - (*bytes_written), &bytes_used);
+ *bytes_written += bytes_used;
+ }
+ return 1;
+}
+
+int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Cid** output) {
+ // short cut for nulls
+ if (buffer_length == 0) {
+ *output = NULL;
+ return 1;
+ }
+
+ size_t pos = 0;
+ int version = 0;
+ unsigned char* hash;
+ size_t hash_length;
+ char codec = 0;
+ int retVal = 0;
+
+ while(pos < buffer_length) {
+ size_t bytes_read = 0;
+ int field_no;
+ enum WireType field_type;
+ if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
+ return 0;
+ }
+ pos += bytes_read;
+ switch(field_no) {
+ case (1):
+ version = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
+ pos += bytes_read;
+ break;
+ case (2):
+ codec = varint_decode(&buffer[pos], buffer_length - pos, &bytes_read);
+ pos += bytes_read;
+ break;
+ case (3):
+ retVal = protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, &hash, &hash_length, &bytes_read);
+ if (retVal == 0)
+ return 0;
+ pos += bytes_read;
+ break;
+ }
+
+ }
+
+ retVal = ipfs_cid_new(version, hash, hash_length, codec, output);
+ free(hash);
+ return retVal;
+}
/**
* Create a new CID based on the given hash
@@ -118,16 +187,16 @@ int ipfs_cid_cast(unsigned char* incoming, size_t incoming_size, struct Cid* cid
// This is not a multihash. Perhaps it is using varints. Try to peel the information out of the bytes.
// first the version
- int pos = 0, retVal = 0;
+ int pos = 0;
size_t num_bytes = 0;
- num_bytes = uvarint_decode32(&incoming[pos], incoming_size - pos, &cid->version);
- if (num_bytes < 0 || cid->version > 1 || cid->version < 0)
+ cid->version = varint_decode(&incoming[pos], incoming_size - pos, &num_bytes);
+ if (num_bytes == 0 || cid->version > 1 || cid->version < 0)
return 0;
pos = num_bytes;
// now the codec
uint32_t codec = 0;
- num_bytes = uvarint_decode32(&incoming[pos], incoming_size - pos, &codec);
- if (num_bytes < 0)
+ codec = varint_decode(&incoming[pos], incoming_size - pos, &num_bytes);
+ if (num_bytes == 0)
return 0;
cid->codec = codec;
pos += num_bytes;
diff --git a/cmd/ipfs/Makefile b/cmd/ipfs/Makefile
index 9021275..24b9bd5 100644
--- a/cmd/ipfs/Makefile
+++ b/cmd/ipfs/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -Wall
+CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/core/Makefile b/core/Makefile
index 943ec08..94a443b 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-protobuf -Wall
LFLAGS =
DEPS = builder.h ipfs_node.h
OBJS = builder.o
diff --git a/dnslink/dnslink.c b/dnslink/dnslink.c
new file mode 100644
index 0000000..d80fe2c
--- /dev/null
+++ b/dnslink/dnslink.c
@@ -0,0 +1,295 @@
+/*
+Package dnslink implements a dns link resolver. dnslink is a basic
+standard for placing traversable links in dns itself. See dnslink.info
+
+A dnslink is a path link in a dns TXT record, like this:
+
+ dnslink=/ipfs/QmR7tiySn6vFHcEjBeZNtYGAFh735PJHfEMdVEycj9jAPy
+
+For example:
+
+ > dig TXT ipfs.io
+ ipfs.io. 120 IN TXT dnslink=/ipfs/QmR7tiySn6vFHcEjBeZNtYGAFh735PJHfEMdVEycj9jAPy
+
+This package eases resolving and working with thse dns links. For example:
+
+ import (
+ dnslink "github.com/jbenet/go-dnslink"
+ )
+
+ link, err := dnslink.Resolve("ipfs.io")
+ // link = "/ipfs/QmR7tiySn6vFHcEjBeZNtYGAFh735PJHfEMdVEycj9jAPy"
+
+It even supports recursive resolution. Suppose you have three domains with
+dnslink records like these:
+
+ > dig TXT foo.com
+ foo.com. 120 IN TXT dnslink=/dns/bar.com/f/o/o
+ > dig TXT bar.com
+ bar.com. 120 IN TXT dnslink=/dns/long.test.baz.it/b/a/r
+ > dig TXT long.test.baz.it
+ long.test.baz.it. 120 IN TXT dnslink=/b/a/z
+
+Expect these resolutions:
+
+ dnslink.ResolveN("long.test.baz.it", 0) // "/dns/long.test.baz.it"
+ dnslink.Resolve("long.test.baz.it") // "/b/a/z"
+
+ dnslink.ResolveN("bar.com", 1) // "/dns/long.test.baz.it/b/a/r"
+ dnslink.Resolve("bar.com") // "/b/a/z/b/a/r"
+
+ dnslink.ResolveN("foo.com", 1) // "/dns/bar.com/f/o/o/"
+ dnslink.ResolveN("foo.com", 2) // "/dns/long.test.baz.it/b/a/r/f/o/o/"
+ dnslink.Resolve("foo.com") // "/b/a/z/b/a/r/f/o/o"
+
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include "ipfs/namesys/namesys.h"
+#define IPFS_DNSLINK_C
+#include "ipfs/dnslink/dnslink.h"
+#include "ipfs/cid/cid.h"
+#include "ipfs/path/path.h"
+
+// ipfs_dnslink_resolve resolves the dnslink at a particular domain. It will
+// recursively keep resolving until reaching the defaultDepth of Resolver. If
+// the depth is reached, ipfs_dnslink_resolve will return the last value
+// retrieved, and ErrResolveLimit. If TXT records are found but are not valid
+// dnslink records, ipfs_dnslink_resolve will return ErrInvalidDNSLink.
+// ipfs_dnslink_resolve will check every TXT record returned. If resolution
+// fails otherwise, ipfs_dnslink_resolve will return ErrResolveFailed
+int ipfs_dnslink_resolve (char **p, char *domain)
+{
+ return ipfs_dnslink_resolve_n (p, domain, DefaultDepthLimit);
+}
+
+// ipfs_dnslink_lookup_txt is a function that looks up a TXT record in some dns resolver.
+// This is useful for testing or passing your own dns resolution process, which
+// could take into account non-standard TLDs like .bit, .onion, .ipfs, etc.
+int (*ipfs_dnslink_lookup_txt)(char ***txt, char *name) = NULL;
+
+// ipfs_dnslink_resolve_n is just like Resolve, with the option to specify a
+// maximum resolution depth.
+int ipfs_dnslink_resolve_n (char **p, char *d, int depth)
+{
+ int err, i, l;
+ char *rest, **link, tail[500], buf[500], domain[500];
+ char dns_prefix[] = "/dns/";
+
+ domain[sizeof(domain)-1] = '\0';
+ strncpy (domain, d, sizeof(domain) - 1);
+ for (i=0 ; i < depth ; i++) {
+ err = ipfs_dnslink_resolve_once (&link, domain);
+ if (err) {
+ return err;
+ }
+
+ // if does not have /dns/ as a prefix, done.
+ if (memcmp (*link, dns_prefix, sizeof(dns_prefix) - 1)!=0) {
+ l = strlen(*link) + strlen(tail);
+ *p = malloc(l + 1);
+ if (!*p) {
+ free(*link);
+ free(link);
+ return ErrAllocFailed;
+ }
+ *p[l] = '\0';
+ strncpy(*p, *link, l);
+ free(*link);
+ free(link);
+ strncat(*p, tail, l - strlen(*p));
+ return 0; // done
+ }
+
+ // keep resolving
+ err = ipfs_dnslink_parse_link_domain (&d, &rest, *link);
+ free (*link);
+ free (link);
+ if (err) {
+ *p = NULL;
+ return err;
+ }
+
+ strncpy (domain, d, sizeof(domain) - 1);
+ free (d);
+ strncpy (buf, tail, sizeof(buf) - 1);
+ strncpy (tail, rest, sizeof(tail) - 1);
+ strncat (tail, buf, sizeof(tail) - 1 - strlen(tail));
+ }
+
+ strncpy (buf, tail, sizeof(buf) - 1);
+ strncpy (tail, dns_prefix, sizeof(tail) - 1);
+ strncat (tail, domain, sizeof(tail) - 1 - strlen(tail));
+ strncat (tail, buf, sizeof(tail) - 1 - strlen(tail));
+ return ErrResolveLimit;
+}
+
+// lookup using libresolv -lresolv
+int ipfs_dnslink_resolv_lookupTXT(char ***txt, char *domain)
+{
+ char buf[4096], *p;
+ int responseLength;
+ int i, l, n = 0;
+ ns_msg query_parse_msg;
+ ns_rr query_parse_rr;
+ u_char responseByte[4096];
+
+ // Use res_query from libresolv to retrieve TXT record from DNS server.
+ if ((responseLength = res_query(domain,C_IN,T_TXT,responseByte,sizeof(responseByte))) < 0 ||
+ ns_initparse(responseByte,responseLength,&query_parse_msg) < 0) {
+ return ErrResolveFailed;
+ } else {
+ l = sizeof (buf);
+ buf[--l] = '\0';
+ p = buf;
+ // save every TXT record to buffer separating with a \0
+ for (i=0 ; i < ns_msg_count(query_parse_msg,ns_s_an) ; i++) {
+ if (ns_parserr(&query_parse_msg,ns_s_an,i,&query_parse_rr)) {
+ return ErrResolveFailed;
+ } else {
+ char *rdata = ns_rr_rdata(query_parse_rr);
+ memcpy(p, rdata+1, *rdata); // first byte is record length
+ p += *rdata; // update pointer
+ *p++ = '\0'; // mark end-of-record and update pointer to next record.
+ n++; // update record count
+ }
+ }
+ // allocate array for all records + NULL pointer terminator.
+ *txt = calloc(n+1, sizeof(void*));
+ if (!*txt) {
+ return ErrAllocFailed;
+ }
+ l = p - buf; // length of all records in buffer.
+ p = malloc(l); // allocate memory that will be used as string data at *txt array.
+ if (!p) {
+ free(*txt);
+ *txt = NULL;
+ return ErrAllocFailed;
+ }
+ memcpy(p, buf, l); // transfer from buffer to allocated memory.
+ for (i = 0 ; i < n ; i++) {
+ *txt[i] = p; // save position of current record at *txt array.
+ p = memchr(p, '\0', l - (p - *txt[0])) + 1; // find next record position after next \0
+ }
+ }
+ return 0;
+}
+
+// ipfs_dnslink_resolve_once implements resolver.
+int ipfs_dnslink_resolve_once (char ***p, char *domain)
+{
+ int err, i;
+ char **txt;
+
+ if (!p || !domain) {
+ return ErrInvalidParam;
+ }
+
+ *p = NULL;
+
+ if (!ipfs_isdomain_is_domain (domain)) {
+ return ErrInvalidDomain;
+ }
+
+ if (!ipfs_dnslink_lookup_txt) { // if not set
+ ipfs_dnslink_lookup_txt = ipfs_dnslink_resolv_lookupTXT; // use default libresolv
+ }
+
+ err = ipfs_dnslink_lookup_txt (&txt, domain);
+ if (err) {
+ return err;
+ }
+
+ err = ErrResolveFailed;
+ for (i=0 ; txt[i] ; i++) {
+ err = ipfs_dnslink_parse_txt(*p, txt[i]);
+ if (!err) {
+ break;
+ }
+ }
+ free(*txt);
+ free(txt);
+ return err;
+}
+
+// ipfs_dnslink_parse_txt parses a TXT record value for a dnslink value.
+// The TXT record must follow the dnslink format:
+// TXT dnslink=
+// TXT dnslink=/foo/bar/baz
+// ipfs_dnslink_parse_txt will return ErrInvalidDNSLink if parsing fails.
+int ipfs_dnslink_parse_txt (char **path, char *txt)
+{
+ char **parts;
+
+ if (!path || !txt) {
+ return ErrInvalidParam;
+ }
+ parts = ipfs_path_split_n (txt, "=", 2);
+ if (!parts) {
+ return ErrAllocFailed;
+ }
+ if (ipfs_path_segments_length (parts) == 2 && strcmp(parts[0], "dnslink")==0 && memcmp(parts[1], "/", 1)==0) {
+ *path = ipfs_path_clean_path(parts[1]);
+ if (path) {
+ ipfs_path_free_segments (&parts);
+ return 0;
+ }
+ }
+ ipfs_path_free_segments (&parts);
+ *path = NULL;
+ return ErrInvalidDNSLink;
+}
+
+// ipfs_dnslink_parse_link_domain parses a domain from a dnslink path.
+// The link path must follow the dnslink format:
+// /dns//
+// /dns/ipfs.io
+// /dns/ipfs.io/blog/0-hello-worlds
+// ipfs_dnslink_parse_link_domain will return ErrInvalidDNSLink if parsing
+// fails, and ErrInvalidDomain if the domain is not valid.
+int ipfs_dnslink_parse_link_domain (char **domain, char**rest, char *txt)
+{
+ char **parts;
+ int parts_len;
+
+ if (!domain || !rest || !txt) {
+ return ErrInvalidParam;
+ }
+
+ *domain = *rest = NULL;
+
+ parts = ipfs_path_split_n (txt, "/", 4);
+ parts_len = ipfs_path_segments_length(parts);
+ if (!parts || parts_len < 3 || parts[0][0]!='\0' || strcmp(parts[1], "dns") != 0) {
+ return ErrInvalidDNSLink;
+ }
+
+ if (! ipfs_isdomain_is_domain (parts[2])) {
+ ipfs_path_free_segments (&parts);
+ return ErrInvalidDomain;
+ }
+
+ *domain = malloc(strlen (parts[2]) + 1);
+ if (!*domain) {
+ ipfs_path_free_segments (&parts);
+ return ErrAllocFailed;
+ }
+ strcpy(*domain, parts[2]);
+
+ if (parts_len > 3) {
+ *rest = malloc(strlen (parts[3]) + 1);
+ if (!*rest) {
+ ipfs_path_free_segments (&parts);
+ free (*domain);
+ *domain = NULL;
+ return ErrAllocFailed;
+ }
+ strcpy(*rest, parts[3]);
+ }
+
+ return 0;
+}
diff --git a/importer/importer.c b/importer/importer.c
new file mode 100644
index 0000000..3c5b324
--- /dev/null
+++ b/importer/importer.c
@@ -0,0 +1,46 @@
+#include
+
+#include "ipfs/importer/importer.h"
+
+#define MAX_DATA_SIZE 262144 // 1024 * 256;
+
+/**
+ * read the next chunk of bytes, create a node, and add a link to the node in the passed-in node
+ * @param file the file handle
+ * @param node the node to add to
+ * @returns number of bytes read
+ */
+int ipfs_import_chunk(FILE* file, struct Node* node) {
+ unsigned char buffer[MAX_DATA_SIZE];
+ size_t bytes_read = fread(buffer, MAX_DATA_SIZE, 1, file);
+ if (node->data_size == 0) {
+ Node_Set_Data(node, buffer, bytes_read);
+ } else {
+ // create a new node, and link to the parent
+ struct Node* new_node = N_Create_From_Data(buffer, bytes_read);
+ // persist
+ // put link in node
+ Node_Add_Link(node, Create_Link("", new_node->cached->hash));
+ Node_Delete(new_node);
+ }
+ return bytes_read;
+}
+
+/**
+ * Creates a node based on an incoming file
+ * @param file_name the file to import
+ * @param node the root node (could have links to others)
+ * @returns true(1) on success
+ */
+int ipfs_import_file(const char* fileName, struct Node** node) {
+ int retVal = 1;
+
+ FILE* file = fopen(fileName, "rb");
+ *node = (struct Node)malloc(sizeof(struct Node));
+
+ // add all nodes
+ while (ipfs_import_chunk(file, *node) == MAX_DATA_SIZE) {}
+ fclose(file);
+
+ return 1;
+}
diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h
index e499c41..1ce766b 100644
--- a/include/ipfs/cid/cid.h
+++ b/include/ipfs/cid/cid.h
@@ -6,6 +6,7 @@
#define __IPFS_CID_CID_H
#include
+#include "protobuf.h"
#define CID_PROTOBUF 0x70
#define CID_CBOR 0x71
@@ -25,6 +26,30 @@ struct Cid {
size_t hash_length;
};
+/***
+ * encode a Cid into a protobuf array of bytes
+ * @param incoming the incoming Cid struct
+ * @param buffer the buffer
+ * @param max_buffer_length the length of the buffer
+ * @param bytes_written the number of bytes written
+ */
+int ipfs_cid_protobuf_encode(struct Cid* incoming, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written);
+
+/***
+ * decode an array of bytes into a Cid structure
+ * @param buffer the incming array of bytes
+ * @param buffer_length the length of the buffer
+ * @param output the Cid struct NOTE: all allocations are made by this function. Be sure to call free
+ * @returns true(1) on success
+ */
+int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Cid** output);
+
+/***
+ * Returns a safe estimate of the required buffer size to encode the Cid struct
+ * @param incoming the struct to encode
+ * @returns the number of approximate bytes
+ */
+size_t ipfs_cid_protobuf_encode_size(struct Cid* incoming);
/**
* Create a new CID based on the given hash
diff --git a/include/ipfs/dnslink/dnslink.h b/include/ipfs/dnslink/dnslink.h
new file mode 100644
index 0000000..f04cb7c
--- /dev/null
+++ b/include/ipfs/dnslink/dnslink.h
@@ -0,0 +1,26 @@
+#ifndef DNSLINK_H
+ #define DNSLINK_H
+
+ #include "ipfs/errs.h"
+
+ // DefaultDepthLimit controls how many dns links to resolve through before
+ // returning. Users can override this default.
+ #ifndef DefaultDepthLimit
+ #define DefaultDepthLimit 16
+ #endif
+ // MaximumDepthLimit governs the max number of recursive resolutions.
+ #ifndef MaximumDepthLimit
+ #define MaximumDepthLimit 256
+ #endif
+
+ #ifndef IPFS_DNSLINK_C
+ extern int (*ipfs_dnslink_lookup_txt)(char ***, char *);
+ #endif // IPFS_DNSLINK_C
+
+ int ipfs_dnslink_resolve (char **p, char *domain);
+ int ipfs_dnslink_resolve_n (char **p, char *d, int depth);
+ int ipfs_dnslink_resolv_lookupTXT(char ***txt, char *domain);
+ int ipfs_dnslink_resolve_once (char ***p, char *domain);
+ int ipfs_dnslink_parse_txt (char **path, char *txt);
+ int ipfs_dnslink_parse_link_domain (char **domain, char**rest, char *txt);
+#endif // DNSLINK_H
diff --git a/include/ipfs/errs.h b/include/ipfs/errs.h
new file mode 100644
index 0000000..c300dac
--- /dev/null
+++ b/include/ipfs/errs.h
@@ -0,0 +1,52 @@
+#ifndef IPFS_ERRS_H
+ #define IPFS_ERRS_H
+
+ char *Err[] = {
+ NULL,
+ "ErrAllocFailed",
+ "ErrNULLPointer",
+ "ErrPipe",
+ "ErrPoll",
+ "Could not publish name."
+ "Could not resolve name.",
+ "Could not resolve name (recursion limit exceeded).",
+ "expired record",
+ "unrecognized validity type",
+ "not a valid proquint string",
+ "not a valid domain name",
+ "not a valid dnslink entry",
+ // ErrBadPath is returned when a given path is incorrectly formatted
+ "invalid 'ipfs ref' path",
+ // Paths after a protocol must contain at least one component
+ "path must contain at least one component",
+ "TODO: ErrCidDecode",
+ NULL,
+ "no link named %s under %s",
+ "ErrInvalidParam",
+ // ErrResolveLimit is returned when a recursive resolution goes over
+ // the limit.
+ "resolve depth exceeded"
+ };
+
+ enum {
+ ErrAllocFailed = 1,
+ ErrNULLPointer,
+ ErrPipe,
+ ErrPoll,
+ ErrPublishFailed,
+ ErrResolveFailed,
+ ErrResolveRecursion,
+ ErrExpiredRecord,
+ ErrUnrecognizedValidity,
+ ErrInvalidProquint,
+ ErrInvalidDomain,
+ ErrInvalidDNSLink,
+ ErrBadPath,
+ ErrNoComponents,
+ ErrCidDecode,
+ ErrNoLink,
+ ErrNoLinkFmt,
+ ErrInvalidParam,
+ ErrResolveLimit
+ } ErrsIdx;
+#endif // IPFS_ERRS_H
diff --git a/include/ipfs/importer/importer.h b/include/ipfs/importer/importer.h
new file mode 100644
index 0000000..00c977c
--- /dev/null
+++ b/include/ipfs/importer/importer.h
@@ -0,0 +1,12 @@
+#ifndef __IPFS_IMPORTER_IMPORTER_H__
+#define __IPFS_IMPORTER_IMPORTER_H__
+
+/**
+ * Creates a node based on an incoming file
+ * @param file_name the file to import
+ * @param node the root node (could have links to others)
+ * @returns true(1) on success
+ */
+int ipfs_import_file(const char* fileName, struct Node** node);
+
+#endif /* INCLUDE_IPFS_IMPORTER_IMPORTER_H_ */
diff --git a/include/ipfs/merkledag/merkledag.h b/include/ipfs/merkledag/merkledag.h
index fb0c682..9817187 100644
--- a/include/ipfs/merkledag/merkledag.h
+++ b/include/ipfs/merkledag/merkledag.h
@@ -1,3 +1,6 @@
+/***
+ * Merkledag methods
+ */
#ifndef __IPFS_MERKLEDAG_H__
#define __IPFS_MERKLEDAG_H__
diff --git a/include/ipfs/namesys/namesys.h b/include/ipfs/namesys/namesys.h
index 9ff92dd..aaa70e5 100644
--- a/include/ipfs/namesys/namesys.h
+++ b/include/ipfs/namesys/namesys.h
@@ -3,40 +3,7 @@
#define DefaultDepthLimit 32
- #ifdef NAMESYS_C
- char *ErrNamesys[] = {
- NULL,
- "ErrAllocFailed",
- "ErrNULLPointer",
- "ErrPipe",
- "ErrPoll",
- "Could not publish name."
- "Could not resolve name.",
- "Could not resolve name (recursion limit exceeded).",
- "expired record",
- "unrecognized validity type",
- "not a valid proquint string",
- "not a valid domain name",
- "not a valid dnslink entry"
- };
- #else
- extern char *ErrNamesys;
- #endif // NAMESYS_C
-
- enum {
- ErrAllocFailed = 1,
- ErrNULLPointer,
- ErrPipe,
- ErrPoll,
- ErrPublishFailed,
- ErrResolveFailed,
- ErrResolveRecursion,
- ErrExpiredRecord,
- ErrUnrecognizedValidity,
- ErrInvalidProquint,
- ErrInvalidDomain,
- ErrInvalidDNSLink
- } NamesysErrs;
+ #include "ipfs/errs.h"
typedef struct s_resolvers {
char *protocol;
@@ -73,7 +40,6 @@
int condition;
} tlds;
- int ipfs_namesys_resolve (resolver *r, char **p, char *str, int depth, char **prefixes);
int ipfs_namesys_resolve(char **path, char *name);
int ipfs_namesys_resolve_n(char **path, char *name, int depth);
int ipfs_namesys_resolve_once (char **path, char *name);
diff --git a/include/ipfs/node/Example for this.c b/include/ipfs/node/Example for this.c
index 1cf7d4a..1ec8f98 100644
--- a/include/ipfs/node/Example for this.c
+++ b/include/ipfs/node/Example for this.c
@@ -46,12 +46,12 @@ int main(int argc, char** argv)
struct Node * Mynode;
Mynode = N_Create_From_Link(mylink);
mylink->name = "HAHA";//Testing for valid node creation
- printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->Lcid->hash);
+ printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->head_link[0]->name, Mynode->head_link[0]->Lcid->hash);
//N_Add_Link
Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2));
mylink2->name = "HAHA";//Testing for valid node creation
- printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->Lcid->hash);
+ printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->head_link[1]->name,Mynode->head_link[1]->Lcid->hash);
//Node_Get_Link
struct Link * ResultLink = Node_Get_Link(Mynode, "Simo");
@@ -74,7 +74,7 @@ int main(int argc, char** argv)
//Node Copy
struct Node * Node2;
Node2 = Node_Copy(Mynode);
- printf("NODE COPY TEST: [0]: %s\n", Node2->links[0]->Lcid->hash);
+ printf("NODE COPY TEST: [0]: %s\n", Node2->head_link[0]->Lcid->hash);
Node_Delete(Node2);
//Node_Set_Data
diff --git a/include/ipfs/node/node.h b/include/ipfs/node/node.h
index c3a82f1..56990fe 100644
--- a/include/ipfs/node/node.h
+++ b/include/ipfs/node/node.h
@@ -13,21 +13,20 @@
*
*===================================================================================*/
-struct Link
+struct NodeLink
{
- char * name;
- size_t size;
- struct Cid * Lcid;
+ char* name;
+ struct Cid * cid;
+ struct NodeLink* next;
};
struct Node
{
- unsigned char * data;
+ unsigned char* data;
size_t data_size;
- unsigned char * encoded;
- struct Cid * cached;
- int link_ammount;
- struct Link * links[];
+ unsigned char* encoded;
+ struct Cid* cached;
+ struct NodeLink* head_link;
};
/*====================================================================================
@@ -42,107 +41,141 @@ struct Node
/* Create_Link
* @Param name: The name of the link (char *)
- * @Param size: Size of the link (size_t)
* @Param ahash: An Qmhash
+ * @param node_link a pointer to the new struct NodeLink
+ * @returns true(1) on success
*/
-struct Link * Create_Link(char * name, unsigned char * ahash);
+int ipfs_node_link_new(char * name, unsigned char * ahash, struct NodeLink** node_link);
-/* Free_Link
+/* ipfs_node_link_free
* @param L: Free the link you have allocated.
*/
-void Free_Link(struct Link * L);
+int ipfs_node_link_free(struct NodeLink * node_link);
+
+/***
+ * Node protobuf functions
+ */
+
+/***
+ * return an approximate size of the encoded node
+ * @param node the node to examine
+ * @returns the max size of an encoded stream of bytes, if it were encoded
+ */
+size_t ipfs_node_protobuf_encode_size(struct Node* node);
+
+/***
+ * Encode a node into a protobuf byte stream
+ * @param node the node to encode
+ * @param buffer where to put it
+ * @param max_buffer_length the length of buffer
+ * @param bytes_written how much of buffer was used
+ * @returns true(1) on success
+ */
+ipfs_node_protobuf_encode(struct Node* node, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written);
+
+/***
+ * Decode a stream of bytes into a Node structure
+ * @param buffer where to get the bytes from
+ * @param buffer_length the length of buffer
+ * @param node pointer to the Node to be created
+ * @returns true(1) on success
+ */
+ipfs_node_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Node** node);
/*====================================================================================
* Node Functions
*===================================================================================*/
-/*Create_Empty_Node
+/*ipfs_node_new
* Creates an empty node, allocates the required memory
* Returns a fresh new node with no data set in it.
*/
-struct Node * Create_Empty_Node();
+int ipfs_node_new(struct Node** node);
-//Node_Set_Cached
-int Node_Set_Cached(struct Node * N, struct Cid * TheCid);
+/**
+ * sets the Cid into the struct element titled cached
+ * @param node the node to work with
+ * @param cid the cid
+ * @returns true(1) on success
+ */
+int ipfs_node_set_cached(struct Node* node, struct Cid* cid);
-/*Node_Set_Data
+/*ipfs_node_set_data
* Sets the data of a node
* @param Node: The node which you want to set data in.
* @param Data, the data you want to assign to the node
* Sets pointers of encoded & cached to NULL /following go method
* returns 1 on success 0 on failure
*/
-int Node_Set_Data(struct Node * N, unsigned char * Data);
+int ipfs_node_set_data(struct Node * N, unsigned char * Data, size_t data_size);
-/*Node_Set_Encoded
+/*ipfs_node_set_encoded
* @param NODE: the node you wish to alter (struct Node *)
* @param Data: The data you wish to set in encoded.(unsigned char *)
* returns 1 on success 0 on failure
*/
-int Node_Set_Encoded(struct Node * N, unsigned char * Data);
+int ipfs_node_set_encoded(struct Node * N, unsigned char * Data);
-/*Node_Get_Data
+/*ipfs_node_get_data
* Gets data from a node
* @param Node: = The node you want to get data from. (unsigned char *)
* Returns data of node.
*/
-unsigned char * Node_Get_Data(struct Node * N);
+unsigned char * ipfs_node_get_data(struct Node * N);
-/*Node_Copy: Returns a copy of the node you input
- * @param Node: The node you want to copy (struct CP_Node *)
- * Returns a copy of the node you wanted to copy.
- */
-struct Node * Node_Copy(struct Node * CP_Node);
-
-/*Node_Delete
+/*ipfs_node_free
* Once you are finished using a node, always delete it using this.
* It will take care of the links inside it.
* @param N: the node you want to free. (struct Node *)
*/
-void Node_Delete(struct Node * N);
+void ipfs_node_free(struct Node * N);
-/*Node_Get_Link
+/*ipfs_node_get_link_by_name
* Returns a copy of the link with given name
* @param Name: (char * name) searches for link with this name
* Returns the link struct if it's found otherwise returns NULL
*/
-struct Link * Node_Get_Link(struct Node * N, char * Name);
+struct NodeLink * ipfs_node_get_link_by_name(struct Node * N, char * Name);
-/*Node_Remove_Link
+/*ipfs_node_remove_link_by_name
* Removes a link from node if found by name.
* @param name: Name of link (char * name)
* returns 1 on success, 0 on failure.
*/
-int Node_Remove_Link(char * Name, struct Node * mynode);
+int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode);
-/* N_Add_Link
+/* ipfs_node_add_link
* Adds a link to your node
* @param mynode: &yournode
* @param mylink: the CID you want to create a node from
* @param linksz: sizeof(your cid here)
* Returns your node with the newly added link
*/
-struct Node * N_Add_Link(struct Node ** mynode, struct Link * mylink, size_t linksz);
+int ipfs_node_add_link(struct Node * mynode, struct NodeLink * mylink);
-/*N_Create_From_Link
+/*ipfs_node_new_from_link
* Create a node from a link
* @param mylink: the link you want to create it from. (struct Cid *)
- * @param linksize: sizeof(the link in mylink) (size_T)
- * Returns a fresh new node with the link you specified. Has to be freed with Node_Free preferably.
+ * @param node the pointer to the new node
+ * @returns true(1) on success
*/
-struct Node * N_Create_From_Link(struct Link * mylink) ;
+int ipfs_node_new_from_link(struct NodeLink * mylink, struct Node** node);
-/*N_Create_From_Data
+/*ipfs_node_new_from_data
* @param data: bytes buffer you want to create the node from
- * returns a node with the data you inputted.
+ * @param data_size the size of the data
+ * @param node the pointer to the new node
+ * @returns true(1) on success
*/
-struct Node * N_Create_From_Data(unsigned char * data, size_t data_size);
+int ipfs_node_new_from_data(unsigned char * data, size_t data_size, struct Node** node);
-/*N_Create_From_Encoded
- * @param data: encoded bytes buffer you want to create the node from
- * returns a node with the encoded data you inputted.
+/***
+ * create a Node struct from encoded data
+ * @param data: encoded bytes buffer you want to create the node from. Note: this copies the pointer, not a memcpy
+ * @param node a pointer to the node that will be created
+ * @returns true(1) on success
*/
-struct Node * N_Create_From_Encoded(unsigned char * data);
+int ipfs_node_new_from_encoded(unsigned char * data, struct Node** node);
/*Node_Resolve_Max_Size
* !!!This shouldn't concern you!
@@ -179,7 +212,7 @@ struct Link_Proc
{
char * remaining_links; // Not your concern.
int ammount; //This will store the ammount of links, so you know what to process.
- struct Link * links[]; // Link array
+ struct NodeLink * links[]; // Link array
};
/*Node_Resolve_Links
diff --git a/include/ipfs/path/path.h b/include/ipfs/path/path.h
index 9ad58f4..e588c67 100644
--- a/include/ipfs/path/path.h
+++ b/include/ipfs/path/path.h
@@ -1,28 +1,7 @@
#ifndef IPFS_PATH_H
#define IPFS_PATH_H
- #ifdef IPFS_PATH_C
- char *ErrPath[] = {
- NULL,
- // ErrBadPath is returned when a given path is incorrectly formatted
- "invalid 'ipfs ref' path",
- // Paths after a protocol must contain at least one component
- "path must contain at least one component",
- "TODO: ErrCidDecode",
- NULL,
- "no link named %s under %s"
- };
- #else
- extern char **ErrPath;
- #endif // IPFS_PATH_C
-
- enum {
- ErrBadPath = 1,
- ErrNoComponents,
- ErrCidDecode,
- ErrNoLink,
- ErrNoLinkFmt
- } PathErrs;
+ #include "ipfs/errs.h"
char* ipfs_path_from_cid (struct Cid *c);
char** ipfs_path_split_n (char *p, char *delim, int n);
diff --git a/merkledag/Makefile b/merkledag/Makefile
index a5f0784..aadae27 100644
--- a/merkledag/Makefile
+++ b/merkledag/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/merkledag/merkledag.c b/merkledag/merkledag.c
index b118c65..e9a0bc4 100644
--- a/merkledag/merkledag.c
+++ b/merkledag/merkledag.c
@@ -13,9 +13,15 @@
int ipfs_merkledag_add(struct Node* node, struct FSRepo* fs_repo) {
// taken from merkledag.go line 59
+ // protobuf the node
+ size_t protobuf_len = ipfs_node_protobuf_encode_size(node);
+ size_t bytes_written = 0;
+ unsigned char protobuf[protobuf_len];
+ ipfs_node_protobuf_encode(node, protobuf, protobuf_len, &bytes_written);
+
// turn the node into a block
struct Block* block;
- ipfs_blocks_block_new(node->data, node->data_size, &block);
+ ipfs_blocks_block_new(protobuf, bytes_written, &block);
int retVal = fs_repo->config->datastore->datastore_put_block(block, fs_repo->config->datastore);
if (retVal == 0) {
@@ -23,7 +29,7 @@ int ipfs_merkledag_add(struct Node* node, struct FSRepo* fs_repo) {
return 0;
}
- Node_Set_Cached(node, block->cid);
+ ipfs_node_set_cached(node, block->cid);
ipfs_blocks_block_free(block);
// TODO: call HasBlock (unsure why as yet)
@@ -47,8 +53,8 @@ int ipfs_merkledag_get(const struct Cid* cid, struct Node** node, const struct F
return 0;
// we have the block. Fill the node
- *node = N_Create_From_Data(block->data, block->data_length);
- Node_Set_Cached(*node, cid);
+ ipfs_node_protobuf_decode(block->data, block->data_length, node);
+ ipfs_node_set_cached(*node, cid);
ipfs_blocks_block_free(block);
diff --git a/namesys/dns.c b/namesys/dns.c
index 0991a8d..23d7e9a 100644
--- a/namesys/dns.c
+++ b/namesys/dns.c
@@ -51,7 +51,7 @@ type lookupRes struct {
int ipfs_dns_resolver_resolve_once (char **path, char *name)
{
char **segments, *domain, *dnslink, buf[500], dlprefix[] = "_dnslink.";
- int p1[2], p2[2], r, c=2;
+ int p1[2], p2[2], r, l, c=2;
struct pollfd event[2], *e;
segments = ipfs_path_split_n(name, "/", 2);
@@ -84,12 +84,14 @@ int ipfs_dns_resolver_resolve_once (char **path, char *name)
case 0: // child
close(p2[STDIN_FILENO]); // we don't need to read at child process.
- dnslink = malloc(strlen(domain) + sizeof(dlprefix));
+ l = strlen(domain) + sizeof(dlprefix);
+ dnslink = malloc(l);
if (!dnslink) {
return ErrAllocFailed;
}
- strcpy (dnslink, dlprefix);
- strcat (dnslink, domain);
+ dnslink[--l] = '\0';
+ strncpy (dnslink, dlprefix, l);
+ strncat (dnslink, domain, l - strlen(dnslink));
return ipfs_dns_work_domain (p2[STDOUT_FILENO], r, dnslink);
}
@@ -114,7 +116,8 @@ int ipfs_dns_resolver_resolve_once (char **path, char *name)
buf[r] = '\0';
*path = malloc(r+1);
if (*path) {
- strcpy(*path, buf);
+ *path[r] = '\0';
+ strncpy(*path, buf, r);
}
} else if (r <= 0) {
return ErrPoll;
@@ -187,7 +190,7 @@ int ipfs_dns_parse_entry (char **path, char *txt)
if (!*path) {
return ErrAllocFailed;
}
- strcpy(*path, buf);
+ memcpy(*path, buf, strlen(buf) + 1);
return 0;
}
return ipfs_dns_try_parse_dns_link(path, txt);
@@ -205,7 +208,7 @@ int ipfs_dns_try_parse_dns_link(char **path, char *txt)
if (! *parts) {
return ErrAllocFailed;
}
- strcpy(*parts, buf);
+ memcpy(*parts, buf, strlen(buf) + 1);
return 0;
}
return err;
diff --git a/namesys/isdomain.c b/namesys/isdomain.c
index ec9d2ca..5317070 100644
--- a/namesys/isdomain.c
+++ b/namesys/isdomain.c
@@ -90,10 +90,14 @@ int ipfs_isdomain_is_tld (char *s)
// It first checks the TLD, and then uses a regular expression.
int ipfs_isdomain_is_domain (char *s)
{
- char str[strlen(s)];
- char *tld;
+ int err;
+ char *str, *tld;
- strcpy(str, s);
+ str = malloc(strlen(s) + 1);
+ if (!str) {
+ return ErrAllocFailed;
+ }
+ memcpy(str, s, strlen(s) + 1);
s = str; // work with local copy.
if (ipfs_isdomain_has_suffix (s, ".")) {
@@ -112,5 +116,7 @@ int ipfs_isdomain_is_domain (char *s)
return 0;
}
- return ipfs_isdomain_match_string(s);
+ err = ipfs_isdomain_match_string(s);
+ free (s);
+ return err;
}
diff --git a/namesys/namesys.c b/namesys/namesys.c
index fd534a4..9b3abff 100644
--- a/namesys/namesys.c
+++ b/namesys/namesys.c
@@ -3,7 +3,6 @@
#include
#include "ipfs/cid/cid.h"
#include "ipfs/path/path.h"
-#define NAMESYS_C
#include "ipfs/namesys/namesys.h"
/* mpns (a multi-protocol NameSystem) implements generic IPFS naming.
@@ -55,7 +54,7 @@ int ipfs_namesys_resolve_n(char **path, char *name, int depth)
ipfs_path_parse(p, name);
*path = malloc(strlen(p) + 1);
if (*p) {
- strcpy(*path, p);
+ memcpy(*path, p, strlen(p) + 1);
} else {
err = ErrAllocFailed;
}
@@ -63,18 +62,22 @@ int ipfs_namesys_resolve_n(char **path, char *name, int depth)
}
if (*name == '/') {
- int err;
- char *str = malloc(sizeof(ipfs_prefix) + strlen(name));
+ int err, l;
+ char *str;
+
+ l = sizeof(ipfs_prefix) + strlen(name);
+ str = malloc(l);
if (!str) {
return ErrAllocFailed;
}
- strcpy(str, ipfs_prefix);
- strcat(str, name+1); // ignore inital / from name, because ipfs_prefix already has it.
+ str[--l] = '\0';
+ strncpy(str, ipfs_prefix, l);
+ strncat(str, name+1, l - strlen (str)); // ignore inital / from name, because ipfs_prefix already has it.
err = ipfs_path_parse(p, str); // save return value.
free (str); // so we can free allocated memory before return.
*path = malloc(strlen(p) + 1);
if (*p) {
- strcpy(*path, p);
+ memcpy(*path, p, strlen(p) + 1);
} else {
err = ErrAllocFailed;
}
@@ -97,12 +100,14 @@ int ipfs_namesys_resolve_once (char **path, char *name)
}
if (memcmp (name, ipns_prefix, strlen(ipns_prefix)) == 0) { // prefix missing.
- ptr = malloc(strlen(name) + sizeof(ipns_prefix));
+ i = strlen(name) + sizeof(ipns_prefix);
+ ptr = malloc(i);
if (!ptr) { // allocation fail.
return ErrAllocFailed;
}
- strcpy(ptr, ipns_prefix);
- strcat(ptr, name);
+ ptr[--i] = '\0';
+ strncpy(ptr, ipns_prefix, i);
+ strncat(ptr, name, i - strlen(ptr));
segs = ipfs_path_split_segments(ptr);
free (ptr);
} else {
diff --git a/namesys/proquint.c b/namesys/proquint.c
index ded1995..561b4f0 100644
--- a/namesys/proquint.c
+++ b/namesys/proquint.c
@@ -176,7 +176,7 @@ int ipfs_proquint_resolve_once (char **p, char *name)
if (!err) {
*p = malloc (strlen(buf) + 1);
if (p) {
- strcpy(*p, buf);
+ memcpy(*p, buf, strlen(buf) + 1);
}
}
}
diff --git a/node/Makefile b/node/Makefile
index 607fbec..40240eb 100644
--- a/node/Makefile
+++ b/node/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/node/node.c b/node/node.c
index 3dc0c51..8d037f2 100644
--- a/node/node.c
+++ b/node/node.c
@@ -10,74 +10,302 @@
#include "ipfs/node/node.h"
+// for protobuf Node data & data_size encoded cid link_amount & links
+enum WireType ipfs_node_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED };
+// for protobuf NodeLink name cid
+enum WireType ipfs_node_link_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED };
+
/*====================================================================================
* Link Functions
*===================================================================================*/
-/* Create_Link
+/* ipfs_node_link_new
* @Param name: The name of the link (char *)
* @Param size: Size of the link (size_t)
* @Param ahash: An Qmhash
*/
-struct Link * Create_Link(char * name, unsigned char * ahash)
+int ipfs_node_link_new(char * name, unsigned char * ahash, struct NodeLink** node_link)
{
- struct Link * mylink;
- mylink = malloc(sizeof(struct Link));
- mylink->name = name;
+ *node_link = malloc(sizeof(struct NodeLink));
+ if (*node_link == NULL)
+ return 0;
+ (*node_link)->name = name;
+ (*node_link)->next = NULL;
int ver = 0;
- size_t lenhash = strlen((char*)ahash)-1;
- ipfs_cid_new(ver, ahash, lenhash*2, CID_PROTOBUF, &mylink->Lcid);
- mylink->size = sizeof(mylink) + mylink->Lcid->hash_length; //Unsure of this
- return mylink;
+ size_t lenhash = strlen((char*)ahash);
+ if (ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &(*node_link)->cid) == 0) {
+ free(*node_link);
+ return 0;
+ }
+ return 1;
}
-/* Free_Link
- * @param L: Free the link you have allocated.
+/* ipfs_node_link_free
+ * @param node_link: Free the link you have allocated.
*/
-void Free_Link(struct Link * L)
+int ipfs_node_link_free(struct NodeLink * node_link)
{
- ipfs_cid_free(L->Lcid);
- free(L);
+ if (node_link != NULL)
+ ipfs_cid_free(node_link->cid);
+ free(node_link);
+ return 1;
}
+
+int ipfs_node_link_protobuf_encode_size(struct NodeLink* link) {
+ if (link == NULL)
+ return 0;
+
+ size_t size = 0;
+ size += 11 + strlen(link->name);
+ size += ipfs_cid_protobuf_encode_size(link->cid);
+ return size;
+}
+
+int ipfs_node_link_protobuf_encode(struct NodeLink* link, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) {
+ size_t bytes_used = 0;
+ int retVal = 0;
+ *bytes_written = 0;
+ retVal = protobuf_encode_length_delimited(1, ipfs_node_link_message_fields[0], link->name, strlen(link->name), &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ // cid
+ size_t cid_size = ipfs_cid_protobuf_encode_size(link->cid);
+ unsigned char cid_buffer[cid_size];
+ retVal = ipfs_cid_protobuf_encode(link->cid, cid_buffer, cid_size, &bytes_used);
+ retVal = protobuf_encode_length_delimited(2, ipfs_node_link_message_fields[1], cid_buffer, bytes_used, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ return 1;
+}
+
+int ipfs_node_link_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct NodeLink** link, size_t* bytes_read) {
+ size_t pos = 0;
+ int retVal = 0;
+ *link = (struct NodeLink*)malloc(sizeof(struct NodeLink));
+ (*link)->cid = NULL;
+ (*link)->name = NULL;
+ (*link)->next = NULL;
+ unsigned char* temp_buffer = NULL;
+ size_t temp_size;
+
+ if (*link == NULL)
+ goto exit;
+ while(pos < buffer_length) {
+ size_t bytes_read = 0;
+ int field_no;
+ enum WireType field_type;
+ if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
+ goto exit;
+ }
+ pos += bytes_read;
+ switch(field_no) {
+ case (1):
+ if (protobuf_decode_string(&buffer[pos], buffer_length - pos, &((*link)->name), &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ break;
+ case (2):
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&temp_buffer, &temp_size, &bytes_read) == 0)
+ goto exit;
+ ipfs_cid_protobuf_decode(temp_buffer, temp_size, &((*link)->cid));
+ pos += bytes_read;
+ free(temp_buffer);
+ temp_buffer = NULL;
+ break;
+ }
+ }
+
+ retVal = 1;
+
+exit:
+ if (retVal == 0) {
+ if (link != NULL)
+ ipfs_node_link_free(*link);
+ }
+ if (temp_buffer != NULL)
+ free(temp_buffer);
+
+ return retVal;
+}
+
+/***
+ * return an approximate size of the encoded node
+ */
+size_t ipfs_node_protobuf_encode_size(struct Node* node) {
+ size_t size = 0;
+ // data
+ size += 11 + node->data_size;
+ // encoded
+ size += 11;
+ if (node->encoded != NULL)
+ size += strlen((const char*)node->encoded);
+ // cid (a.k.a. cached)
+ size += 11 + ipfs_cid_protobuf_encode_size(node->cached);
+ // links
+ size += 11;
+ struct NodeLink* current = node->head_link;
+ while(current != NULL) {
+ size += 11 + strlen(current->name) + ipfs_cid_protobuf_encode_size(current->cid);
+ current = current->next;
+ }
+ return size;
+}
+
+/***
+ * Encode a node into a protobuf byte stream
+ * @param node the node to encode
+ * @param buffer where to put it
+ * @param max_buffer_length the length of buffer
+ * @param bytes_written how much of buffer was used
+ * @returns true(1) on success
+ */
+int ipfs_node_protobuf_encode(struct Node* node, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) {
+ // data & data_size
+ size_t bytes_used = 0;
+ *bytes_written = 0;
+ int retVal = 0;
+ retVal = protobuf_encode_length_delimited(1, ipfs_node_message_fields[0], node->data, node->data_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ int sz = 0;
+ if (node->encoded != NULL)
+ sz = strlen(node->encoded);
+ retVal = protobuf_encode_length_delimited(2, ipfs_node_message_fields[1], node->encoded, sz, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ // cid
+ size_t cid_size = ipfs_cid_protobuf_encode_size(node->cached);
+ unsigned char cid[cid_size];
+ retVal = ipfs_cid_protobuf_encode(node->cached, cid, cid_size, &cid_size);
+ retVal = protobuf_encode_length_delimited(3, ipfs_node_message_fields[2], cid, cid_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ // links
+ struct NodeLink* current = node->head_link;
+ while(current != NULL) {
+ // size + name + cid
+ size_t link_buffer_size = 11 + ipfs_node_link_protobuf_encode_size(current);
+ unsigned char link_buffer[link_buffer_size];
+ retVal = ipfs_node_link_protobuf_encode(current, link_buffer, link_buffer_size, &link_buffer_size);
+ protobuf_encode_length_delimited(4, ipfs_node_message_fields[3], link_buffer, link_buffer_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
+ *bytes_written += bytes_used;
+ current = current->next;
+ }
+
+ return 1;
+}
+
+/***
+ * Decode a stream of bytes into a Node structure
+ * @param buffer where to get the bytes from
+ * @param buffer_length the length of buffer
+ * @param node pointer to the Node to be created
+ * @returns true(1) on success
+ */
+int ipfs_node_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Node** node) {
+ /*
+ * Field 0: data
+ * Field 1: encoded
+ * Field 3: cid
+ * Field 4: links array
+ */
+ size_t pos = 0;
+ int retVal = 0;
+ unsigned char* temp_buffer = NULL;
+ size_t temp_size;
+ struct NodeLink* temp_link = NULL;
+
+ if (ipfs_node_new(node) == 0)
+ goto exit;
+
+ while(pos < buffer_length) {
+ size_t bytes_read = 0;
+ int field_no;
+ enum WireType field_type;
+ if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
+ goto exit;
+ }
+ pos += bytes_read;
+ switch(field_no) {
+ case (1): // data
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*node)->data), &((*node)->data_size), &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ break;
+ case (2): // encoded
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*node)->encoded), &temp_size, &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ break;
+ case (3): // cid
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&temp_buffer, &temp_size, &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ if (ipfs_cid_protobuf_decode(temp_buffer, temp_size, &((*node)->cached)) == 0)
+ goto exit;
+ free(temp_buffer);
+ temp_buffer = NULL;
+ break;
+ case (4): // links
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&temp_buffer, &temp_size, &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ if (ipfs_node_link_protobuf_decode(temp_buffer, temp_size, &temp_link, &bytes_read) == 0)
+ goto exit;
+ free(temp_buffer);
+ temp_buffer = NULL;
+ ipfs_node_add_link(*node, temp_link);
+ break;
+ }
+ }
+
+ retVal = 1;
+
+exit:
+ if (retVal == 0) {
+ ipfs_node_free(*node);
+ }
+ if (temp_buffer != NULL)
+ free(temp_buffer);
+
+ return retVal;
+}
+
/*====================================================================================
* Node Functions
*===================================================================================*/
-/*Create_Empty_Node
+/*ipfs_node_new
* Creates an empty node, allocates the required memory
* Returns a fresh new node with no data set in it.
*/
-struct Node * Create_Empty_Node()
+int ipfs_node_new(struct Node** node)
{
- struct Node * N;
- N = (struct Node *)malloc(sizeof(struct Node));
- N->cached = NULL;
- N->data = NULL;
- N->encoded = NULL;
- N->link_ammount = 0;
- return N;
+ *node = (struct Node *)malloc(sizeof(struct Node));
+ if (*node == NULL)
+ return 0;
+ (*node)->cached = NULL;
+ (*node)->data = NULL;
+ (*node)->encoded = NULL;
+ (*node)->head_link = NULL;
+ return 1;
}
/**
* Set the cached struct element
- * @param N the node to be modified
- * @param TheCid the Cid to be copied into the Node->cached element
+ * @param node the node to be modified
+ * @param cid the Cid to be copied into the Node->cached element
* @returns true(1) on success
*/
-int Node_Set_Cached(struct Node * N, struct Cid * TheCid)
+int ipfs_node_set_cached(struct Node* node, struct Cid* cid)
{
- if (N->cached != NULL)
- ipfs_cid_free(N->cached);
- return ipfs_cid_new(TheCid->version, TheCid->hash, TheCid->hash_length, TheCid->codec, &(N->cached));
+ if (node->cached != NULL)
+ ipfs_cid_free(node->cached);
+ return ipfs_cid_new(cid->version, cid->hash, cid->hash_length, cid->codec, &(node->cached));
}
-/*Node_Set_Data
+/*ipfs_node_set_data
* Sets the data of a node
* @param Node: The node which you want to set data in.
* @param Data, the data you want to assign to the node
* Sets pointers of encoded & cached to NULL /following go method
* returns 1 on success 0 on failure
*/
-int Node_Set_Data(struct Node * N, unsigned char * Data)
+int ipfs_node_set_data(struct Node * N, unsigned char * Data, size_t data_size)
{
if(!N || !Data)
{
@@ -85,16 +313,21 @@ int Node_Set_Data(struct Node * N, unsigned char * Data)
}
N->encoded = NULL;
N->cached = NULL;
- N->data = Data;
+ N->data = malloc(sizeof(unsigned char) * data_size);
+ if (N->data == NULL)
+ return 0;
+
+ memcpy(N->data, Data, data_size);
+ N->data_size = data_size;
return 1;
}
-/*Node_Set_Encoded
+/*ipfs_node_set_encoded
* @param NODE: the node you wish to alter (struct Node *)
* @param Data: The data you wish to set in encoded.(unsigned char *)
* returns 1 on success 0 on failure
*/
-int Node_Set_Encoded(struct Node * N, unsigned char * Data)
+int ipfs_node_set_encoded(struct Node * N, unsigned char * Data)
{
if(!N || !Data)
{
@@ -106,52 +339,65 @@ int Node_Set_Encoded(struct Node * N, unsigned char * Data)
//N->data = NULL;
return 1;
}
-/*Node_Get_Data
+/*ipfs_node_get_data
* Gets data from a node
* @param Node: = The node you want to get data from. (unsigned char *)
* Returns data of node.
*/
-unsigned char * Node_Get_Data(struct Node * N)
+unsigned char * ipfs_node_get_data(struct Node * N)
{
unsigned char * DATA;
DATA = N->data;
return DATA;
}
-/*Node_Copy: Returns a copy of the node you input
- * @param Node: The node you want to copy (struct CP_Node *)
- * Returns a copy of the node you wanted to copy.
- */
-struct Node * Node_Copy(struct Node * CP_Node)
-{
- struct Node * CN;
- CN = (struct Node*) malloc(sizeof(struct Node) + sizeof(struct Link) * 2);
- if(CP_Node->link_ammount != 0)
- {
- for(int i=0; ilink_ammount; i++)
- {
- CN->links[i] = malloc(sizeof(struct Link));
- }
+struct NodeLink* ipfs_node_link_last(struct Node* node) {
+ struct NodeLink* current = node->head_link;
+ while(current != NULL) {
+ if (current->next == NULL)
+ break;
+ current = current->next;
}
- memcpy(CN, CP_Node, sizeof(struct Node));
- memcpy(CN->links[0],CP_Node->links[0], sizeof(struct Link));
- return CN;
+ return current;
}
-/*Node_Delete
+
+int ipfs_node_remove_link(struct Node* node, struct NodeLink* toRemove) {
+ struct NodeLink* current = node->head_link;
+ struct NodeLink* previous = NULL;
+ while(current != NULL && current != toRemove) {
+ previous = current;
+ current = current->next;
+ }
+ if (current != NULL) {
+ if (previous == NULL) {
+ // we're trying to delete the head
+ previous = current->next;
+ ipfs_node_link_free(current);
+ node->head_link = previous;
+ } else {
+ // we're in the middle or end
+ previous = current->next;
+ ipfs_node_link_free(current);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*ipfs_node_free
* Once you are finished using a node, always delete it using this.
* It will take care of the links inside it.
* @param N: the node you want to free. (struct Node *)
*/
-void Node_Delete(struct Node * N)
+void ipfs_node_free(struct Node * N)
{
- if(N)
+ if(N != NULL)
{
- if(N->link_ammount > 0)
- {
- for(int i=0; ilink_ammount; i++)
- {
- free(N->links[i]);
- }
+ struct NodeLink* current = ipfs_node_link_last(N);
+ while (current != NULL) {
+ struct NodeLink* toDelete = current;
+ current = current->next;
+ ipfs_node_remove_link(N, toDelete);
}
if(N->cached)
{
@@ -163,137 +409,132 @@ void Node_Delete(struct Node * N)
free(N);
}
}
-/*Node_Get_Link
+
+/*ipfs_node_get_link_by_name
* Returns a copy of the link with given name
* @param Name: (char * name) searches for link with this name
* Returns the link struct if it's found otherwise returns NULL
*/
-struct Link * Node_Get_Link(struct Node * N, char * Name)
+struct NodeLink * ipfs_node_get_link_by_name(struct Node * N, char * Name)
{
- struct Link * L;
- for(int i=0;ilink_ammount;i++)
- {
- if(strcmp(N->links[i]->name,Name) == 0)
- {
- L = (struct Link *)malloc(sizeof(struct Link));
- memcpy(L,N->links[i],sizeof(struct Link));
- int ver = L->Lcid->version;
- unsigned char * ahash = L->Lcid->hash;
- size_t lenhash = L->Lcid->hash_length;
- ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &L->Lcid);
- return L;
- }
+ struct NodeLink* current = N->head_link;
+ while(current != NULL && strcmp(Name, current->name) != 0) {
+ current = current->next;
}
- return NULL;
+ return current;
}
-/*Node_Remove_Link
+
+/*ipfs_node_remove_link_by_name
* Removes a link from node if found by name.
* @param name: Name of link (char * name)
* returns 1 on success, 0 on failure.
*/
-int Node_Remove_Link(char * Name, struct Node * mynode)
+int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode)
{
- for(int i=0; ilink_ammount; i++)
- {
- if(mynode->links[i]->name == Name)
- {
- for(int x=i;xlink_ammount && x+1 != mynode->link_ammount;i++)
- {
- memcpy(mynode->links[x],mynode->links[x+1],sizeof(struct Link));
- }
- free(mynode->links[mynode->link_ammount-1]);
- mynode->link_ammount--;
- return 1;
+ struct NodeLink* current = mynode->head_link;
+ struct NodeLink* previous = NULL;
+ while( (current != NULL)
+ && (( Name == NULL && current->name != NULL )
+ || ( Name != NULL && current->name == NULL )
+ || ( Name != NULL && current->name != NULL && strcmp(Name, current->name) != 0) ) ) {
+ previous = current;
+ current = current->next;
+ }
+ if (current != NULL) {
+ // we found it
+ if (previous == NULL) {
+ // we're first, use the next one (if there is one)
+ if (current->next != NULL)
+ mynode->head_link = current->next;
+ } else {
+ // we're somewhere in the middle, remove me from the list
+ previous->next = current->next;
+ ipfs_node_link_free(current);
}
+
+ return 1;
}
return 0;
}
-/* N_Add_Link
- * Adds a link to your node
+
+/* ipfs_node_add_link
+ * Adds a link to your nodse
* @param mynode: &yournode
* @param mylink: the CID you want to create a node from
* @param linksz: sizeof(your cid here)
* Returns your node with the newly added link
*/
-struct Node * N_Add_Link(struct Node ** mynode, struct Link * mylink, size_t linksz)
+int ipfs_node_add_link(struct Node* Nl, struct NodeLink * mylink)
{
- struct Node * Nl = *mynode;
- Nl->link_ammount++;
- size_t calculatesize = 0;
- if(Nl->link_ammount != 0)
- {
- for(int i=0; ilink_ammount-1;i++)
- {
- calculatesize = calculatesize + sizeof(Nl->links[i]);
+ if(Nl->head_link != NULL) {
+ // add to existing by finding last one
+ struct NodeLink* current_end = Nl->head_link;
+ while(current_end->next != NULL) {
+ current_end = current_end->next;
}
- calculatesize = calculatesize + linksz;
- Nl = (struct Node *) realloc(Nl, sizeof(struct Node) + calculatesize);
+ // now we have the last one, add to it
+ current_end->next = mylink;
}
else
{
- Nl = (struct Node *) malloc(sizeof(struct Node) + linksz);
+ Nl->head_link = mylink;
}
- Nl->links[Nl->link_ammount-1] = malloc(sizeof(struct Link));
- memcpy(Nl->links[Nl->link_ammount-1],mylink,sizeof(struct Link));
- return Nl;
+ return 1;
}
-/*N_Create_From_Link
+/*ipfs_node_new_from_link
* Create a node from a link
* @param mylink: the link you want to create it from. (struct Cid *)
* @param linksize: sizeof(the link in mylink) (size_T)
* Returns a fresh new node with the link you specified. Has to be freed with Node_Free preferably.
*/
-struct Node * N_Create_From_Link(struct Link * mylink)
+int ipfs_node_new_from_link(struct NodeLink * mylink, struct Node** node)
{
- struct Node * mynode;
- mynode = (struct Node *) malloc(sizeof(struct Node) + sizeof(struct Link));
- mynode->link_ammount = 0;
- mynode->link_ammount++;
- mynode->links[0] = malloc(sizeof(struct Link));
- memcpy(mynode->links[0], mylink, sizeof(struct Link));
- mynode->cached = NULL;
- mynode->data = NULL;
- mynode->encoded = NULL;
- return mynode;
+ *node = (struct Node *) malloc(sizeof(struct Node));
+ if (*node == NULL)
+ return 0;
+ (*node)->head_link = NULL;
+ ipfs_node_add_link(*node, mylink);
+ (*node)->cached = NULL;
+ (*node)->data = NULL;
+ (*node)->encoded = NULL;
+ return 1;
}
-/*N_Create_From_Data
+
+/**
+ * create a new Node struct with data
* @param data: bytes buffer you want to create the node from
+ * @param data_size the size of the data buffer
+ * @param node a pointer to the node to be created
* returns a node with the data you inputted.
*/
-struct Node * N_Create_From_Data(unsigned char * data, size_t data_size)
+int ipfs_node_new_from_data(unsigned char * data, size_t data_size, struct Node** node)
{
if(data)
{
- struct Node * mynode;
- mynode = (struct Node *) malloc(sizeof(struct Node));
- mynode->data = malloc(sizeof(unsigned char) * data_size);
- memcpy(mynode->data, data, data_size);
- mynode->data_size = data_size;
- mynode->link_ammount=0;
- mynode->encoded = NULL;
- mynode->cached = NULL;
- return mynode;
+ if (ipfs_node_new(node) == 0)
+ return 0;
+ return ipfs_node_set_data(*node, data, data_size);
}
- return NULL;
+ return 0;
}
-/*N_Create_From_Encoded
- * @param data: encoded bytes buffer you want to create the node from
- * returns a node with the encoded data you inputted.
+
+/***
+ * create a Node struct from encoded data
+ * @param data: encoded bytes buffer you want to create the node from. Note: this copies the pointer, not a memcpy
+ * @param node a pointer to the node that will be created
+ * @returns true(1) on success
*/
-struct Node * N_Create_From_Encoded(unsigned char * data)
+int ipfs_node_new_from_encoded(unsigned char * data, struct Node** node)
{
if(data)
{
- struct Node * mynode;
- mynode = (struct Node *) malloc(sizeof(struct Node));
- mynode->encoded = data;
- mynode->link_ammount = 0;
- mynode->data = NULL;
- mynode->cached = NULL;
- return mynode;
+ if (ipfs_node_new(node) == 0)
+ return 0;
+ (*node)->encoded = data;
+ return 1;
}
- return NULL;
+ return 0;
}
/*Node_Resolve_Max_Size
* !!!This shouldn't concern you!
@@ -362,18 +603,18 @@ struct Link_Proc * Node_Resolve_Links(struct Node * N, char * path)
return NULL;
}
int expected_link_ammount = Node_Resolve_Max_Size(path);
- struct Link_Proc * LProc = (struct Link_Proc *) malloc(sizeof(struct Link_Proc) + sizeof(struct Link) * expected_link_ammount);
+ struct Link_Proc * LProc = (struct Link_Proc *) malloc(sizeof(struct Link_Proc) + sizeof(struct NodeLink) * expected_link_ammount);
LProc->ammount = 0;
char * linknames[expected_link_ammount];
Node_Resolve(linknames, path);
for(int i=0;ilinks[i] = (struct Link *)malloc(sizeof(struct Link));
- memcpy(LProc->links[i], proclink, sizeof(struct Link));
+ LProc->links[i] = (struct NodeLink *)malloc(sizeof(struct NodeLink));
+ memcpy(LProc->links[i], proclink, sizeof(struct NodeLink));
LProc->ammount++;
free(proclink);
}
@@ -395,7 +636,7 @@ void Free_Link_Proc(struct Link_Proc * LPRC)
{
for(int i=0;iammount;i++)
{
- Free_Link(LPRC->links[i]);
+ ipfs_node_link_free(LPRC->links[i]);
}
}
free(LPRC);
diff --git a/path/path.c b/path/path.c
index 88c6556..11e6fc8 100644
--- a/path/path.c
+++ b/path/path.c
@@ -1,7 +1,6 @@
#include
#include
#include
-#define IPFS_PATH_C
#include
// FromCid safely converts a cid.Cid type to a Path type
@@ -9,11 +8,14 @@ char* ipfs_path_from_cid (struct Cid *c)
{
const char prefix[] = "/ipfs/";
char *rpath, *cidstr = CidString(c);
+ int l;
- rpath = malloc(sizeof(prefix) + strlen(cidstr));
+ l = sizeof(prefix) + strlen(cidstr);
+ rpath = malloc(l);
if (!rpath) return NULL;
- strcpy(rpath, prefix);
- strcat(rpath, cidstr);
+ rpath[--l] = '\0';
+ strncpy(rpath, prefix, l);
+ strncat(rpath, cidstr, l - strlen(rpath));
return rpath;
}
@@ -48,7 +50,7 @@ char** ipfs_path_split_n (char *p, char *delim, int n)
return NULL;
}
- strcpy(rbuf, p); // keep original
+ memcpy(rbuf, p, strlen(p) + 1); // keep original
for (c = rbuf, i = 0 ; i < n && c ; i++) {
r[i] = c;
c = strstr(c, delim);
@@ -206,10 +208,11 @@ char *ipfs_path_from_segments(char *prefix, char **seg)
ret = malloc(retlen + 1); // allocate final string size + null terminator.
if (!ret) return NULL;
- strcpy(ret, prefix);
+ ret[retlen] = '\0';
+ strncpy(ret, prefix, retlen);
for (i = 0 ; seg[i] ; i++) {
- strcat(ret, "/");
- strcat(ret, seg[i]);
+ strncat(ret, "/", retlen - strlen(ret));
+ strncat(ret, seg[i], retlen - strlen(ret));
}
return ret;
}
@@ -232,7 +235,7 @@ int ipfs_path_parse_from_cid (char *dst, char *txt)
if (!r) {
return ErrCidDecode;
}
- strcpy (dst, r);
+ memcpy (dst, r, strlen(r) + 1);
free (r);
return 0;
}
@@ -252,7 +255,7 @@ int ipfs_path_parse (char *dst, char *txt)
}
err = ipfs_path_parse_from_cid (dst+plen, txt);
if (err == 0) { // only change dst if ipfs_path_parse_from_cid returned success.
- // Use memcpy instead of strcpy to avoid overwriting
+ // Use memcpy instead of strncpy to avoid overwriting
// result of ipfs_path_parse_from_cid with a null terminator.
memcpy (dst, prefix, plen);
}
@@ -264,11 +267,21 @@ int ipfs_path_parse (char *dst, char *txt)
if (i < 3) return ErrBadPath;
if (strcmp (txt, prefix) == 0) {
- char buf[strlen(txt+5)];
- strcpy (buf, txt+6); // copy to temp buffer.
+ char *buf;
+ i = strlen(txt+6);
+ buf = malloc(i + 1);
+ if (!buf) {
+ return ErrAllocFailed;
+ }
+ buf[i] = '\0';
+ strncpy (buf, txt+6, i); // copy to temp buffer.
c = strchr(buf, '/');
- if (c) *c = '\0';
- return ipfs_path_parse_from_cid(dst, buf);
+ if (c) {
+ *c = '\0';
+ }
+ err = ipfs_path_parse_from_cid(dst, buf);
+ free (buf);
+ return err;
} else if (strcmp (txt, "/ipns/") != 0) {
return ErrBadPath;
}
diff --git a/path/resolver.c b/path/resolver.c
index c4b410f..4d17129 100644
--- a/path/resolver.c
+++ b/path/resolver.c
@@ -87,7 +87,7 @@ int ipfs_path_resolve_path_components(Node ***nd, Context ctx, Resolver *s, char
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
int ipfs_path_resolve_links(Node ***result, Context ctx, Node *ndd, char **names)
{
- int err, idx = 0;
+ int err, idx = 0, l;
NodeLink *lnk;
Node *nd;
@@ -115,9 +115,10 @@ int ipfs_path_resolve_links(Node ***result, Context ctx, Node *ndd, char **names
if (ErrPath[ErrNoLink]) {
free(ErrPath[ErrNoLink]);
}
- ErrPath[ErrNoLink] = malloc(strlen(msg) + 1);
+ l = strlen(msg) + 1;
+ ErrPath[ErrNoLink] = malloc(l);
if (ErrPath[ErrNoLink]) {
- strcpy(ErrPath[ErrNoLink], msg);
+ memcpy(ErrPath[ErrNoLink], msg, l);
}
free (*result);
return ErrNoLink;
diff --git a/repo/config/Makefile b/repo/config/Makefile
index c0a1792..cf49611 100644
--- a/repo/config/Makefile
+++ b/repo/config/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../c-multihash/include -Wall
+CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../c-multihash/include -I../../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/repo/fsrepo/Makefile b/repo/fsrepo/Makefile
index 48e22d6..a4196c0 100644
--- a/repo/fsrepo/Makefile
+++ b/repo/fsrepo/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../lmdb/libraries/liblmdb -Wall
+CFLAGS = -O0 -I../../include -I../../../c-libp2p/include -I../../../lmdb/libraries/liblmdb -I../../../c-protobuf -Wall
ifdef DEBUG
CFLAGS += -g3
diff --git a/repo/fsrepo/lmdb_datastore.c b/repo/fsrepo/lmdb_datastore.c
index 62b29f5..9ac6e8d 100644
--- a/repo/fsrepo/lmdb_datastore.c
+++ b/repo/fsrepo/lmdb_datastore.c
@@ -175,10 +175,17 @@ int repo_fsrepo_lmdb_put(unsigned const char* key, size_t key_size, unsigned cha
* @returns true(1) on success
*/
int repo_fsrepo_lmdb_put_block(const struct Block* block, const struct Datastore* datastore) {
-
return repo_fsrepo_lmdb_put(block->cid->hash, block->cid->hash_length, block->data, block->data_length, datastore);
}
+/***
+ * Save a node in the datastore
+ */
+int repo_fsrepo_lmdb_put_node(const struct Node* node, const struct Datastore* datastore) {
+ // first the links, then the data
+
+}
+
/**
* Open an lmdb database with the given parameters.
* Note: for now, the parameters are not used
diff --git a/test/Makefile b/test/Makefile
index 9a247e6..c241eb0 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/ -g3 -Wall
+CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/ -I../../c-protobuf -g3 -Wall
LFLAGS = -L../../c-libp2p -L../../c-multihash -L../../c-multiaddr -lp2p -lm -lmultihash -lmultiaddr -lpthread
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
OBJS = testit.o test_helper.o \
@@ -18,7 +18,8 @@ OBJS = testit.o test_helper.o \
../repo/config/config.o ../repo/config/identity.o \
../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
+ ../thirdparty/ipfsaddr/ipfs_addr.o \
+ ../../c-protobuf/protobuf.o ../../c-protobuf/varint.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
diff --git a/test/cid/test_cid.h b/test/cid/test_cid.h
index aa28841..8eb0d6f 100644
--- a/test/cid/test_cid.h
+++ b/test/cid/test_cid.h
@@ -106,3 +106,50 @@ int test_cid_cast_non_multihash() {
return 1;
}
+int test_cid_protobuf_encode_decode() {
+ struct Cid tester;
+ tester.version = 1;
+ tester.codec = CID_ETHEREUM_BLOCK;
+ tester.hash = "ABC123";
+ tester.hash_length = 6;
+ size_t bytes_written_to_buffer;
+
+ // encode
+ size_t buffer_length = ipfs_cid_protobuf_encode_size(&tester);
+ unsigned char buffer[buffer_length];
+ ipfs_cid_protobuf_encode(&tester, buffer, buffer_length, &bytes_written_to_buffer);
+
+ // decode
+ struct Cid* results;
+ ipfs_cid_protobuf_decode(buffer, bytes_written_to_buffer, &results);
+
+ // compare
+ if (tester.version != results->version) {
+ printf("Version %d does not match version %d\n", tester.version, results->version);
+ ipfs_cid_free(results);
+ return 0;
+ }
+
+ if (tester.codec != results->codec) {
+ printf("Codec %02x does not match %02x\n", tester.codec, results->codec);
+ ipfs_cid_free(results);
+ return 0;
+ }
+
+ if (tester.hash_length != results->hash_length) {
+ printf("Hash length %d does not match %d\n", tester.hash_length, results->hash_length);
+ ipfs_cid_free(results);
+ return 0;
+ }
+
+ for(int i = 0; i < 6; i++) {
+ if (tester.hash[i] != results->hash[i]) {
+ printf("Hash character %c does not match %c at position %d", tester.hash[i], results->hash[i], i);
+ ipfs_cid_free(results);
+ return 0;
+ }
+ }
+
+ ipfs_cid_free(results);
+ return 1;
+}
diff --git a/test/merkledag/test_merkledag.h b/test/merkledag/test_merkledag.h
index be26a9d..632be2e 100644
--- a/test/merkledag/test_merkledag.h
+++ b/test/merkledag/test_merkledag.h
@@ -2,30 +2,35 @@
#include "ipfs/node/node.h"
#include "../test_helper.h"
-int test_merkledag_get_data() {
- int retVal = 0;
-
+struct FSRepo* createAndOpenRepo(const char* dir) {
+ int retVal = 1;
// create a fresh repo
- retVal = drop_and_build_repository("/tmp/.ipfs");
+ retVal = drop_and_build_repository(dir);
if (retVal == 0)
- return 0;
+ return NULL;
// open the fs repo
struct RepoConfig* repo_config = NULL;
struct FSRepo* fs_repo;
- const char* path = "/tmp/.ipfs";
// create the struct
- retVal = ipfs_repo_fsrepo_new((char*)path, repo_config, &fs_repo);
+ retVal = ipfs_repo_fsrepo_new(dir, repo_config, &fs_repo);
if (retVal == 0)
- return 0;
+ return NULL;
// open the repository and read the config file
retVal = ipfs_repo_fsrepo_open(fs_repo);
if (retVal == 0) {
ipfs_repo_fsrepo_free(fs_repo);
- return 0;
+ return NULL;
}
+ return fs_repo;
+}
+
+int test_merkledag_get_data() {
+ int retVal = 0;
+
+ struct FSRepo* fs_repo = createAndOpenRepo("/tmp/.ipfs");
// create data for node
size_t binary_data_size = 256;
@@ -35,11 +40,12 @@ int test_merkledag_get_data() {
}
// create a node
- struct Node* node1 = N_Create_From_Data(binary_data, binary_data_size);
+ struct Node* node1;
+ retVal = ipfs_node_new_from_data(binary_data, binary_data_size, &node1);
retVal = ipfs_merkledag_add(node1, fs_repo);
if (retVal == 0) {
- Node_Delete(node1);
+ ipfs_node_free(node1);
ipfs_repo_fsrepo_free(fs_repo);
return 0;
}
@@ -48,15 +54,15 @@ int test_merkledag_get_data() {
struct Node* results_node;
retVal = ipfs_merkledag_get(node1->cached, &results_node, fs_repo);
if (retVal == 0) {
- Node_Delete(node1);
- Node_Delete(results_node);
+ ipfs_node_free(node1);
+ ipfs_node_free(results_node);
ipfs_repo_fsrepo_free(fs_repo);
return 0;
}
if (results_node->data_size != 256) {
- Node_Delete(node1);
- Node_Delete(results_node);
+ ipfs_node_free(node1);
+ ipfs_node_free(results_node);
ipfs_repo_fsrepo_free(fs_repo);
return 0;
}
@@ -64,15 +70,15 @@ int test_merkledag_get_data() {
// the data should be the same
for(int i = 0; i < results_node->data_size; i++) {
if (results_node->data[i] != node1->data[i]) {
- Node_Delete(node1);
- Node_Delete(results_node);
+ ipfs_node_free(node1);
+ ipfs_node_free(results_node);
ipfs_repo_fsrepo_free(fs_repo);
return 0;
}
}
- Node_Delete(node1);
- Node_Delete(results_node);
+ ipfs_node_free(node1);
+ ipfs_node_free(results_node);
ipfs_repo_fsrepo_free(fs_repo);
return retVal;
@@ -81,28 +87,10 @@ int test_merkledag_get_data() {
int test_merkledag_add_data() {
int retVal = 0;
- // create a fresh repo
- retVal = drop_and_build_repository("/tmp/.ipfs");
- if (retVal == 0)
+ struct FSRepo* fs_repo = createAndOpenRepo("/tmp/.ipfs");
+ if (fs_repo == NULL)
return 0;
- // open the fs repo
- struct RepoConfig* repo_config = NULL;
- struct FSRepo* fs_repo;
- const char* path = "/tmp/.ipfs";
-
- // create the struct
- retVal = ipfs_repo_fsrepo_new((char*)path, repo_config, &fs_repo);
- if (retVal == 0)
- return 0;
-
- // open the repository and read the config file
- retVal = ipfs_repo_fsrepo_open(fs_repo);
- if (retVal == 0) {
- ipfs_repo_fsrepo_free(fs_repo);
- return 0;
- }
-
// get the size of the database
int start_file_size = os_utils_file_size("/tmp/.ipfs/datastore/data.mdb");
@@ -114,11 +102,12 @@ int test_merkledag_add_data() {
}
// create a node
- struct Node* node1 = N_Create_From_Data(binary_data, binary_data_size);
+ struct Node* node1;
+ retVal = ipfs_node_new_from_data(binary_data, binary_data_size, &node1);
retVal = ipfs_merkledag_add(node1, fs_repo);
if (retVal == 0) {
- Node_Delete(node1);
+ ipfs_node_free(node1);
return 0;
}
@@ -128,30 +117,31 @@ int test_merkledag_add_data() {
int first_add_size = os_utils_file_size("/tmp/.ipfs/datastore/data.mdb");
if (first_add_size == start_file_size) { // uh oh, database should have increased in size
- Node_Delete(node1);
+ ipfs_node_free(node1);
return 0;
}
// adding the same binary again should do nothing (the hash should be the same)
- struct Node* node2 = N_Create_From_Data(binary_data, binary_data_size);
+ struct Node* node2;
+ retVal = ipfs_node_new_from_data(binary_data, binary_data_size, &node2);
retVal = ipfs_merkledag_add(node2, fs_repo);
if (retVal == 0) {
- Node_Delete(node1);
- Node_Delete(node2);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
return 0;
}
// make sure everything is correct
if (node2->cached == NULL) {
- Node_Delete(node1);
- Node_Delete(node2);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
return 0;
}
for(int i = 0; i < node1->cached->hash_length; i++) {
if (node1->cached->hash[i] != node2->cached->hash[i]) {
printf("hash of node1 does not match node2 at position %d\n", i);
- Node_Delete(node1);
- Node_Delete(node2);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
return 0;
}
}
@@ -159,35 +149,36 @@ int test_merkledag_add_data() {
int second_add_size = os_utils_file_size("/tmp/.ipfs/datastore/data.mdb");
if (first_add_size != second_add_size) { // uh oh, the database shouldn't have changed size
printf("looks as if a new record was added when it shouldn't have. Old file size: %d, new file size: %d\n", first_add_size, second_add_size);
- Node_Delete(node1);
- Node_Delete(node2);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
return 0;
}
// now change 1 byte, which should change the hash
binary_data[10] = 0;
// create a node
- struct Node* node3 = N_Create_From_Data(binary_data, binary_data_size);
+ struct Node* node3;
+ retVal = ipfs_node_new_from_data(binary_data, binary_data_size, &node3);
retVal = ipfs_merkledag_add(node3, fs_repo);
if (retVal == 0) {
- Node_Delete(node1);
- Node_Delete(node2);
- Node_Delete(node3);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
+ ipfs_node_free(node3);
return 0;
}
// make sure everything is correct
if (node3->cached == NULL) {
- Node_Delete(node1);
- Node_Delete(node2);
- Node_Delete(node3);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
+ ipfs_node_free(node3);
return 0;
}
- Node_Delete(node1);
- Node_Delete(node2);
- Node_Delete(node3);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
+ ipfs_node_free(node3);
int third_add_size = os_utils_file_size("/tmp/.ipfs/datastore/data.mdb");
if (third_add_size == second_add_size || third_add_size < second_add_size) {// uh oh, it didn't add it
printf("Node 3 should have been added, but the file size did not change from %d.\n", third_add_size);
@@ -198,3 +189,61 @@ int test_merkledag_add_data() {
return 1;
}
+
+/**
+ * Should save links
+ */
+int test_merkledag_add_node_with_links() {
+ int retVal = 0;
+ struct Link* link = NULL;
+ struct Node* node1 = NULL;
+
+ struct FSRepo* fs_repo = createAndOpenRepo("/tmp/.ipfs");
+ if (fs_repo == NULL) {
+ printf("Unable to create repo\n");
+ return 0;
+ }
+
+ // make link
+ retVal = ipfs_node_link_new("", "abc123", &link);
+ retVal = ipfs_node_new_from_link(link, &node1);
+
+ retVal = ipfs_merkledag_add(node1, fs_repo);
+ if (retVal == 0) {
+ ipfs_repo_fsrepo_free(fs_repo);
+ ipfs_node_free(node1);
+ printf("Unable to add node\n");
+ return 0;
+ }
+
+ // now look for it
+ struct Node* node2 = NULL;
+ retVal = ipfs_merkledag_get(node1->cached, &node2, fs_repo);
+ if (retVal == 0) {
+ ipfs_repo_fsrepo_free(fs_repo);
+ ipfs_node_free(node1);
+ return 0;
+ }
+
+ struct NodeLink* node1_link = node1->head_link;
+ struct NodeLink* node2_link = node2->head_link;
+ while(node1_link != NULL) {
+ for(int i = 0; i < node1_link->cid->hash_length; i++) {
+ if(node1_link->cid->hash[i] != node2_link->cid->hash[i]) {
+ printf("Hashes do not match for node %s\n", node1_link->name);
+ ipfs_repo_fsrepo_free(fs_repo);
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
+ return 0;
+ }
+ }
+ node1_link = node1_link->next;
+ node2_link = node2_link->next;
+ }
+
+ ipfs_node_free(node1);
+ ipfs_node_free(node2);
+ ipfs_repo_fsrepo_free(fs_repo);
+
+ return 1;
+}
diff --git a/test/node/test_node.h b/test/node/test_node.h
index bdf89e9..ca0720f 100644
--- a/test/node/test_node.h
+++ b/test/node/test_node.h
@@ -3,40 +3,157 @@
int test_node() {
//Variables of link:
char * name = "Alex";
- unsigned char * ahash = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
- struct Link * mylink;
- mylink = Create_Link(name,ahash);
- printf("===================================\n" \
- "Node Link:\n" \
- " -Name: %s\n" \
- " -Size: %lu\n" \
- "\n Cid Details:\n\n" \
- " -Version: %d\n" \
- " -Codec: %c\n" \
- " -Hash: %s\n" \
- " -Hash Length: %lu\n" \
- "====================================\n" \
- , mylink->name, mylink->size, mylink->Lcid->version,mylink->Lcid->codec,mylink->Lcid->hash,mylink->Lcid->hash_length);
+ unsigned char * ahash = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
+ struct NodeLink * mylink;
+ int retVal = ipfs_node_link_new(name,ahash, &mylink);
+
//Link Two for testing purposes
char * name2 = "Simo";
- unsigned char * ahash2 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo";
- struct Link * mylink2;
- mylink2 = Create_Link(name2,ahash2);
+ unsigned char * ahash2 = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo";
+ struct NodeLink * mylink2;
+ retVal = ipfs_node_link_new(name2, ahash2, &mylink2);
+
//Nodes
struct Node * Mynode;
- Mynode = N_Create_From_Link(mylink);
- mylink->name = "HAHA";//Testing for valid node creation
- printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->Lcid->hash);
- Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2));
- mylink2->name = "HAHA";//Testing for valid node creation
- printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->Lcid->hash);
- struct Link * ResultLink = Node_Get_Link(Mynode, "Simo");
- printf("\nResultLink: \nName: %s\nHash: %s\n", ResultLink->name, ResultLink->Lcid->hash);
- Node_Remove_Link("Simo", Mynode);
- printf("Outlinkamt: %d\n", Mynode->link_ammount);
- Free_Link(mylink);
- Free_Link(mylink2);
- Free_Link(ResultLink);
- Node_Delete(Mynode);
+ retVal = ipfs_node_new_from_link(mylink, &Mynode);
+ //mylink->name = "HAHA";//Testing for valid node creation
+ retVal = ipfs_node_add_link(Mynode, mylink2);
+ //mylink2->name = "HAHA";//Testing for valid node creation
+ struct NodeLink * ResultLink = ipfs_node_get_link_by_name(Mynode, "Simo");
+ ipfs_node_remove_link_by_name("Simo", Mynode);
+ ipfs_node_free(Mynode);
return 1;
}
+
+int compare_link(struct NodeLink* link1, struct NodeLink* link2) {
+ if (strcmp(link1->name, link2->name) != 0) {
+ printf("Link Names are different %s vs. %s\n", link1->name, link2->name);
+ return 0;
+ }
+ if (link1->cid->codec != link2->cid->codec) {
+ printf("Link cid codecs are different. Expected %02x but got %02x\n", link1->cid->codec, link2->cid->codec);
+ return 0;
+ }
+ if (link1->cid->hash_length != link2->cid->hash_length) {
+ printf("Link cid hash lengths are different. Expected %d but got %d\n", link1->cid->hash_length, link2->cid->hash_length);
+ return 0;
+ }
+ if (link1->cid->version != link2->cid->version) {
+ printf("Link cid versions are different. Expected %d but got %d\n", link1->cid->version, link2->cid->version);
+ return 0;
+ }
+ if (memcmp(link1->cid->hash, link2->cid->hash, link1->cid->hash_length) != 0) {
+ printf("compare_link: The values of the hashes are different\n");
+ return 0;
+ }
+ return 1;
+}
+
+int test_node_link_encode_decode() {
+ struct NodeLink* control = NULL;
+ struct NodeLink* results = NULL;
+ size_t nl_size;
+ unsigned char* buffer = NULL;
+ int retVal = 0;
+
+ // make a NodeLink
+ if (ipfs_node_link_new("My Name", "QmMyHash", &control) == 0)
+ goto exit;
+
+ // encode it
+ nl_size = ipfs_node_link_protobuf_encode_size(control);
+ buffer = malloc(nl_size);
+ if (buffer == NULL)
+ goto exit;
+ if (ipfs_node_link_protobuf_encode(control, buffer, nl_size, &nl_size) == 0) {
+ goto exit;
+ }
+
+ // decode it
+ if (ipfs_node_link_protobuf_decode(buffer, nl_size, &results) == 0) {
+ goto exit;
+ }
+
+ // verify it
+ if (compare_link(control, results) == 0)
+ goto exit;
+ retVal = 1;
+exit:
+ if (control != NULL)
+ ipfs_node_link_free(control);
+ if (results != NULL)
+ ipfs_node_link_free(results);
+ return retVal;
+}
+
+/***
+ * Test a node with 2 links
+ */
+int test_node_encode_decode() {
+ struct Node* control = NULL;
+ struct Node* results = NULL;
+ struct NodeLink* link1 = NULL;
+ struct NodeLink* link2 = NULL;
+ int retVal = 0;
+ size_t buffer_length = 0;
+ unsigned char* buffer = NULL;
+
+ // node
+ if (ipfs_node_new(&control) == 0)
+ goto exit;
+
+ // first link
+ if (ipfs_node_link_new((char*)"Link1", (unsigned char*)"QmLink1", &link1) == 0)
+ goto exit;
+
+ if ( ipfs_node_add_link(control, link1) == 0)
+ goto exit;
+
+ // second link
+ if (ipfs_node_link_new((char*)"Link2", (unsigned char*)"QmLink2", &link2) == 0)
+ goto exit;
+ if ( ipfs_node_add_link(control, link2) == 0)
+ goto exit;
+
+ // encode
+ buffer_length = ipfs_node_protobuf_encode_size(control);
+ buffer = (unsigned char*)malloc(buffer_length);
+ if (ipfs_node_protobuf_encode(control, buffer, buffer_length, &buffer_length) == 0)
+ goto exit;
+
+ // decode
+ if (ipfs_node_protobuf_decode(buffer, buffer_length, &results) == 0)
+ goto exit;
+
+ // compare results
+
+ struct NodeLink* control_link = control->head_link;
+ struct NodeLink* results_link = results->head_link;
+ while(control_link != NULL) {
+ if (compare_link(control_link, results_link) == 0) {
+ printf("Error was on link %s\n", control_link->name);
+ goto exit;
+ }
+ control_link = control_link->next;
+ results_link = results_link->next;
+ }
+
+ if (control->data_size != results->data_size)
+ goto exit;
+
+ if (memcmp(results->data, control->data, control->data_size) != 0) {
+ goto exit;
+ }
+
+ retVal = 1;
+exit:
+ // clean up
+ if (control != NULL)
+ ipfs_node_free(control);
+ if (results != NULL)
+ ipfs_node_free(results);
+ if (buffer != NULL)
+ free(buffer);
+
+ return retVal;
+}
diff --git a/test/test_helper.c b/test/test_helper.c
index fdea41e..592669a 100644
--- a/test/test_helper.c
+++ b/test/test_helper.c
@@ -69,21 +69,25 @@ int remove_directory(const char *path)
int make_ipfs_repository(const char* path) {
int retVal;
+ char currDirectory[1024];
struct RepoConfig* repo_config;
- char currDirectory[1024];
- retVal = os_utils_filepath_join(path, "config", currDirectory, 1024);
- if (retVal == 0)
- return 0;
- unlink(currDirectory);
- retVal = os_utils_filepath_join(path, "datastore", currDirectory, 1024);
- if (retVal == 0)
- return 0;
- remove_directory(currDirectory);
- retVal = os_utils_filepath_join(path, "blockstore", currDirectory, 1024);
- if (retVal == 0)
- return 0;
- remove_directory(currDirectory);
+ if (os_utils_file_exists(path)) {
+ retVal = os_utils_filepath_join(path, "config", currDirectory, 1024);
+ if (retVal == 0)
+ return 0;
+ unlink(currDirectory);
+ retVal = os_utils_filepath_join(path, "datastore", currDirectory, 1024);
+ if (retVal == 0)
+ return 0;
+ remove_directory(currDirectory);
+ retVal = os_utils_filepath_join(path, "blockstore", currDirectory, 1024);
+ if (retVal == 0)
+ return 0;
+ remove_directory(currDirectory);
+ } else {
+ mkdir(path, S_IRWXU);
+ }
// build a default repo config
retVal = ipfs_repo_config_new(&repo_config);
diff --git a/test/testit.c b/test/testit.c
index 8da3a93..1ba6006 100644
--- a/test/testit.c
+++ b/test/testit.c
@@ -25,7 +25,7 @@ const char* names[] = {
"test_cid_new_free",
"test_cid_cast_multihash",
"test_cid_cast_non_multihash",
- //"test_init_new_installation",
+ "test_cid_protobuf_encode_decode",
"test_repo_config_new",
"test_repo_config_init",
"test_repo_config_write",
@@ -41,15 +41,18 @@ const char* names[] = {
"test_repo_bootstrap_peers_init",
"test_ipfs_datastore_put",
"test_node",
+ "test_node_link_encode_decode",
+ "test_node_encode_decode",
"test_merkledag_add_data",
- "test_merkledag_get_data"
+ "test_merkledag_get_data",
+ "test_merkledag_add_node_with_links"
};
int (*funcs[])(void) = {
test_cid_new_free,
test_cid_cast_multihash,
test_cid_cast_non_multihash,
- //test_init_new_installation,
+ test_cid_protobuf_encode_decode,
test_repo_config_new,
test_repo_config_init,
test_repo_config_write,
@@ -65,8 +68,11 @@ int (*funcs[])(void) = {
test_repo_bootstrap_peers_init,
test_ipfs_datastore_put,
test_node,
+ test_node_link_encode_decode,
+ test_node_encode_decode,
test_merkledag_add_data,
- test_merkledag_get_data
+ test_merkledag_get_data,
+ test_merkledag_add_node_with_links
};
/**
@@ -88,9 +94,12 @@ int main(int argc, char** argv) {
}
int array_length = sizeof(funcs) / sizeof(funcs[0]);
for (int i = 0; i < array_length; i++) {
- if (only_one && strcmp(names[i], test_wanted) == 0) {
- tests_ran++;
- counter += testit(names[i], funcs[i]);
+ if (only_one) {
+ char* currName = names[i];
+ if (strcmp(currName, test_wanted) == 0) {
+ tests_ran++;
+ counter += testit(names[i], funcs[i]);
+ }
}
else
if (!only_one) {