libdht

A simple helper library for distributed hash tables.
git clone git://r-36.net/libdht
Log | Files | Refs | LICENSE

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 +