]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9775: Initial commit of the first portion of the DHT rewrite for peer review
authorShane Bryldt <astaelan@gmail.com>
Wed, 30 Nov 2016 03:47:40 +0000 (03:47 +0000)
committerMike Jerris <mike@jerris.com>
Wed, 25 Jan 2017 20:59:33 +0000 (14:59 -0600)
Code compiles, but not yet functional, unit tests to come soon for current code

libs/libks/Makefile.am
libs/libks/src/dht/ks_dht-int.h [new file with mode: 0644]
libs/libks/src/dht/ks_dht.c [new file with mode: 0644]
libs/libks/src/dht/ks_dht.h [new file with mode: 0644]
libs/libks/src/dht/ks_dht_endpoint-int.h [new file with mode: 0644]
libs/libks/src/dht/ks_dht_endpoint.c [new file with mode: 0644]
libs/libks/src/dht/ks_dht_endpoint.h [new file with mode: 0644]
libs/libks/src/dht/ks_dht_nodeid.c [new file with mode: 0644]
libs/libks/src/dht/ks_dht_nodeid.h [new file with mode: 0644]

index 897236bd1cc3af3b9bfc4cdb0be80092b7e85aaf..353b44438676d9b328bd0f82d62aeee296f72b1a 100644 (file)
@@ -13,6 +13,7 @@ libks_la_SOURCES += src/ks_time.c src/ks_printf.c src/ks_hash.c src/ks_q.c src/k
 libks_la_SOURCES += src/ks_ssl.c src/kws.c src/ks_rng.c
 libks_la_SOURCES += src/utp/utp_api.cpp src/utp/utp_callbacks.cpp src/utp/utp_hash.cpp src/utp/utp_internal.cpp
 libks_la_SOURCES += src/utp/utp_packedsockaddr.cpp src/utp/utp_utils.cpp src/ks_bencode.c
+libks_la_SOURCES += src/dht/ks_dht.c src/dht/ks_dht_endpoint.c src/dht/ks_dht_nodeid.c
 libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c 
 #aes.h aescpp.h brg_endian.h aesopt.h aestab.h brg_types.h sha2.h twofish.h
 
@@ -28,6 +29,7 @@ library_include_HEADERS += src/include/ks_dso.h src/include/ks_dht.h src/include
 library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
 library_include_HEADERS += src/utp/utp_internal.h src/utp/utp.h src/utp/utp_types.h src/utp/utp_callbacks.h src/utp/utp_templates.h
 library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h
+library_include_HEADERS += src/dht/ks_dht.h src/dht/ks_dht-int.h src/dht/ks_dht_endpoint.h src/dht/ks_dht_endpoint-int.h src/dht/ks_dht_nodeid.h
 
 tests: libks.la
        $(MAKE) -C test tests
