naturalpolice / libdht

C implementation of the Kademlia-based Distributed Hash Table (DHT) used in the BitTorrent network (aka "mainline DHT")
MIT License
22 stars 5 forks source link

libdht

Build Status

libdht is a C implementation of the Kademlia-based Distributed Hash Table (DHT) used in the BitTorrent network (aka "mainline DHT").

Features

License

libdht is distributed under the MIT license (see LICENSE). The present source also incorporates code from the following external projects:

Dependencies

libdht only depends on the following libraries:

It does not require any other external libraries.

Supported platforms

So far libdht has been successfully built and tested on:

Documentation

Doxygen generated documentation for the library's API is available online at https://naturalpolice.github.io/libdht/.

Running a DHT node

Here is an example to get started operating a basic DHT node. Please refer to the rest of the documentation for more complex scenarios.

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <dht/node.h>

static void sock_send(const unsigned char *data, size_t len,
                      const struct sockaddr *dest, socklen_t addrlen,
                      void *opaque)
{
    int sock = *(int *)opaque;

    if (sendto(sock, data, len, 0, dest, addrlen) < 0)
        fprintf(stderr, "sendto: %s\n", strerror(errno));
}

int node_run(void)
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in sin;
    struct dht_node node;

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(6881);

    bind(sock, (struct sockaddr *)&sin, sizeof(sin));

    if (dht_node_init(&node, NULL, sock_send, &sock))
        return -1;

    dht_node_start(&node);

    while (1) {
        struct timeval tv;
        fd_set rfds;
        int rc;

        FD_ZERO(&rfds);
        FD_SET(sock, &rfds);

        dht_node_timeout(&node, &tv);
        rc = select(sock + 1, &rfds, NULL, NULL, &tv);
        if (rc < 0) {
            fprintf(stderr, "select: %s\n", strerror(errno));
            return -1;
        }
        if (rc && FD_ISSET(sock, &rfds)) {
            unsigned char buf[2048];
            struct sockaddr_storage ss;
            socklen_t sl = sizeof(ss);

            rc = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&ss, &sl);
            if (rc < 0) {
                fprintf(stderr, "recvfrom: %s\n", strerror(errno));
                return -1;
            }

            dht_node_input(&node, buf, rc, (struct sockaddr *)&ss, sl);
        }

        dht_node_work(&node);
    }

    return 0;
}