From 0d0c9bde535062cf8baf175b4c4d84e5b60af1bc Mon Sep 17 00:00:00 2001 From: John Jones Date: Sun, 19 Mar 2017 14:39:48 -0500 Subject: [PATCH] Finishing NodeIO --- include/libp2p/conn/session.h | 3 + include/libp2p/nodeio/nodeio.h | 16 +++- include/libp2p/peer/providerstore.h | 32 +++++++ include/libp2p/utils/vector.h | 55 +++++------- nodeio/nodeio.c | 47 ++++++++++- peer/Makefile | 2 +- peer/providerstore.c | 68 +++++++++++++++ utils/vector.c | 126 ++++++++++++++-------------- 8 files changed, 242 insertions(+), 107 deletions(-) create mode 100644 include/libp2p/peer/providerstore.h create mode 100644 peer/providerstore.c diff --git a/include/libp2p/conn/session.h b/include/libp2p/conn/session.h index 74c16c8..ca0068f 100644 --- a/include/libp2p/conn/session.h +++ b/include/libp2p/conn/session.h @@ -1,3 +1,6 @@ +#pragma once + +#include "libp2p/crypto/key.h" /*** * Holds the details of communication between two hosts */ diff --git a/include/libp2p/nodeio/nodeio.h b/include/libp2p/nodeio/nodeio.h index 58058db..83a9a7c 100644 --- a/include/libp2p/nodeio/nodeio.h +++ b/include/libp2p/nodeio/nodeio.h @@ -1,6 +1,18 @@ #pragma once #include "libp2p/net/stream.h" +#include "libp2p/conn/session.h" -int libp2p_nodeio_upgrade_stream(struct Stream* stream); -struct Node* libp2p_nodeio_get(struct Stream* stream, unsigned char* hash, int hash_length); +int libp2p_nodeio_upgrade_stream(struct SessionContext* context); +int libp2p_nodeio_handshake(struct SessionContext* context); +int libp2p_nodeio_handle(struct SessionContext* context); +/** + * Called by requestor to get a protobuf'd node from a hash + * @param context the session context + * @param hash the hash + * @param hash_size the length of the hash + * @param results where to put the buffer + * @param results_size the size of the results + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_nodeio_get(struct SessionContext* context, unsigned char* hash, int hash_size, unsigned char** results, size_t* results_length); diff --git a/include/libp2p/peer/providerstore.h b/include/libp2p/peer/providerstore.h new file mode 100644 index 0000000..2648876 --- /dev/null +++ b/include/libp2p/peer/providerstore.h @@ -0,0 +1,32 @@ +#pragma once + +struct ProviderEntry { + unsigned char* hash; + int hash_size; + unsigned char* peer_id; + int peer_id_size; +}; + +struct ProviderStore { + struct Libp2pVector* provider_entries; +}; + +/*** + * Stores hashes, and peers where you can possibly get them + */ + +/** + * Create a new ProviderStore + * @returns a ProviderStore struct + */ +struct ProviderStore* libp2p_providerstore_new(); + +/*** + * Clean resources used by a ProviderStore + * @param in the ProviderStore to clean up + */ +void libp2p_providerstore_free(struct ProviderStore* in); + +void libp2p_providerstore_add(struct ProviderStore* store, unsigned char* hash, int hash_size, unsigned char* peer_id, int peer_id_size); + +int libp2p_providerstore_get(struct ProviderStore* store, unsigned char* hash, int hash_size, unsigned char** peer_id, int *peer_id_size); diff --git a/include/libp2p/utils/vector.h b/include/libp2p/utils/vector.h index a778fbe..eb59961 100644 --- a/include/libp2p/utils/vector.h +++ b/include/libp2p/utils/vector.h @@ -1,41 +1,26 @@ #pragma once -/*** - * A very simple vector implementation for unsigned chars - */ +#define VECTOR_INIT_CAPACITY 4 + +//#define VECTOR_INIT(vec) vector vec; vector_init(&vec) +//#define VECTOR_ADD(vec, item) vector_add(&vec, (void *) item) +//#define VECTOR_SET(vec, id, item) vector_set(&vec, id, (void *) item) +//#define VECTOR_GET(vec, type, id) (type) vector_get(&vec, id) +//#define VECTOR_DELETE(vec, id) vector_delete(&vec, id) +//#define VECTOR_TOTAL(vec) vector_total(&vec) +//#define VECTOR_FREE(vec) vector_free(&vec) -/** - * The struct - */ struct Libp2pVector { - unsigned char* buffer; - size_t buffer_size; + void **items; + int capacity; + int total; }; -/** - * Create and destroy - */ -struct Libp2pVector* libp2p_utils_vector_new(); -void libp2p_utils_vector_free(struct Libp2pVector* vector); - -/** - * Add bytes to vector - */ -int libp2p_utils_vector_add(struct Libp2pVector* vector, unsigned char* in_bytes, size_t in_size); - -/** - * serialize the vector into a byte array that has a 4 byte prefix of the size - * @param vector the vector to serialize - * @param out a pointer to the byte array that will be filled - * @param out_size the number of bytes written - * @returns true(1) on success, otherwise false - */ -int libp2p_utils_vector_serialize(struct Libp2pVector* vector, unsigned char** out, size_t* out_size); - -/** - * turn a byte array into a Libp2pVector - * @param in the bytes that were previously serialized - * @param out the new Libp2pVector - * @returns true(1) on success, otherwise false(0) - */ -int libp2p_utils_vector_unserialize(unsigned char* in, struct Libp2pVector** out); +struct Libp2pVector* libp2p_utils_vector_new(int initial_size); +int libp2p_utils_vector_total(struct Libp2pVector* in); +//static void libp2p_utils_vector_resize(struct Libp2pVector *vector, int new_size); +void libp2p_utils_vector_add(struct Libp2pVector *vector, void * value); +void libp2p_utils_vector_set(struct Libp2pVector *vector, int pos, void *value); +void *libp2p_utils_vector_get(struct Libp2pVector *vector, int); +void libp2p_utils_vector_delete(struct Libp2pVector *vector, int pos); +void libp2p_utils_vector_free(struct Libp2pVector *vector); diff --git a/nodeio/nodeio.c b/nodeio/nodeio.c index f0a7ccd..a9d37e5 100644 --- a/nodeio/nodeio.c +++ b/nodeio/nodeio.c @@ -1,10 +1,49 @@ #include +#include + #include "libp2p/net/stream.h" +#include "libp2p/conn/session.h" -int libp2p_nodeio_upgrade_stream(struct Stream* stream) { - return 0; +int libp2p_nodeio_upgrade_stream(struct SessionContext* context) { + int retVal = 0; + char* protocol = "/nodeio/1.0.0\n"; + unsigned char* results = NULL; + size_t results_size = 0; + if (!context->default_stream->write(context, (unsigned char*)protocol, strlen(protocol))) + goto exit; + if (!context->default_stream->read(context, &results, &results_size)) + goto exit; + if (results_size != strlen(protocol)) + goto exit; + if (strncmp((char*)results, protocol, results_size) != 0) + goto exit; + retVal = 1; + exit: + if (results != NULL) { + free(results); + results = NULL; + } + return retVal; } -struct Node* libp2p_nodeio_get(struct Stream* stream, unsigned char* hash, int hash_length) { - return NULL; +/** + * Called by requestor to get a protobuf'd node from a hash + * @param context the session context + * @param hash the hash + * @param hash_size the length of the hash + * @param results where to put the buffer + * @param results_size the size of the results + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_nodeio_get(struct SessionContext* context, unsigned char* hash, int hash_length, unsigned char** results, size_t* results_size) { + if (!context->default_stream->write(context, hash, hash_length)) + return 0; + if (!context->default_stream->read(context, results, results_size)) + return 0; + return 1; +} + +int libp2p_nodeio_handshake(struct SessionContext* context) { + char* protocol = "/nodeio/1.0.0\n"; + return context->default_stream->write(context, (unsigned char*)protocol, strlen(protocol)); } diff --git a/peer/Makefile b/peer/Makefile index 6856cd8..0d989e9 100644 --- a/peer/Makefile +++ b/peer/Makefile @@ -2,7 +2,7 @@ CC = gcc CFLAGS = -O0 -I../include -I../../c-protobuf -I../../c-multihash/include -I../../c-multiaddr/include -g3 LFLAGS = DEPS = -OBJS = peer.o peerstore.o +OBJS = peer.o peerstore.o providerstore.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/peer/providerstore.c b/peer/providerstore.c new file mode 100644 index 0000000..c3a218f --- /dev/null +++ b/peer/providerstore.c @@ -0,0 +1,68 @@ +#include +#include + +#include "libp2p/utils/vector.h" + +struct ProviderEntry { + unsigned char* hash; + int hash_size; + unsigned char* peer_id; + int peer_id_size; +}; + +struct ProviderStore { + struct Libp2pVector* provider_entries; +}; + +/*** + * Stores hashes, and peers where you can possibly get them + */ + +/** + * Create a new ProviderStore + * @returns a ProviderStore struct + */ +struct ProviderStore* libp2p_providerstore_new() { + struct ProviderStore* out = (struct ProviderStore*)malloc(sizeof(struct ProviderStore)); + if (out != NULL) { + out->provider_entries = libp2p_utils_vector_new(4); + } + return out; +} + +/*** + * Clean resources used by a ProviderStore + * @param in the ProviderStore to clean up + */ +void libp2p_providerstore_free(struct ProviderStore* in) { + if (in != NULL) { + libp2p_utils_vector_free(in->provider_entries); + free(in); + in = NULL; + } +} + +void libp2p_providerstore_add(struct ProviderStore* store, unsigned char* hash, int hash_size, unsigned char* peer_id, int peer_id_size) { + struct ProviderEntry* entry = (struct ProviderEntry*)malloc(sizeof(struct ProviderEntry)); + entry->hash = malloc(hash_size); + memcpy(entry->hash, hash, hash_size); + entry->hash_size = hash_size; + entry->peer_id = malloc(peer_id_size); + memcpy(entry->peer_id, peer_id, peer_id_size); + entry->peer_id_size = peer_id_size; + libp2p_utils_vector_add(store->provider_entries, entry); +} + +int libp2p_providerstore_get(struct ProviderStore* store, unsigned char* hash, int hash_size, unsigned char** peer_id, int *peer_id_size) { + struct ProviderEntry* current = NULL; + for (int i = 0; i < store->provider_entries->total; i++) { + current = (struct ProviderEntry*)libp2p_utils_vector_get(store->provider_entries, i); + if (current->hash_size == hash_size && memcmp(current->hash, hash, hash_size) == 0) { + *peer_id = malloc(current->peer_id_size); + memcpy(*peer_id, current->peer_id, current->peer_id_size); + *peer_id_size = current->peer_id_size; + return 1; + } + } + return 0; +} diff --git a/utils/vector.c b/utils/vector.c index 2087070..e4e1d66 100644 --- a/utils/vector.c +++ b/utils/vector.c @@ -1,78 +1,74 @@ +#include #include -#include #include "libp2p/utils/vector.h" -/** - * Allocate memory for a new Libp2pVector - * @returns a new Libp2pVector or NULL if it couldn't do it - */ -struct Libp2pVector* libp2p_utils_vector_new() { - struct Libp2pVector* out = (struct Libp2pVector*)malloc(sizeof(struct Libp2pVector)); - if (out != NULL) { - out->buffer = NULL; - out->buffer_size = 0; - } - return out; +struct Libp2pVector* libp2p_utils_vector_new(int initial_size) +{ + struct Libp2pVector* v = (struct Libp2pVector*)malloc(sizeof(struct Libp2pVector)); + v->capacity = initial_size; + v->total = 0; + v->items = malloc(sizeof(void *) * v->capacity); + return v; } -void libp2p_utils_vector_free(struct Libp2pVector* vector) { - if (vector != NULL) { - if (vector->buffer != NULL) - free(vector->buffer); - vector->buffer_size = 0; - free(vector); - vector = NULL; - } +int libp2p_utils_vector_total(struct Libp2pVector *v) +{ + return v->total; } -/** - * Add bytes to vector - */ -int libp2p_utils_vector_add(struct Libp2pVector* vector, unsigned char* in_bytes, size_t in_size) { - if (in_size > 0) { - if (vector->buffer == NULL) { - vector->buffer = (unsigned char*)malloc(in_size); - if (vector->buffer == NULL) - return 0; - memcpy(vector->buffer, in_bytes, in_size); - } else { - vector->buffer = (unsigned char*)realloc(vector->buffer, in_size + vector->buffer_size); - if (vector->buffer == NULL) - return 0; - memcpy(&vector->buffer[vector->buffer_size], in_bytes, in_size); - vector->buffer_size += in_size; - } - } - return 1; +static void libp2p_utils_vector_resize(struct Libp2pVector *v, int capacity) +{ + #ifdef DEBUG_ON + printf("vector_resize: %d to %d\n", v->capacity, capacity); + #endif + + void **items = realloc(v->items, sizeof(void *) * capacity); + if (items) { + v->items = items; + v->capacity = capacity; + } } -int libp2p_utils_vector_serialize(struct Libp2pVector* vector, unsigned char** out, size_t* out_size) { - // the first 4 bytes are the size, followed by the the byte array - *out_size = vector->buffer_size + 4; - *out = (unsigned char*)malloc(*out_size); - if (*out == NULL) - return 0; - unsigned char* ptr = *out; - ptr[0] = (vector->buffer_size >> 24) & 0xFF; - ptr[1] = (vector->buffer_size >> 16) & 0xFF; - ptr[2] = (vector->buffer_size >> 8) & 0xFF; - ptr[3] = vector->buffer_size & 0xFF; - memcpy(&ptr[4], vector->buffer, vector->buffer_size); - return 1; +void libp2p_utils_vector_add(struct Libp2pVector *v, void *item) +{ + if (v->capacity == v->total) + libp2p_utils_vector_resize(v, v->capacity * 2); + v->items[v->total++] = item; } -int libp2p_utils_vector_unserialize(unsigned char* in, struct Libp2pVector** out) { - *out = (struct Libp2pVector*)malloc(sizeof(struct Libp2pVector)); - if (*out == NULL) - return 0; - struct Libp2pVector* ptr = *out; - ptr->buffer_size = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24); - ptr->buffer = (unsigned char*)malloc(ptr->buffer_size); - if (ptr->buffer == NULL) { - free (*out); - return 0; - } - memcpy(ptr->buffer, &in[4], ptr->buffer_size); - return 1; +void libp2p_utils_vector_set(struct Libp2pVector *v, int index, void *item) +{ + if (index >= 0 && index < v->total) + v->items[index] = item; +} + +void *libp2p_utils_vector_get(struct Libp2pVector *v, int index) +{ + if (index >= 0 && index < v->total) + return v->items[index]; + return NULL; +} + +void libp2p_utils_vector_delete(struct Libp2pVector *v, int index) +{ + if (index < 0 || index >= v->total) + return; + + v->items[index] = NULL; + + for (int i = 0; i < v->total - 1; i++) { + v->items[i] = v->items[i + 1]; + v->items[i + 1] = NULL; + } + + v->total--; + + if (v->total > 0 && v->total == v->capacity / 4) + libp2p_utils_vector_resize(v, v->capacity / 2); +} + +void libp2p_utils_vector_free(struct Libp2pVector *v) +{ + free(v->items); }