diff --git a/Makefile b/Makefile index 79a487e..930a0a0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ DEBUG = true export DEBUG -OBJS = crypto/*.o crypto/encoding/*.o thirdparty/mbedtls/*.o hashmap/hashmap.o record/*.o +OBJS = crypto/*.o crypto/encoding/*.o thirdparty/mbedtls/*.o hashmap/hashmap.o record/*.o routing/*.o compile: @@ -10,6 +10,7 @@ compile: cd thirdparty; make all; cd hashmap; make all; cd record; make all; + cd routing; make all; ar rcs libp2p.a $(OBJS) test: compile @@ -25,5 +26,6 @@ clean: cd thirdparty; make clean cd test; make clean; cd record; make clean; + cd routing; make clean; rm -rf libp2p.a diff --git a/routing/Makefile b/routing/Makefile new file mode 100644 index 0000000..7804bc4 --- /dev/null +++ b/routing/Makefile @@ -0,0 +1,21 @@ +DHT_DIR = dht +CC = gcc +CFLAGS = -O0 -I../include -I$(DHT_DIR) -g3 +LFLAGS = +DEPS = $(DHT_DIR)/dht.h +OBJS = kademlia.o dht.o + +%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +all: $(OBJS) + +$(DHT_DIR)/dht.h: + git clone https://github.com/jech/dht.git $(DHT_DIR) + +dht.c: $(DEPS) + ln -s $(DHT_DIR)/dht.c . + +clean: + rm -f $(OBJS) dht.c + rm -rf $(DHT_DIR) diff --git a/routing/kademlia.c b/routing/kademlia.c new file mode 100644 index 0000000..e5b96cd --- /dev/null +++ b/routing/kademlia.c @@ -0,0 +1,110 @@ +/* For crypt */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BOOTSTRAP_NODES 20 +static struct sockaddr_storage bootstrap_nodes[MAX_BOOTSTRAP_NODES]; +static int num_bootstrap_nodes = 0; + +/* The call-back function is called by the DHT whenever something + interesting happens. Right now, it only happens when we get a new value or + when a search completes, but this may be extended in future versions. */ +static void +callback(void *closure, + int event, + const unsigned char *info_hash, + const void *data, size_t data_len) +{ + switch (event) { + case DHT_EVENT_VALUES: + case DHT_EVENT_VALUES6: + printf("Received %d values.\n", (int)(data_len / 6)); + break; + case DHT_EVENT_SEARCH_DONE: + case DHT_EVENT_SEARCH_DONE6: + printf("Search done.\n"); + break; + default: + break; + } +} + +/* Functions called by the DHT. */ + +int dht_blacklisted (const struct sockaddr *sa, int salen) +{ + return 0; +} + +/* We need to provide a reasonably strong cryptographic hashing function. + SHA-1 code adapted from https://github.com/mwarning/KadNode */ +void dht_hash (void *hash_return, int hash_size, + const void *v1, int len1, + const void *v2, int len2, + const void *v3, int len3) +{ + SHA1_CTX ctx; + uint8_t digest[SHA1_DIGEST_SIZE]; + + SHA1_Init (&ctx); + if (v1) SHA1_Update (&ctx, v1, len1); + if (v2) SHA1_Update (&ctx, v2, len2); + if (v3) SHA1_Update (&ctx, v3, len3); + SHA1_Final (&ctx, digest); + + if (hash_size > SHA1_DIGEST_SIZE) { + memset ((char*)hash_return + SHA1_DIGEST_SIZE, 0, hash_size - SHA1_DIGEST_SIZE); + hash_size = SHA1_DIGEST_SIZE; + } + memcpy(hash_return, digest, hash_size); +} + +int dht_random_bytes (void *buf, size_t size) +{ + int fd, rc, save; + size_t len = 0; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + return fd; + } + + while (len < size) { + rc = read (fd, buf + len, size - len); + if (rc < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; // not fatal, try again. + } + if (errno == EWOULDBLOCK && len > 0) { + rc = len; + } + + break; // fail. + } + len += rc; + } + + if (len > 0 && rc >= 0) { + rc = len; + } + + save = errno; + close(fd); + errno = save; + + return rc; +}