diff --git a/libs/libks/src/dht/ks_dht-int.h b/libs/libks/src/dht/ks_dht-int.h
new file mode 100644 (file)
index 0000000..f878faa
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef KS_DHT_INT_H
+#define KS_DHT_INT_H
+
+#include "ks.h"
+
+KS_BEGIN_EXTERN_C
+
+
+KS_DECLARE(ks_status_t) ks_dht2_idle(ks_dht2_t *dht);
+KS_DECLARE(ks_status_t) ks_dht2_process(ks_dht2_t *dht, ks_sockaddr_t *raddr);
+
+KS_END_EXTERN_C
+
+#endif /* KS_DHT_INT_H */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/libs/libks/src/dht/ks_dht.c b/libs/libks/src/dht/ks_dht.c
new file mode 100644 (file)
index 0000000..7a25d78
--- /dev/null
@@ -0,0 +1,220 @@
+#include "ks_dht.h"
+#include "ks_dht-int.h"
+#include "ks_dht_endpoint-int.h"
+#include "sodium.h"
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_alloc(ks_dht2_t **dht, ks_pool_t *pool)
+{
+       ks_bool_t pool_alloc = !pool;
+       ks_dht2_t *d;
+
+       ks_assert(dht);
+       
+       if (pool_alloc) ks_pool_open(&pool);
+       *dht = d = ks_pool_alloc(pool, sizeof(ks_dht2_t));
+
+       d->pool = pool;
+       d->pool_alloc = pool_alloc;
+
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_free(ks_dht2_t *dht)
+{
+       ks_pool_t *pool = dht->pool;
+       ks_bool_t pool_alloc = dht->pool_alloc;
+
+       ks_pool_free(pool, dht);
+       if (pool_alloc) {
+               ks_pool_close(&pool);
+       }
+
+       return KS_STATUS_SUCCESS;
+}
+                                                                                               
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_init(ks_dht2_t *dht, const uint8_t *nodeid)
+{
+       ks_assert(dht);
+
+       if (ks_dht2_nodeid_init(&dht->nodeid, nodeid) != KS_STATUS_SUCCESS) {
+               return KS_STATUS_FAIL;
+       }
+       
+    dht->bind_ipv4 = KS_FALSE;
+       dht->bind_ipv6 = KS_FALSE;
+       
+       dht->endpoints = NULL;
+       dht->endpoints_size = 0;
+       ks_hash_create(&dht->endpoints_hash, KS_HASH_MODE_DEFAULT, KS_HASH_FLAG_RWLOCK, dht->pool);
+       dht->endpoints_poll = NULL;
+       
+       dht->recv_buffer_length = 0;
+       
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_deinit(ks_dht2_t *dht)
+{
+       ks_assert(dht);
+
+       dht->recv_buffer_length = 0;
+       // @todo dht->endpoints_poll deinit
+       // @todo dht->endpoints deinit
+       ks_hash_destroy(&dht->endpoints_hash);
+       dht->bind_ipv4 = KS_FALSE;
+       dht->bind_ipv6 = KS_FALSE;
+       ks_dht2_nodeid_deinit(&dht->nodeid);
+       
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_bind(ks_dht2_t *dht, const ks_sockaddr_t *addr)
+{
+       ks_dht2_endpoint_t *ep;
+       ks_socket_t sock;
+       int32_t epindex;
+       
+       ks_assert(dht);
+       ks_assert(addr);
+       ks_assert(addr->family == AF_INET || addr->family == AF_INET6);
+       ks_assert(addr->port);
+       
+       //if (!addr->port) {
+       //      addr->port = KS_DHT_DEFAULT_PORT;
+       //}
+
+       dht->bind_ipv4 |= addr->family == AF_INET;
+       dht->bind_ipv6 |= addr->family == AF_INET6;
+
+       // @todo start of ks_dht2_endpoint_bind
+       if ((sock = socket(addr->family, SOCK_DGRAM, IPPROTO_UDP)) == KS_SOCK_INVALID) {
+               return KS_STATUS_FAIL;
+       }
+
+       // @todo shouldn't ks_addr_bind take a const addr *?
+       if (ks_addr_bind(sock, (ks_sockaddr_t *)addr) != KS_STATUS_SUCCESS) {
+               ks_socket_close(&sock);
+               return KS_STATUS_FAIL;
+       }
+       
+       if (ks_dht2_endpoint_alloc(&ep, dht->pool) != KS_STATUS_SUCCESS) {
+               ks_socket_close(&sock);
+               return KS_STATUS_FAIL;
+       }
+       
+       if (ks_dht2_endpoint_init(ep, addr, sock) != KS_STATUS_SUCCESS) {
+               ks_dht2_endpoint_free(ep);
+               ks_socket_close(&sock);
+               return KS_STATUS_FAIL;
+       }
+
+       ks_socket_option(ep->sock, SO_REUSEADDR, KS_TRUE);
+       ks_socket_option(ep->sock, KS_SO_NONBLOCK, KS_TRUE);
+
+       // @todo end of ks_dht2_endpoint_bind
+       
+       epindex = dht->endpoints_size++;
+       dht->endpoints = (ks_dht2_endpoint_t **)ks_pool_resize(dht->pool,
+                                                                                                                  (void *)dht->endpoints,
+                                                                                                                  sizeof(ks_dht2_endpoint_t *) * dht->endpoints_size);
+       dht->endpoints[epindex] = ep;
+       ks_hash_insert(dht->endpoints_hash, ep->addr.host, ep);
+       
+       dht->endpoints_poll = (struct pollfd *)ks_pool_resize(dht->pool,
+                                                                                                                 (void *)dht->endpoints_poll,
+                                                                                                                 sizeof(struct pollfd) * dht->endpoints_size);
+       dht->endpoints_poll[epindex].fd = ep->sock;
+       dht->endpoints_poll[epindex].events = POLLIN | POLLERR;
+       
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_pulse(ks_dht2_t *dht, int32_t timeout)
+{
+       int32_t result;
+               
+       ks_assert(dht);
+       ks_assert (timeout >= 0);
+
+       // @todo why was old DHT code checking for poll descriptor resizing here?
+
+       if (timeout == 0) {
+               // @todo deal with default timeout, should return quickly but not hog the CPU polling
+       }
+       
+       result = ks_poll(dht->endpoints_poll, dht->endpoints_size, timeout);
+       if (result < 0) {
+               return KS_STATUS_FAIL;
+       }
+
+       if (result == 0) {
+               ks_dht2_idle(dht);
+               return KS_STATUS_TIMEOUT;
+       }
+
+       for (int32_t i = 0; i < dht->endpoints_size; ++i) {
+               if (dht->endpoints_poll[i].revents & POLLIN) {
+                       ks_sockaddr_t raddr = KS_SA_INIT;
+                       dht->recv_buffer_length = KS_DHT_RECV_BUFFER_SIZE;
+                       
+                       raddr.family = dht->endpoints[i]->addr.family;
+                       if (ks_socket_recvfrom(dht->endpoints_poll[i].fd, dht->recv_buffer, &dht->recv_buffer_length, &raddr) == KS_STATUS_SUCCESS) {
+                               ks_dht2_process(dht, &raddr);
+                       }
+               }
+       }
+
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_idle(ks_dht2_t *dht)
+{
+       ks_assert(dht);
+
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_process(ks_dht2_t *dht, ks_sockaddr_t *raddr)
+{
+       ks_assert(dht);
+       ks_assert(raddr);
+
+       return KS_STATUS_SUCCESS;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/libs/libks/src/dht/ks_dht.h b/libs/libks/src/dht/ks_dht.h
new file mode 100644 (file)
index 0000000..63c2852
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef KS_DHT_H
+#define KS_DHT_H
+
+#include "ks.h"
+#include "ks_bencode.h"
+
+#include "ks_dht_endpoint.h"
+#include "ks_dht_nodeid.h"
+
+KS_BEGIN_EXTERN_C
+
+
+#define KS_DHT_DEFAULT_PORT 5309
+#define KS_DHT_RECV_BUFFER_SIZE 0xFFFF
+
+
+typedef struct ks_dht2_s ks_dht2_t;
+struct ks_dht2_s {
+       ks_pool_t *pool;
+       ks_bool_t pool_alloc;
+
+       ks_dht2_nodeid_t nodeid;
+
+       ks_bool_t bind_ipv4;
+       ks_bool_t bind_ipv6;
+
+       ks_dht2_endpoint_t **endpoints;
+       int32_t endpoints_size;
+       ks_hash_t *endpoints_hash;
+       struct pollfd *endpoints_poll;
+
+       uint8_t recv_buffer[KS_DHT_RECV_BUFFER_SIZE];
+       ks_size_t recv_buffer_length;
+};
+
+
+KS_DECLARE(ks_status_t) ks_dht2_alloc(ks_dht2_t **dht, ks_pool_t *pool);
+KS_DECLARE(ks_status_t) ks_dht2_free(ks_dht2_t *dht);
+
+                                               
+KS_DECLARE(ks_status_t) ks_dht2_init(ks_dht2_t *dht, const uint8_t *nodeid);
+KS_DECLARE(ks_status_t) ks_dht2_deinit(ks_dht2_t *dht);
+
+
+KS_DECLARE(ks_status_t) ks_dht2_bind(ks_dht2_t *dht, const ks_sockaddr_t *addr);
+KS_DECLARE(ks_status_t) ks_dht2_pulse(ks_dht2_t *dht, int32_t timeout);
+
+KS_END_EXTERN_C
+
+#endif /* KS_DHT_H */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/libs/libks/src/dht/ks_dht_endpoint-int.h b/libs/libks/src/dht/ks_dht_endpoint-int.h
new file mode 100644 (file)
index 0000000..c8361ac
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef KS_DHT_ENDPOINT_INT_H
+#define KS_DHT_ENDPOINT_INT_H
+
+#include "ks.h"
+
+KS_BEGIN_EXTERN_C
+
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_alloc(ks_dht2_endpoint_t **endpoint, ks_pool_t *pool);
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_free(ks_dht2_endpoint_t *endpoint);
+
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_init(ks_dht2_endpoint_t *endpoint, const ks_sockaddr_t *addr, ks_socket_t sock);
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_deinit(ks_dht2_endpoint_t *endpoint);
+                                               
+KS_END_EXTERN_C
+
+#endif /* KS_DHT_ENDPOINT_H */
+
+
+/* For Emacs:
+* Local Variables:
+* mode:c
+* indent-tabs-mode:t
+* tab-width:4
+* c-basic-offset:4
+* End:
+* For VIM:
+* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+*/
diff --git a/libs/libks/src/dht/ks_dht_endpoint.c b/libs/libks/src/dht/ks_dht_endpoint.c
new file mode 100644 (file)
index 0000000..2818a7c
--- /dev/null
@@ -0,0 +1,68 @@
+#include "ks_dht_endpoint.h"
+#include "ks_dht_endpoint-int.h"
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_alloc(ks_dht2_endpoint_t **endpoint, ks_pool_t *pool)
+{
+       ks_dht2_endpoint_t *ep;
+
+       ks_assert(endpoint);
+       ks_assert(pool);
+       
+       *endpoint = ep = ks_pool_alloc(pool, sizeof(ks_dht2_endpoint_t));
+       ep->pool = pool;
+
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_free(ks_dht2_endpoint_t *endpoint)
+{
+       ks_assert(endpoint);
+       
+       ks_pool_free(endpoint->pool, endpoint);
+
+       return KS_STATUS_SUCCESS;
+}
+                                                                                               
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_init(ks_dht2_endpoint_t *endpoint, const ks_sockaddr_t *addr, ks_socket_t sock)
+{
+       ks_assert(endpoint);
+       ks_assert(addr);
+       ks_assert(addr->family == AF_INET || addr->family == AF_INET6);
+
+       endpoint->addr = *addr;
+       endpoint->sock = sock;
+       
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_endpoint_deinit(ks_dht2_endpoint_t *endpoint)
+{
+       ks_assert(endpoint);
+
+       return KS_STATUS_SUCCESS;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/libs/libks/src/dht/ks_dht_endpoint.h b/libs/libks/src/dht/ks_dht_endpoint.h
new file mode 100644 (file)
index 0000000..6d9df05
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef KS_DHT_ENDPOINT_H
+#define KS_DHT_ENDPOINT_H
+
+#include "ks.h"
+
+KS_BEGIN_EXTERN_C
+
+typedef struct ks_dht2_endpoint_s ks_dht2_endpoint_t;
+struct ks_dht2_endpoint_s {
+       ks_pool_t *pool;
+       ks_sockaddr_t addr;
+       ks_socket_t sock;
+};
+
+KS_END_EXTERN_C
+
+#endif /* KS_DHT_ENDPOINT_H */
+
+
+/* For Emacs:
+* Local Variables:
+* mode:c
+* indent-tabs-mode:t
+* tab-width:4
+* c-basic-offset:4
+* End:
+* For VIM:
+* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+*/
diff --git a/libs/libks/src/dht/ks_dht_nodeid.c b/libs/libks/src/dht/ks_dht_nodeid.c
new file mode 100644 (file)
index 0000000..752f9ac
--- /dev/null
@@ -0,0 +1,70 @@
+#include "ks_dht_nodeid.h"
+#include "sodium.h"
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_alloc(ks_dht2_nodeid_t **nodeid, ks_pool_t *pool)
+{
+       ks_dht2_nodeid_t *nid;
+
+       ks_assert(nodeid);
+       ks_assert(pool);
+       
+       *nodeid = nid = ks_pool_alloc(pool, sizeof(ks_dht2_nodeid_t));
+       nid->pool = pool;
+
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_free(ks_dht2_nodeid_t *nodeid)
+{
+       ks_assert(nodeid);
+       
+       ks_pool_free(nodeid->pool, nodeid);
+
+       return KS_STATUS_SUCCESS;
+}
+                                                                                               
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_init(ks_dht2_nodeid_t *nodeid, const uint8_t *id)
+{
+       ks_assert(nodeid);
+       ks_assert(id);
+
+       if (!id) {
+               randombytes_buf(nodeid->id, KS_DHT_NODEID_LENGTH);
+       } else {
+               memcpy(nodeid->id, id, KS_DHT_NODEID_LENGTH);
+       }
+       
+       return KS_STATUS_SUCCESS;
+}
+
+/**
+ *
+ */
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_deinit(ks_dht2_nodeid_t *nodeid)
+{
+       ks_assert(nodeid);
+
+       return KS_STATUS_SUCCESS;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/libs/libks/src/dht/ks_dht_nodeid.h b/libs/libks/src/dht/ks_dht_nodeid.h
new file mode 100644 (file)
index 0000000..5eef173
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef KS_DHT_NODEID_H
+#define KS_DHT_NODEID_H
+
+#include "ks.h"
+
+KS_BEGIN_EXTERN_C
+
+#define KS_DHT_NODEID_LENGTH 20
+
+typedef struct ks_dht2_nodeid_s ks_dht2_nodeid_t;
+struct ks_dht2_nodeid_s {
+       ks_pool_t *pool;
+    uint8_t id[KS_DHT_NODEID_LENGTH];
+};
+
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_alloc(ks_dht2_nodeid_t **nodeid, ks_pool_t *pool);
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_free(ks_dht2_nodeid_t *nodeid);
+
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_init(ks_dht2_nodeid_t *nodeid, const uint8_t *id);
+KS_DECLARE(ks_status_t) ks_dht2_nodeid_deinit(ks_dht2_nodeid_t *nodeid);
+
+KS_END_EXTERN_C
+
+#endif /* KS_DHT_NODEID_H */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
+