commit 0f07ba665e3bb84594cbaaac03393a72d26219e8
Author: Christoph Lohmann <20h@r-36.net>
Date: Tue, 8 Mar 2011 02:25:40 +0100
Initial commit of libdht.
Diffstat:
LICENSE | | | 21 | +++++++++++++++++++++ |
Makefile | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
README.md | | | 49 | +++++++++++++++++++++++++++++++++++++++++++++++++ |
config.mk | | | 23 | +++++++++++++++++++++++ |
dht.c | | | 260 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dht.h | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dhtlist.c | | | 166 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dhttest.c | | | 113 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
ind.c | | | 99 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
ind.h | | | 22 | ++++++++++++++++++++++ |
10 files changed, 940 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT/X Consortium License
+
+© 2011 Christoph Lohmann <20h@r-36.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,69 @@
+# libdht - simple dht library
+# See LICENSE file for copyright and license details.
+
+include config.mk
+
+SRC = dht.c ind.c dhtlist.c
+OBJ = ${SRC:.c=.o}
+SOUT = ${NAME}.a
+DOUT = ${NAME}.so
+
+all: options ${SOUT} ${DOUT}
+
+options:
+ @echo ${NAME} build options:
+ @echo "CFLAGS = ${CFLAGS}"
+ @echo "LDFLAGS = ${LDFLAGS}"
+ @echo "CC = ${CC}"
+
+.c.o:
+ @echo CC $<
+ @${CC} -c ${CFLAGS} $<
+
+${OBJ}: config.mk
+
+${SOUT}: ${OBJ}
+ @ar rcs ${SOUT} ${OBJ}
+
+${DOUT}: ${OBJ}
+ @${CC} -shared ${OBJ} -o ${DOUT}
+
+dhttest: ${OBJ} dhttest.o
+ @echo CC -o $@
+ @${CC} -o $@ ${OBJ} dhttest.o ${LDFLAGS}
+
+test: dhttest
+ @echo running dhttest
+ ./dhttest
+
+clean:
+ @echo cleaning
+ @rm -f *.so *.a ${NAME} ${OBJ} dhttest dhttest.o ${NAME}-${VERSION}.tar.gz
+
+dist: clean
+ @echo creating dist tarball
+ @mkdir -p ${NAME}-${VERSION}
+ @cp -R LICENSE Makefile README.md config.mk \
+ ${SRC} *.h ${NAME}-${VERSION}
+ @tar -cf ${NAME}-${VERSION}.tar ${NAME}-${VERSION}
+ @gzip ${NAME}-${VERSION}.tar
+ @rm -rf ${NAME}-${VERSION}
+
+install: all
+ @echo installing libraries to ${DESTDIR}${PREFIX}/lib
+ @mkdir -p ${DESTDIR}${PREFIX}/lib
+ @cp -f ${NAME}.a ${NAME}.so ${DESTDIR}${PREFIX}/lib
+ @chmod 755 ${DESTDIR}${PREFIX}/lib/${NAME}.*
+ @echo installing header file to ${DESTDIR}${PREFIX}/include
+ @mkdir -p ${DESTDIR}${PREFIX}/include
+ @cp -f dht.h ${DESTDIR}${PREFIX}/include
+ @chmod 644 ${DESTDIR}${PREFIX}/include/dht.h
+
+uninstall:
+ @echo removing libraries from ${DESTDIR}${PREFIX}/bin
+ @rm -f ${DESTDIR}${PREFIX}/lib/${NAME}.*
+ @echo removing header file from ${DESTDIR}${PREFIX}/include
+ @rm -f ${DESTDIR}${PREFIX}/include/dht.h
+
+.PHONY: all options clean dist install uninstall test
+# DO NOT DELETE
diff --git a/README.md b/README.md
@@ -0,0 +1,49 @@
+# libdht - a kadmelia helper function library
+
+The algorithm was taken from [here](https://gist.github.com/240988).
+
+## Installation
+
+ make
+ make install
+
+## How to use it
+
+ #include <dht.h>
+
+ dht_t *dht;
+ dhtnode_t *node;
+ char id[IDLENGTH];
+ llist_t *llist;
+
+ dht = dht_new("localhost");
+
+ /*
+ * Set some node, which appeared on the network.
+ */
+ node = dhtnode_new();
+ dhtnode_setid(node);
+ dhtnode_setaddr("127.0.0.1:7689");
+ dht_update(dht, node);
+ dhtnode_free(node);
+
+ /*
+ * Get at maximum five nodes next to the target node
+ */
+ dhtnode_setid(node);
+ dhtnode_setaddr("8.8.8.8:6669");
+ llist = dht_getclosest(dht, node, 5);
+ forllist(llist, elem)
+ dosomething(((dhtnode_t *)elem->data)->addr);
+ dhtnode_free(node);
+
+ /*
+ * Cleanup.
+ */
+ dht_free(dht);
+
+## Thread safety
+
+This library is not thread safe. The critical part is the list hand-
+ling.
+
diff --git a/config.mk b/config.mk
@@ -0,0 +1,23 @@
+# libdht metadata
+NAME = libdht
+VERSION = 0.2
+
+# Customize below to fit your system
+
+# paths
+PREFIX = /usr
+MANPREFIX = ${PREFIX}/share/man
+
+# includes and libs
+INCS = -I. -I/usr/include
+LIBS = -L/usr/lib -lc
+
+# flags
+CPPFLAGS = -DVERSION=\"${VERSION}\"
+CFLAGS = -g -fPIC -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
+LDFLAGS = -g ${LIBS}
+#LDFLAGS = -s ${LIBS}
+
+# compiler and linker
+CC = cc
+
diff --git a/dht.c b/dht.c
@@ -0,0 +1,260 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+
+#include "dht.h"
+#include "ind.h"
+
+dhtnode_t *
+dhtnode_mkid(dhtnode_t *node)
+{
+ srand((unsigned int)time(NULL)*rand());
+
+ for (int i = 0; i < sizeof(node->id); i++)
+ node->id[i] = rand() & 0xFF;
+
+ return node;
+}
+
+dhtnode_t *
+dhtnode_setid(dhtnode_t *node, char id[IDLENGTH])
+{
+ memmove(node->id, id, sizeof(node->id));
+
+ return node;
+}
+
+dhtnode_t *
+dhtnode_setaddr(dhtnode_t *node, char *addr)
+{
+ node->addr = memdup(addr, strlen(addr)+1);
+
+ return node;
+}
+
+dhtnode_t *
+dhtnode_new(void)
+{
+ dhtnode_t *node;
+
+ node = mallocz(sizeof(dhtnode_t), 2);
+
+ return node;
+}
+
+void
+dhtnode_free(dhtnode_t *node)
+{
+ free(node);
+}
+
+void
+dhtnode_print(dhtnode_t *node)
+{
+ printf("dhtnode[id=");
+ for (int i = 0; i < sizeof(node->id); i++)
+ printf("%.2x", node->id[i] & 0xFF);
+ printf(", addr='");
+ if (node->addr != NULL)
+ printf("%s", node->addr);
+ printf("']\n");
+}
+
+int
+dhtnode_cmp(dhtnode_t *node1, dhtnode_t *node2)
+{
+ return memcmp(node1->id, node2->id, sizeof(node1->id));
+}
+
+dhtnode_t *
+dhtnode_xor(dhtnode_t *node1, dhtnode_t *node2)
+{
+ dhtnode_t *ret;
+
+ ret = dhtnode_new();
+ for (int i = 0; i < sizeof(ret->id); i++)
+ ret->id[i] = node1->id[i] ^ node2->id[i];
+
+ return ret;
+}
+
+int
+dhtnode_prefixlen(dhtnode_t *node)
+{
+ for (int i = 0; i < sizeof(node->id); i++)
+ for (int j = 0; j < 8; j++)
+ if ((node->id[i] >> (7-j)) & 0x1)
+ return i * 8 + j;
+ return sizeof(node->id) * 8 - 1;
+}
+
+dhtrouting_t *
+dhtrouting_new(dhtnode_t *node)
+{
+ dhtrouting_t *route;
+
+ route = mallocz(sizeof(dhtrouting_t), 2);
+ for (int i = 0; i < nelem(route->buckets); i++)
+ route->buckets[i] = dhtlist_new();
+ route->node = node;
+
+ return route;
+}
+
+void
+dhtrouting_free(dhtrouting_t *route)
+{
+
+ for (int i = 0; i < nelem(route->buckets); i++)
+ dhtlist_free(route->buckets[i]);
+ dhtnode_free(route->node);
+ free(route);
+}
+
+dhtrouting_t *
+dhtrouting_update(dhtrouting_t *route, dhtnode_t *node)
+{
+ dhtlist_t *bucket;
+ dhtlistelem_t *elem;
+ dhtnode_t *xornode;
+ int bucketnum;
+
+ xornode = dhtnode_xor(route->node, node);
+ bucketnum = dhtnode_prefixlen(xornode);
+ dhtnode_free(xornode);
+ bucket = route->buckets[bucketnum];
+
+ forodhtlist(bucket, elem)
+ if (!dhtnode_cmp(elem->node, node))
+ break;
+ if (elem == NULL) {
+ if (bucket->len < IDLENGTH)
+ dhtlist_push(bucket, node);
+ else
+ return NULL;
+ } else
+ dhtlist_move(bucket, elem, 0);
+
+ return route;
+}
+
+dhtlist_t *
+dhtrouting_sortnodes(dhtlist_t *dhtlist, dhtnode_t *target)
+{
+ dhtnode_t *xornode1, *xornode2, *swap;
+ int sorted;
+
+ sorted = 0;
+
+ while(!sorted) {
+ sorted = 1;
+ fordhtlist(dhtlist, elem) {
+ if (elem->next == NULL)
+ break;
+ xornode1 = dhtnode_xor(elem->node, target);
+ xornode2 = dhtnode_xor(elem->next->node, target);
+
+ if (dhtnode_cmp(xornode1, xornode2) > 0) {
+ swap = elem->next->node;
+ elem->next->node = elem->node;
+ elem->node = swap;
+ sorted = 0;
+ }
+ dhtnode_free(xornode1);
+ dhtnode_free(xornode2);
+ }
+ }
+
+ return dhtlist;
+}
+
+dhtlist_t *
+dhtrouting_addnodes(dhtlist_t *dhtlist, dhtlist_t *bucket, dhtnode_t *target,
+ int max)
+{
+ fordhtlist(bucket, elem) {
+ if (dhtlist->len >= max)
+ break;
+ dhtlist_add(dhtlist, elem->node);
+ }
+
+ return dhtrouting_sortnodes(dhtlist, target);
+}
+
+dhtlist_t *
+dhtrouting_findclosest(dhtrouting_t *route, dhtnode_t *target, int max)
+{
+ int bucketnum;
+ dhtnode_t *xornode;
+ dhtlist_t *retnodes;
+
+ retnodes = dhtlist_new();
+
+ xornode = dhtnode_xor(route->node, target);
+ bucketnum = dhtnode_prefixlen(xornode);
+ dhtnode_free(xornode);
+
+ dhtrouting_addnodes(retnodes, route->buckets[bucketnum], target, max);
+ for (int i = 1; ((bucketnum-i) >= 0
+ || (bucketnum+i) < IDLENGTH * 8)
+ && retnodes->len < max; i++) {
+ if (bucketnum-i >= 0) {
+ dhtrouting_addnodes(retnodes,
+ route->buckets[bucketnum-i],
+ target, max);
+ }
+ if (bucketnum+i < IDLENGTH * 8) {
+ dhtrouting_addnodes(retnodes,
+ route->buckets[bucketnum+i],
+ target, max);
+ }
+ }
+
+ return retnodes;
+}
+
+dht_t *
+dht_new(char *localhost)
+{
+ dht_t *dht;
+ dhtnode_t *node;
+
+ node = dhtnode_new();
+ dhtnode_mkid(node);
+ dhtnode_setaddr(node, localhost);
+
+ dht = mallocz(sizeof(dht_t), 2);
+ dht->routing = dhtrouting_new(node);
+
+ return dht;
+}
+
+void
+dht_free(dht_t *dht)
+{
+ dhtrouting_free(dht->routing);
+ free(dht);
+}
+
+dhtlist_t *
+dht_find(dht_t *dht, dhtnode_t *target, int max)
+{
+ return dhtrouting_findclosest(dht->routing, target, max);
+}
+
+dht_t *
+dht_update(dht_t *dht, dhtnode_t *node)
+{
+ dhtrouting_update(dht->routing, node);
+
+ return dht;
+}
+
diff --git a/dht.h b/dht.h
@@ -0,0 +1,118 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef __DHT_H__
+#define __DHT_H__
+
+/*
+ * List functions. Most of them aren't needed, but provided.
+ */
+
+#define fordhtlist(list, elem) for (dhtlistelem_t *elem = (list)->first; elem;\
+ elem = elem->next)
+
+#define forodhtlist(list, elem) for (elem = (list)->first; elem;\
+ elem = elem->next)
+
+typedef struct dhtnode_t dhtnode_t;
+
+typedef struct dhtlistelem_t dhtlistelem_t;
+struct dhtlistelem_t {
+ dhtlistelem_t *next;
+ dhtlistelem_t *prev;
+
+ dhtnode_t *node;
+};
+
+typedef struct dhtlist_t dhtlist_t;
+struct dhtlist_t {
+ dhtlistelem_t *first;
+ dhtlistelem_t *last;
+ int len;
+};
+
+dhtlistelem_t *dhtlistelem_set(dhtlistelem_t *elem, dhtnode_t *node);
+dhtlistelem_t *dhtlistelem_new(dhtnode_t *node);
+void dhtlistelem_free(dhtlistelem_t *elem);
+
+dhtlist_t *dhtlist_new(void);
+void dhtlist_free(dhtlist_t *dhtlist);
+dhtlistelem_t *dhtlist_addelem(dhtlist_t *dhtlist, dhtlistelem_t *elem);
+dhtlistelem_t *dhtlist_add(dhtlist_t *dhtlist, dhtnode_t *node);
+dhtlistelem_t *dhtlist_push(dhtlist_t *dhtlist, dhtnode_t *node);
+void dhtlist_delelemlinks(dhtlist_t *dhtlist, dhtlistelem_t *elem);
+void dhtlist_delelem(dhtlist_t *dhtlist, dhtlistelem_t *elem);
+dhtlistelem_t *dhtlist_insert(dhtlist_t *dhtlist, dhtlistelem_t *elem, int idx);
+dhtlistelem_t *dhtlist_move(dhtlist_t *dhtlist, dhtlistelem_t *elem, int idx);
+void dhtlist_print(dhtlist_t *dhtlist);
+
+/*
+ * DHT functions.
+ */
+#define IDLENGTH 20
+
+struct dhtnode_t {
+ char id[IDLENGTH];
+ char *addr;
+};
+
+typedef struct dhtrouting_t dhtrouting_t;
+struct dhtrouting_t {
+ dhtnode_t *node;
+ dhtlist_t *buckets[IDLENGTH * 8];
+};
+
+typedef struct dht_t dht_t;
+struct dht_t {
+ dhtrouting_t *routing;
+};
+
+/*
+ * These functions are used for handling the dhtnodes, which is simply
+ * the ID of the specific host.
+ */
+dhtnode_t *dhtnode_mkid(dhtnode_t *node);
+dhtnode_t *dhtnode_setid(dhtnode_t *node, char id[IDLENGTH]);
+dhtnode_t *dhtnode_setaddr(dhtnode_t *node, char *addr);
+dhtnode_t *dhtnode_new(void);
+void dhtnode_free(dhtnode_t *node);
+
+/*
+ * These are internal functions for the dhtnode.
+ */
+void dhtnode_print(dhtnode_t *node);
+int dhtnode_cmp(dhtnode_t *node1, dhtnode_t *node2);
+dhtnode_t *dhtnode_xor(dhtnode_t *node1, dhtnode_t *node2);
+int dhtnode_prefixlen(dhtnode_t *node);
+
+/*
+ * These are internal routing functions.
+ */
+dhtrouting_t *dhtrouting_new(dhtnode_t *node);
+void dhtrouting_free(dhtrouting_t *route);
+dhtrouting_t *dhtrouting_update(dhtrouting_t *route, dhtnode_t *node);
+dhtlist_t *dhtrouting_findclosest(dhtrouting_t *route, dhtnode_t *target,
+ int max);
+
+/*
+ * These are the high-level functions for dht handling.
+ */
+
+dht_t *dht_new(char *network); /* network is a unique identifier */
+void dht_free(dht_t *dht);
+
+/*
+ * This function will get you a dhtlist with a maximum of max elements,
+ * which are the closest nodes to your position.
+ */
+dhtlist_t *dht_find(dht_t *dht, dhtnode_t *target, int max);
+
+/*
+ * When a new node appears, add it to your internal routing buckets.
+ */
+dht_t *dht_update(dht_t *dht, dhtnode_t *node);
+
+#endif
+
diff --git a/dhtlist.c b/dhtlist.c
@@ -0,0 +1,166 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include "ind.h"
+#include "dht.h"
+
+dhtlistelem_t *
+dhtlistelem_set(dhtlistelem_t *elem, dhtnode_t *node)
+{
+ elem->node = node;
+
+ return elem;
+}
+
+dhtlistelem_t *
+dhtlistelem_new(dhtnode_t *node)
+{
+ return dhtlistelem_set(mallocz(sizeof(dhtlistelem_t), 2), node);
+}
+
+void
+dhtlistelem_free(dhtlistelem_t *elem)
+{
+ free(elem);
+}
+
+dhtlist_t *
+dhtlist_new(void)
+{
+ return (dhtlist_t *)mallocz(sizeof(dhtlist_t), 2);
+}
+
+void
+dhtlist_free(dhtlist_t *node)
+{
+ dhtlistelem_t *elem;
+
+ if (node->first != NULL) {
+ for (elem = node->first;;) {
+ if (elem->next != NULL) {
+ elem = elem->next;
+ free(elem->prev);
+ } else {
+ free(elem);
+ break;
+ }
+ }
+ }
+ free(node);
+}
+
+dhtlistelem_t *
+dhtlist_addelem(dhtlist_t *dhtlist, dhtlistelem_t *elem)
+{
+ if (dhtlist->first == NULL)
+ dhtlist->first = elem;
+ if (dhtlist->last == NULL)
+ dhtlist->last = elem;
+ else {
+ dhtlist->last->next = elem;
+ elem->prev = dhtlist->last;
+ dhtlist->last = elem;
+ }
+ dhtlist->len++;
+
+ return elem;
+}
+
+dhtlistelem_t *
+dhtlist_add(dhtlist_t *dhtlist, dhtnode_t *node)
+{
+ return dhtlist_addelem(dhtlist, dhtlistelem_new(node));
+}
+
+dhtlistelem_t *
+dhtlist_push(dhtlist_t *dhtlist, dhtnode_t *node)
+{
+ dhtlistelem_t *elem;
+
+ elem = dhtlistelem_new(node);
+
+ if (dhtlist->first == NULL)
+ dhtlist->first = elem;
+ else {
+ dhtlist->first->prev = elem;
+ elem->next = dhtlist->first;
+ dhtlist->first = elem;
+ }
+ if (dhtlist->last == NULL)
+ dhtlist->last = elem;
+ dhtlist->len++;
+
+ return elem;
+}
+
+void
+dhtlist_delelemlinks(dhtlist_t *dhtlist, dhtlistelem_t *elem)
+{
+ dhtlistelem_t *prev, *next;
+
+ prev = elem->prev;
+ next = elem->next;
+
+ if (prev != NULL)
+ prev->next = next;
+ if (next != NULL)
+ next->prev = prev;
+ if (dhtlist->first == elem)
+ dhtlist->first = next;
+ if (dhtlist->last == elem)
+ dhtlist->last = prev;
+ dhtlist->len--;
+}
+
+dhtlistelem_t *
+dhtlist_insert(dhtlist_t *dhtlist, dhtlistelem_t *elem, int idx)
+{
+ int i;
+ dhtlistelem_t *next;
+
+ i = 0;
+
+ if (idx > dhtlist->len-1)
+ return NULL;
+ if (idx == dhtlist->len-1)
+ return dhtlist_addelem(dhtlist, elem);
+
+ forodhtlist(dhtlist, next)
+ if (i == idx)
+ break;
+
+ if (next->prev != NULL)
+ next->prev->next = elem;
+ elem->prev = next->prev;
+ next->prev = elem;
+ elem->next = next;
+ dhtlist->len++;
+
+ return elem;
+}
+
+dhtlistelem_t *
+dhtlist_move(dhtlist_t *dhtlist, dhtlistelem_t *elem, int idx)
+{
+ dhtlist_delelemlinks(dhtlist, elem);
+ return dhtlist_insert(dhtlist, elem, idx);
+}
+
+void
+dhtlist_print(dhtlist_t *dhtlist)
+{
+ fordhtlist(dhtlist, elem)
+ printf("%p\n", (void *)elem);
+ fflush(stdout);
+}
+
diff --git a/dhttest.c b/dhttest.c
@@ -0,0 +1,113 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include "dht.h"
+
+int
+main(void)
+{
+ dht_t *dht;
+ dhtnode_t *node, *node78;
+ char nodename[17];
+ dhtlist_t *results;
+
+ bzero(nodename, sizeof(nodename));
+ dht = dht_new("testnetwork");
+
+ for (int i = 0; i < 4096; i++) {
+ node = dhtnode_new();
+ dhtnode_mkid(node);
+ snprintf(nodename, sizeof(nodename)-1, "node%d", i);
+ dhtnode_setaddr(node, nodename);
+
+ if(dht_update(dht, node) == NULL) {
+ dhtnode_free(node);
+ break;
+ }
+
+ if (i == 78)
+ node78 = node;
+ }
+ printf("4096 nodes created.\n");
+
+ printf("node78:\n");
+ dhtnode_print(node78);
+ printf("nearby node78 is:\n");
+ results = dht_find(dht, node78, 5);
+ fordhtlist(results, elem)
+ dhtnode_print(elem->node);
+ dhtlist_free(results);
+
+ node = dhtnode_new();
+ dhtnode_mkid(node);
+ printf("noderand:\n");
+ dhtnode_print(node);
+ printf("nearby noderand is:\n");
+ results = dht_find(dht, node, 10);
+ fordhtlist(results, elem)
+ dhtnode_print(elem->node);
+ dhtlist_free(results);
+ dhtnode_free(node);
+
+ dht_free(dht);
+
+ dht = dht_new("localhost");
+ dhtnode_setid(dht->routing->node, "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+
+ node = dhtnode_new();
+ dhtnode_setid(node, "\xFF\xFF\xFF\xF0\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+ dhtnode_setaddr(node, "node1");
+ dht_update(dht, node);
+
+ node = dhtnode_new();
+ dhtnode_setid(node, "\x11\x11\x11\x11\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+ dhtnode_setaddr(node, "node2");
+ dht_update(dht, node);
+
+ node = dhtnode_new();
+ dhtnode_setid(node, "\x22\x22\x22\x22\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+ dhtnode_setaddr(node, "nodesearch");
+ printf("searching for one nearby node\n");
+ results = dht_find(dht, node, 1);
+ fordhtlist(results, elem)
+ dhtnode_print(elem->node);
+ dhtlist_free(results);
+ dhtnode_free(node);
+
+ node = dhtnode_new();
+ dhtnode_setid(node, "\xFF\xFF\xFF\xF0\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+ dhtnode_setaddr(node, "nodesearch2");
+ printf("searching for 10 nearby nodes\n");
+ results = dht_find(dht, node, 10);
+ fordhtlist(results, elem)
+ dhtnode_print(elem->node);
+ dhtlist_free(results);
+ dhtnode_free(node);
+
+ node = dhtnode_new();
+ dhtnode_setid(node, "\x11\x11\x11\x11\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\00\x00\x00\x00\x00");
+ dhtnode_setaddr(node, "nodesearch3");
+ printf("searching for one nearby nodes\n");
+ results = dht_find(dht, node, 1);
+ fordhtlist(results, elem)
+ dhtnode_print(elem->node);
+ dhtlist_free(results);
+ dhtnode_free(node);
+ dht_free(dht);
+
+ return 0;
+}
+
diff --git a/ind.c b/ind.c
@@ -0,0 +1,99 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "ind.h"
+
+void
+die(char *fmt, ...)
+{
+ va_list fmtargs;
+
+ va_start(fmtargs, fmt);
+ vfprintf(stderr, fmt, fmtargs);
+ va_end(fmtargs);
+
+ exit(EXIT_FAILURE);
+}
+
+void
+edie(char *fmt, ...)
+{
+ va_list fmtargs;
+
+ va_start(fmtargs, fmt);
+ vfprintf(stderr, fmt, fmtargs);
+ va_end(fmtargs);
+
+ perror(NULL);
+
+ exit(EXIT_FAILURE);
+}
+
+void *
+reallocz(void *p, int l, int z)
+{
+ p = realloc(p, l);
+ if(p == NULL)
+ edie("realloc");
+ if(z > 0)
+ memset(p, 0, l);
+
+ return p;
+}
+
+void *
+mallocz(int l, int z)
+{
+ return reallocz(NULL, l, z);
+}
+
+void *
+memdup(void *p, int l)
+{
+ char *ret;
+
+ ret = reallocz(NULL, l, 2);
+ memmove(ret, p, l);
+
+ return (void *)ret;
+}
+
+char *
+vsmprintf(char *fmt, va_list fmtargs)
+{
+ char *ret;
+ int size;
+
+ ret = "";
+
+ size = vsnprintf(ret, 0, fmt, fmtargs);
+ ret = reallocz(NULL, ++size, 2);
+ vsnprintf(ret, size, fmt, fmtargs);
+
+ return ret;
+}
+
+char *
+smprintf(char *fmt, ...)
+{
+ va_list fmtargs;
+ char *ret;
+
+ va_start(fmtargs, fmt);
+ ret = vsmprintf(fmt, fmtargs);
+ va_end(fmtargs);
+
+ return ret;
+}
+
diff --git a/ind.h b/ind.h
@@ -0,0 +1,22 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef __IND_H__
+#define __IND_H__
+
+#define nelem(x) (sizeof(x) / sizeof((x)[0]))
+
+#include <stdarg.h>
+
+void die(char *fmt, ...);
+void edie(char *fmt, ...);
+void *reallocz(void *p, int l, int z);
+void *mallocz(int l, int z);
+void *memdup(void *p, int l);
+char *vsmprintf(char *fmt, va_list fmtargs);
+char *smprintf(char *fmt, ...);
+
+#endif
+