Ticket #7: transmission-dht-2009.06.19.01.diff

File transmission-dht-2009.06.19.01.diff, 119.9 KB (added by charles, 13 years ago)

updated diff

  • libtransmission/peer-io.c

     
    617617    io->extendedProtocolSupported = flag;
    618618}
    619619
     620void
     621tr_peerIoEnableDHT( tr_peerIo  * io,
     622                    tr_bool      flag )
     623{
     624    assert( tr_isPeerIo( io ) );
     625    assert( tr_isBool( flag ) );
     626
     627    dbgmsg( io, "setting DHT support flag to %d", (flag!=0) );
     628    io->dhtSupported = flag;
     629}
     630
    620631/**
    621632***
    622633**/
  • libtransmission/peer-msgs.c

     
    3636#include "request-list.h"
    3737#include "stats.h"
    3838#include "torrent.h"
     39#include "tr-dht.h"
    3940#include "trevent.h"
    4041#include "utils.h"
    4142#include "version.h"
     
    307308}
    308309
    309310static void
     311protocolSendPort(tr_peermsgs *msgs, uint16_t port)
     312{
     313    tr_peerIo       * io  = msgs->peer->io;
     314    struct evbuffer * out = msgs->outMessages;
     315
     316    dbgmsg( msgs, "sending Port %u", port);
     317    tr_peerIoWriteUint32( io, out, 3 );
     318    tr_peerIoWriteUint8 ( io, out, BT_PORT );
     319    tr_peerIoWriteUint16( io, out, port);
     320}
     321
     322static void
    310323protocolSendHave( tr_peermsgs * msgs,
    311324                  uint32_t      index )
    312325{
     
    21232136    if( tr_peerIoSupportsLTEP( peer->io ) )
    21242137        sendLtepHandshake( m );
    21252138
     2139    if(tr_peerIoSupportsDHT(peer->io))
     2140        protocolSendPort(m, tr_dhtPort(torrent->session));
     2141
    21262142    tellPeerWhatWeHave( m );
    21272143
    21282144    tr_peerIoSetIOFuncs( m->peer->io, canRead, didWrite, gotError, m );
  • libtransmission/torrent.h

     
    175175    struct tr_tracker *        tracker;
    176176    struct tr_publisher_tag *  trackerSubscription;
    177177
     178    time_t                     dhtAnnounceAt;
     179    tr_bool                    dhtAnnounceInProgress;
     180
    178181    uint64_t                   downloadedCur;
    179182    uint64_t                   downloadedPrev;
    180183    uint64_t                   uploadedCur;
     
    288291    return ( tor != NULL  ) && tor->session->isPexEnabled && !tr_torrentIsPrivate( tor );
    289292}
    290293
     294static TR_INLINE tr_bool tr_torrentAllowsDHT( const tr_torrent * tor )
     295{
     296    return ( tor != NULL  ) && tor->session->isDHTEnabled && !tr_torrentIsPrivate( tor );
     297}
     298
    291299static TR_INLINE tr_bool tr_torrentIsPieceChecked( const tr_torrent  * tor, tr_piece_index_t i )
    292300{
    293301    return tr_bitfieldHasFast( &tor->checkedPieces, i );
  • libtransmission/peer-io.h

     
    6363    tr_bool               peerIdIsSet;
    6464    tr_bool               extendedProtocolSupported;
    6565    tr_bool               fastExtensionSupported;
     66    tr_bool               dhtSupported;
    6667
    6768    /* we create the socket in a nonblocking way, so this flag is initially
    6869     * false and then set to true when libevent says that the socket is ready
     
    159160    return io->fastExtensionSupported;
    160161}
    161162
     163void        tr_peerIoEnableDHT( tr_peerIo * io, tr_bool flag );
     164
     165static TR_INLINE tr_bool tr_peerIoSupportsDHT( const tr_peerIo * io )
     166{
     167    assert( tr_isPeerIo( io ) );
     168
     169    return io->dhtSupported;
     170}
     171
    162172/**
    163173***
    164174**/
  • libtransmission/peer-mgr.c

     
    18731873        if( !stat->clientIsChoked && !stat->clientIsInterested ) *pch++ = 'K';
    18741874        if( !stat->peerIsChoked && !stat->peerIsInterested ) *pch++ = '?';
    18751875        if( stat->isEncrypted ) *pch++ = 'E';
     1876        if( stat->from == TR_PEER_FROM_DHT ) *pch++ = 'H';
    18761877        if( stat->from == TR_PEER_FROM_PEX ) *pch++ = 'X';
    18771878        if( stat->isIncoming ) *pch++ = 'I';
    18781879        *pch = '\0';
     
    21632164    if( a->time != b->time )
    21642165        return a->time < b->time ? -1 : 1;
    21652166
    2166     /* all other things being equal, prefer peers whose
    2167      * information comes from a more reliable source */
     2167    /* In order to avoid fragmenting the swarm, peers from trackers and
     2168     * from the DHT should be preferred to peers from PEX. */
    21682169    if( a->from != b->from )
    21692170        return a->from < b->from ? -1 : 1;
    21702171
  • libtransmission/handshake.c

     
    2828#include "peer-io.h"
    2929#include "peer-mgr.h"
    3030#include "torrent.h"
     31#include "tr-dht.h"
    3132#include "trevent.h"
    3233#include "utils.h"
    3334
     
    3536#define ENABLE_LTEP * /
    3637/* fast extensions */
    3738#define ENABLE_FAST * /
     39/* DHT */
     40#define ENABLE_DHT * /
    3841
    3942/***
    4043****
     
    8285 #define HANDSHAKE_SET_FASTEXT( bits ) ( (void)0 )
    8386#endif
    8487
     88#ifdef ENABLE_DHT
     89 #define HANDSHAKE_HAS_DHT( bits ) ( ( ( bits )[7] & 0x01 ) ? 1 : 0 )
     90 #define HANDSHAKE_SET_DHT( bits ) ( ( bits )[7] |= 0x01 )
     91#else
     92 #define HANDSHAKE_HAS_DHT( bits ) ( 0 )
     93 #define HANDSHAKE_SET_DHT( bits ) ( (void)0 )
     94#endif
     95
    8596/* http://www.azureuswiki.com/index.php/Extension_negotiation_protocol
    8697   these macros are to be used if both extended messaging and the
    8798   azureus protocol is supported, they indicate which protocol is preferred */
     
    219230    HANDSHAKE_SET_LTEP( walk );
    220231    HANDSHAKE_SET_FASTEXT( walk );
    221232
     233    /* Note that this doesn't depend on whether the torrent is private.  We
     234       don't accept DHT peers for a private torrent, but we participate in
     235       the DHT regardless. */
     236    if(tr_dhtEnabled(handshake->session))
     237        HANDSHAKE_SET_DHT( walk );
     238
    222239    walk += HANDSHAKE_FLAGS_LEN;
    223240    memcpy( walk, torrentHash, SHA_DIGEST_LENGTH );
    224241    walk += SHA_DIGEST_LENGTH;
     
    303320
    304321    tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) );
    305322
     323    /* This does not depend on whether the torrent is private. */
     324    if(tor->session->isPexEnabled)
     325        tr_peerIoEnableDHT( handshake->io, HANDSHAKE_HAS_DHT( reserved ) );
     326
    306327    return HANDSHAKE_OK;
    307328}
    308329
  • libtransmission/transmission.h

     
    530530
    531531tr_bool            tr_sessionIsPexEnabled( const tr_session * session );
    532532
     533tr_bool            tr_sessionIsDHTEnabled( const tr_session * session );
     534
    533535void               tr_sessionSetLazyBitfieldEnabled( tr_session * session,
    534536                                                     tr_bool       enabled );
    535537
     
    13431345{
    13441346    TR_PEER_FROM_INCOMING  = 0,  /* connections made to the listening port */
    13451347    TR_PEER_FROM_TRACKER   = 1,  /* peers received from a tracker */
    1346     TR_PEER_FROM_CACHE     = 2,  /* peers read from the peer cache */
    1347     TR_PEER_FROM_PEX       = 3,  /* peers discovered via PEX */
     1348    TR_PEER_FROM_DHT       = 2,  /* peers learnt from the DHT */
     1349    TR_PEER_FROM_CACHE     = 3,  /* peers read from the peer cache */
     1350    TR_PEER_FROM_PEX       = 4,  /* peers discovered via PEX */
    13481351    TR_PEER_FROM__MAX
    13491352};
    13501353
  • libtransmission/session.c

     
    4545#include "version.h"
    4646#include "verify.h"
    4747#include "web.h"
     48#include "tr-dht.h"
    4849
    4950#define dbgmsg( ... ) \
    5051    do { \
     
    573574    while( session->isWaiting )
    574575        tr_wait( 100 );
    575576
     577    if(session->isDHTEnabled)
     578        tr_dhtInit(session);
     579
    576580    return session;
    577581}
    578582
     
    621625    found = tr_bencDictFindBool( &settings, TR_PREFS_KEY_PEX_ENABLED, &boolVal );
    622626    assert( found );
    623627    session->isPexEnabled = boolVal;
     628    /* This really ought to be a separate preference. */
     629    session->isDHTEnabled = boolVal;
    624630
    625631    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ENCRYPTION, &i );
    626632    assert( found );
     
    14541460
    14551461    dbgmsg( "shutting down transmission session %p", session );
    14561462
     1463    if(session->isDHTEnabled)
     1464        tr_dhtUninit(session);
     1465
    14571466    /* close the session */
    14581467    tr_runInEventThread( session, tr_closeAllConnections, session );
    14591468    while( !session->isClosed && !deadlineReached( deadline ) )
     
    15791588    return session->isPexEnabled;
    15801589}
    15811590
     1591tr_bool
     1592tr_sessionIsDHTEnabled( const tr_session * session )
     1593{
     1594    assert( tr_isSession( session ) );
     1595
     1596    return session->isDHTEnabled;
     1597}
     1598
    15821599/***
    15831600****
    15841601***/
  • libtransmission/Makefile.am

     
    4949    torrent-ctor.c \
    5050    tr-getopt.c \
    5151    tracker.c \
     52    tr-dht.c \
    5253    trevent.c \
    5354    upnp.c \
    5455    utils.c \
     
    9697    tracker.h \
    9798    tr-getopt.h \
    9899    transmission.h \
     100    tr-dht.h \
    99101    trevent.h \
    100102    upnp.h \
    101103    utils.h \
     
    124126    $(top_builddir)/third-party/miniupnp/libminiupnp.a \
    125127    $(top_builddir)/third-party/libnatpmp/libnatpmp.a \
    126128    $(top_builddir)/third-party/libevent/libevent.la \
     129    $(top_builddir)/third-party/dht/libdht.a \
    127130    $(INTLLIBS) \
    128131    $(LIBCURL_LIBS) \
    129132    $(OPENSSL_LIBS) \
  • libtransmission/session.h

     
    6161{
    6262    tr_bool                      isPortRandom;
    6363    tr_bool                      isPexEnabled;
     64    tr_bool                      isDHTEnabled;
    6465    tr_bool                      isBlocklistEnabled;
    6566    tr_bool                      isProxyEnabled;
    6667    tr_bool                      isProxyAuthEnabled;
  • libtransmission/tracker.c

     
    2626#include "resume.h"
    2727#include "torrent.h"
    2828#include "tracker.h"
     29#include "tr-dht.h"
    2930#include "trevent.h"
    3031#include "utils.h"
    3132#include "web.h"
     
    977978            t->manualAnnounceAllowedAt = TR_TRACKER_BUSY;
    978979            enqueueRequest( session, t, TR_REQ_REANNOUNCE );
    979980        }
     981
     982        if( tor->dhtAnnounceAt <= now ) {
     983            int rc = 1;
     984            if( tr_torrentAllowsDHT(tor) )
     985                rc = tr_dhtAnnounce(tor, 1);
     986            if(rc == 0)
     987                /* The DHT is not ready yet.  Try again soon. */
     988                tor->dhtAnnounceAt = now + 5 + random() % 5;
     989            else
     990                /* We should announce at least once every 30 minutes. */
     991                tor->dhtAnnounceAt = now + 25 * 60 + random() % (3 * 60);
     992        }
    980993    }
    981994
    982995    if( th->runningCount )
  • libtransmission/torrent.c

     
    12851285    tr_torrentSaveResume( tor );
    12861286    tor->startDate = tor->anyDate = time( NULL );
    12871287    tr_trackerStart( tor->tracker );
     1288    tor->dhtAnnounceAt = time(NULL) + random() % 20;
    12881289    tr_peerMgrStartTorrent( tor );
    12891290
    12901291    tr_globalUnlock( tor->session );
  • gtk/details.c

     
    941941        if( i!=n )
    942942            str = mixed;
    943943        else if( baseline )
    944             str = _( "Private to this tracker -- PEX disabled" );
     944            str = _( "Private to this tracker -- DHT and PEX disabled" );
    945945        else
    946946            str = _( "Public torrent" );
    947947    }
     
    14981498                case '?': s = _( "We unchoked this peer, but they're not interested" ); break;
    14991499                case 'E': s = _( "Encrypted connection" ); break;
    15001500                case 'X': s = _( "Peer was discovered through Peer Exchange (PEX)" ); break;
     1501                case 'H': s = _( "Peer was discovered through the DHT" ); break;
    15011502                case 'I': s = _( "Peer is an incoming connection" ); break;
    15021503            }
    15031504            if( s )
  • gtk/Makefile.am

     
    103103    $(top_builddir)/third-party/libevent/libevent.la \
    104104    $(top_builddir)/third-party/miniupnp/libminiupnp.a \
    105105    $(top_builddir)/third-party/libnatpmp/libnatpmp.a \
     106    $(top_builddir)/third-party/dht/libdht.a \
    106107    $(GTK_LIBS) \
    107108    $(GIO_LIBS) \
    108109    $(LIBNOTIFY_LIBS) \
  • AUTHORS

     
    77
    88Project Contributors
    99  Tomas Carnecky  (Profiling, patches, and detection of sneaky bugs)
     10  Juliusz Chroboczek  (DHT)
    1011  John Clay  (Website maintenance and troubleshooting)
    1112  Rashid Eissing  (Mac OS X Transfers preferences icon)
    1213  Hugo van Heuven, madebysofa  (Main icon design)
  • configure.ac

     
    263263use_nls=no
    264264if test "x$enable_nls" = "xyes" ; then
    265265    use_nls=yes
    266     IT_PROG_INTLTOOL([0.40.0],[no-xml])
     266    IT_PROG_INTLTOOL([0.35],[no-xml])
    267267    AC_CHECK_HEADERS([libintl.h])
    268268    GETTEXT_PACKAGE=transmission
    269269    AC_SUBST(GETTEXT_PACKAGE)
     
    355355                 third-party/Makefile
    356356                 third-party/miniupnp/Makefile
    357357                 third-party/libnatpmp/Makefile
     358                 third-party/dht/Makefile
    358359                 macosx/Makefile
    359360                 gtk/Makefile
    360361                 gtk/icons/Makefile
  • daemon/Makefile.am

     
    2222    $(top_builddir)/third-party/miniupnp/libminiupnp.a \
    2323    $(top_builddir)/third-party/libnatpmp/libnatpmp.a \
    2424    $(top_builddir)/third-party/libevent/libevent.la \
     25    $(top_builddir)/third-party/dht/libdht.a \
    2526    $(INTLLIBS) \
    2627    $(LIBCURL_LIBS) \
    2728    $(ZLIB_LIBS) \
  • cli/Makefile.am

     
    2020    $(top_builddir)/third-party/libevent/libevent.la \
    2121    $(top_builddir)/third-party/libnatpmp/libnatpmp.a \
    2222    $(top_builddir)/third-party/miniupnp/libminiupnp.a \
     23    $(top_builddir)/third-party/dht/libdht.a \
    2324    $(INTLLIBS) \
    2425    $(LIBCURL_LIBS) \
    2526    $(ZLIB_LIBS) \
  • third-party/dht/makelog

     
     1if gcc -DPACKAGE_NAME=\"transmission\" -DPACKAGE_TARNAME=\"transmission\" -DPACKAGE_VERSION=\"1.61+\" -DPACKAGE_STRING=\"transmission\ 1.61+\" -DPACKAGE_BUGREPORT=\"http://trac.transmissionbt.com/newticket\" -DPACKAGE=\"transmission\" -DVERSION=\"1.61+\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DTR_NIGHTLY_RELEASE=1 -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_DAEMON=1 -DHAVE_DIRNAME=1 -DHAVE_BASENAME=1 -DHAVE_DAEMON=1 -DHAVE_STRCASECMP=1 -DHAVE_LOCALTIME_R=1 -DHAVE_POSIX_FALLOCATE=1 -DHAVE_MEMMEM=1 -DHAVE_PTHREAD=1 -DHAVE__TMP_DUMMY1_ZLIB_H=1 -DHAVE_ZLIB=1 -DHAVE_DECL_POSIX_FADVISE=1 -DHAVE_POSIX_FADVISE=1 -DWITH_INOTIFY=1 -DHAVE_DBUS_GLIB=1 -DHAVE_LIBINTL_H=1 -DGETTEXT_PACKAGE=\"transmission\" -DHAVE_LOCALE_H=1 -DHAVE_LC_MESSAGES=1 -DHAVE_BIND_TEXTDOMAIN_CODESET=1 -DHAVE_GETTEXT=1 -DHAVE_DCGETTEXT=1 -DENABLE_NLS=1  -I. -I.   -I/mnt/home/charles/opt/easytag/include -I/mnt/home/charles/wx/include -I/mnt/home/charles/wx/include   -Os -Wall -W -ggdb3 -g -O0 -std=gnu99 -ggdb3 -Wall -W -Wpointer-arith -Wformat-security -Wcast-align -Wundef -Wcast-align -Wstrict-prototypes -Wmissing-declarations -Wmissing-format-attribute -Wredundant-decls -Wnested-externs -Wunused-parameter -Wwrite-strings -Wextra -Wdeclaration-after-statement -Winit-self -MT dht.o -MD -MP -MF ".deps/dht.Tpo" -c -o dht.o dht.c; \
     2        then mv -f ".deps/dht.Tpo" ".deps/dht.Po"; else rm -f ".deps/dht.Tpo"; exit 1; fi
     3dht.c:1321: warning: unused parameter ‘s’
     4dht.c:1952: warning: unused parameter ‘port’
     5rm -f libdht.a
     6ar cru libdht.a dht.o
     7ranlib libdht.a
  • third-party/dht/dht.c

     
     1/*
     2Copyright (c) 2009 by Juliusz Chroboczek
     3
     4Permission is hereby granted, free of charge, to any person obtaining a copy
     5of this software and associated documentation files (the "Software"), to deal
     6in the Software without restriction, including without limitation the rights
     7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8copies of the Software, and to permit persons to whom the Software is
     9furnished to do so, subject to the following conditions:
     10
     11The above copyright notice and this permission notice shall be included in
     12all copies or substantial portions of the Software.
     13
     14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20THE SOFTWARE.
     21*/
     22
     23/* Please, please, please.
     24
     25   You are welcome to integrate this code in your favourite Bittorrent
     26   client.  Please remember, however, that it is meant to be usable by
     27   others, including myself.  This means no C++, no relicensing, and no
     28   gratuitious changes to the coding style.  And please send back any
     29   improvements to the author. */
     30
     31/* For memmem. */
     32#define _GNU_SOURCE
     33
     34#include <stdio.h>
     35#include <stdlib.h>
     36#include <errno.h>
     37#include <string.h>
     38#include <stdarg.h>
     39#include <unistd.h>
     40#include <fcntl.h>
     41#include <sys/time.h>
     42#include <arpa/inet.h>
     43#include <sys/types.h>
     44#include <sys/socket.h>
     45
     46#include "dht.h"
     47
     48#ifndef MSG_CONFIRM
     49#define MSG_CONFIRM 0
     50#endif
     51
     52/* We set sin_family to 0 to mark unused slots. */
     53#if AF_INET == 0
     54#error You lose
     55#endif
     56
     57#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
     58/* nothing */
     59#elif defined(__GNUC__)
     60#define inline __inline
     61#if  (__GNUC__ >= 3)
     62#define restrict __restrict
     63#else
     64#define restrict /**/
     65#endif
     66#else
     67#define inline /**/
     68#define restrict /**/
     69#endif
     70
     71#define MAX(x, y) ((x) >= (y) ? (x) : (y))
     72#define MIN(x, y) ((x) <= (y) ? (x) : (y))
     73
     74struct node {
     75    unsigned char id[20];
     76    struct sockaddr_in sin;
     77    time_t time;                /* time of last message received */
     78    time_t reply_time;          /* time of last correct reply received */
     79    time_t pinged_time;         /* time of last request */
     80    int pinged;                 /* how many requests we sent since last reply */
     81    struct node *next;
     82};
     83
     84struct bucket {
     85    unsigned char first[20];
     86    int count;                  /* number of nodes */
     87    int time;                   /* time of last reply in this bucket */
     88    struct node *nodes;
     89    struct sockaddr_in cached;  /* the address of a likely candidate */
     90    struct bucket *next;
     91};
     92
     93struct search_node {
     94    unsigned char id[20];
     95    struct sockaddr_in sin;
     96    time_t request_time;        /* the time of the last unanswered request */
     97    time_t reply_time;          /* the time of the last reply */
     98    int pinged;
     99    unsigned char token[40];
     100    int token_len;
     101    int replied;                /* whether we have received a reply */
     102    int acked;                  /* whether they acked our announcement */
     103};
     104
     105/* When performing a search, we search for up to SEARCH_NODES closest nodes
     106   to the destinatin, and use the additional ones to backtrack if any of
     107   the target 8 turn out to be dead. */
     108#define SEARCH_NODES 14
     109
     110struct search {
     111    unsigned short tid;
     112    time_t step_time;           /* the time of the last search_step */
     113    unsigned char id[20];
     114    unsigned short port;        /* 0 for pure searches */
     115    int done;
     116    struct search_node nodes[SEARCH_NODES];
     117    int numnodes;
     118};
     119
     120struct peer {
     121    time_t time;
     122    unsigned char ip[4];
     123    unsigned short port;
     124};
     125
     126/* The maximum number of peers we store for a given hash. */
     127#ifndef DHT_MAX_PEERS
     128#define DHT_MAX_PEERS 2048
     129#endif
     130
     131struct storage {
     132    unsigned char id[20];
     133    int numpeers;
     134    int maxpeers;
     135    struct peer *peers;
     136    struct storage *next;
     137};
     138
     139static int send_ping(int s, struct sockaddr *sa, int salen,
     140                     const unsigned char *tid, int tid_len);
     141static int send_pong(int s, struct sockaddr *sa, int salen,
     142                     const unsigned char *tid, int tid_len);
     143static int send_find_node(int s, struct sockaddr *sa, int salen,
     144                          const unsigned char *tid, int tid_len,
     145                          const unsigned char *target, int confirm);
     146static int send_found_nodes(int s, struct sockaddr *sa, int salen,
     147                            const unsigned char *tid, int tid_len,
     148                            const unsigned char *nodes, int nodes_len,
     149                            const unsigned char *token, int token_len);
     150static int send_bucket_nodes(int s, struct sockaddr *sa, int salen,
     151                             const unsigned char *tid, int tid_len,
     152                             struct bucket *b,
     153                             const unsigned char *token, int token_len);
     154static int send_get_peers(int s, struct sockaddr *sa, int salen,
     155                          unsigned char *tid, int tid_len,
     156                          unsigned char *infohash, unsigned short port,
     157                          int confirm);
     158static int send_announce_peer(int s, struct sockaddr *sa, int salen,
     159                              unsigned char *tid, int tid_len,
     160                              unsigned char *infohas, unsigned short port,
     161                              unsigned char *token, int token_len, int confirm);
     162int send_peers_found(int s, struct sockaddr *sa, int salen,
     163                     unsigned char *tid, int tid_len,
     164                     struct peer *peers1, int numpeers1,
     165                     struct peer *peers2, int numpeers2,
     166                     unsigned char *token, int token_len);
     167int send_peer_announced(int s, struct sockaddr *sa, int salen,
     168                        unsigned char *tid, int tid_len);
     169
     170#define REPLY 0
     171#define PING 1
     172#define FIND_NODE 2
     173#define GET_PEERS 3
     174#define ANNOUNCE_PEER 4
     175static int parse_message(const unsigned char *buf, int buflen,
     176                         unsigned char *tid_return, int *tid_len,
     177                         unsigned char *id_return,
     178                         unsigned char *info_hash_return,
     179                         unsigned char *target_return,
     180                         unsigned short *port_return,
     181                         unsigned char *token_return, int *token_len,
     182                         unsigned char *nodes_return, int *nodes_len,
     183                         const unsigned char *values_return, int *values_len);
     184
     185static const unsigned char zeroes[20] = {0};
     186static const unsigned char ones[20] = {
     187    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     188    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     189    0xFF, 0xFF, 0xFF, 0xFF
     190};
     191static time_t search_time;
     192static time_t confirm_nodes_time;
     193static time_t rotate_secrets_time;
     194
     195static unsigned char myid[20];
     196static unsigned char secret[8];
     197static unsigned char oldsecret[8];
     198
     199static struct bucket *buckets = NULL;
     200static struct storage *storage;
     201
     202/* The maximum number of concurrent searches. */
     203#ifndef DHT_MAX_SEARCHES
     204#define DHT_MAX_SEARCHES 20
     205#endif
     206
     207static struct search searches[DHT_MAX_SEARCHES];
     208static int numsearches;
     209static unsigned short search_id;
     210
     211/* The maximum number of nodes that we snub.  There is probably little
     212   reason to increase this value. */
     213#ifndef DHT_MAX_BLACKLISTED
     214#define DHT_MAX_BLACKLISTED 10
     215#endif
     216static struct sockaddr_in blacklist[DHT_MAX_BLACKLISTED];
     217int next_blacklisted;
     218
     219static struct timeval now;
     220static time_t mybucket_grow_time;
     221static time_t expire_stuff_time;
     222
     223#define MAX_LEAKY_BUCKET_TOKENS 40
     224static time_t leaky_bucket_time;
     225static int leaky_bucket_tokens;
     226
     227FILE *dht_debug = NULL;
     228
     229#ifdef __GNUC__
     230    __attribute__ ((format (printf, 1, 2)))
     231#endif
     232static void
     233debugf(const char *format, ...)
     234{
     235    va_list args;
     236    va_start(args, format);
     237    if(dht_debug)
     238        vfprintf(dht_debug, format, args);
     239    va_end(args);
     240    fflush(dht_debug);
     241}
     242
     243static void
     244debug_printable(const unsigned char *buf, int buflen)
     245{
     246    int i;
     247    if(dht_debug) {
     248        for(i = 0; i < buflen; i++)
     249            putc(buf[i] >= 32 && buf[i] <= 126 ? buf[i] : '.', dht_debug);
     250    }
     251}
     252
     253static void
     254print_hex(FILE *f, const unsigned char *buf, int buflen)
     255{
     256    int i;
     257    for(i = 0; i < buflen; i++)
     258        fprintf(f, "%02x", buf[i]);
     259}
     260
     261/* Forget about the ``XOR-metric''.  An id is just a path from the
     262   root of the tree, so bits are numbered from the start. */
     263
     264static inline int
     265id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
     266{
     267    /* Memcmp is guaranteed to perform an unsigned comparison. */
     268    return memcmp(id1, id2, 20);
     269}
     270
     271/* Find the lowest 1 bit in an id. */
     272static int
     273lowbit(const unsigned char *id)
     274{
     275    int i, j;
     276    for(i = 19; i >= 0; i--)
     277        if(id[i] != 0)
     278            break;
     279
     280    if(i < 0)
     281        return -1;
     282
     283    for(j = 7; j >= 0; j--)
     284        if((id[i] & (0x80 >> j)) != 0)
     285            break;
     286
     287    return 8 * i + j;
     288}
     289
     290/* Find how many bits two ids have in common. */
     291static int
     292common_bits(const unsigned char *id1, const unsigned char *id2)
     293{
     294    int i, j;
     295    unsigned char xor;
     296    for(i = 0; i < 20; i++) {
     297        if(id1[i] != id2[i])
     298            break;
     299    }
     300
     301    if(i == 20)
     302        return 160;
     303
     304    xor = id1[i] ^ id2[i];
     305
     306    j = 0;
     307    while((xor & 0x80) == 0) {
     308        xor <<= 1;
     309        j++;
     310    }
     311
     312    return 8 * i + j;
     313}
     314
     315/* We keep buckets in a sorted linked list.  A bucket b ranges from
     316   b->first inclusive up to b->next->first exclusive. */
     317static int
     318in_bucket(const unsigned char *id, struct bucket *b)
     319{
     320    return id_cmp(b->first, id) <= 0 &&
     321        (b->next == NULL || id_cmp(id, b->next->first) < 0);
     322}
     323
     324static struct bucket *
     325find_bucket(unsigned const char *id)
     326{
     327    struct bucket *b = buckets;
     328
     329    while(1) {
     330        if(b->next == NULL)
     331            return b;
     332        if(id_cmp(id, b->next->first) < 0)
     333            return b;
     334        b = b->next;
     335    }
     336}
     337
     338static struct bucket *
     339previous_bucket(struct bucket *b)
     340{
     341    struct bucket *p = buckets;
     342
     343    if(b == p)
     344        return NULL;
     345
     346    while(1) {
     347        if(p->next == NULL)
     348            return NULL;
     349        if(p->next == b)
     350            return p;
     351        p = p->next;
     352    }
     353}
     354
     355/* Every bucket contains an unordered list of nodes. */
     356static struct node *
     357find_node(const unsigned char *id)
     358{
     359    struct bucket *b = find_bucket(id);
     360    struct node *n;
     361
     362    if(b == NULL)
     363        return NULL;
     364    n = b->nodes;
     365    while(n) {
     366        if(id_cmp(n->id, id) == 0)
     367            return n;
     368        n = n->next;
     369    }
     370    return NULL;
     371}
     372
     373/* Return a random node in a bucket. */
     374static struct node *
     375random_node(struct bucket *b)
     376{
     377    struct node *n;
     378    int nn;
     379
     380    if(b->count == 0)
     381        return NULL;
     382
     383    nn = random() % b->count;
     384    n = b->nodes;
     385    while(nn > 0 && n) {
     386        n = n->next;
     387        nn--;
     388    }
     389    return n;
     390}
     391
     392/* Return the middle id of a bucket. */
     393static int
     394bucket_middle(struct bucket *b, unsigned char *id_return)
     395{
     396    int bit1 = lowbit(b->first);
     397    int bit2 = b->next ? lowbit(b->next->first) : -1;
     398    int bit = MAX(bit1, bit2) + 1;
     399
     400    if(bit >= 160)
     401        return -1;
     402
     403    memcpy(id_return, b->first, 20);
     404    id_return[bit / 8] |= (0x80 >> (bit % 8));
     405    return 1;
     406}
     407
     408/* Return a random id within a bucket. */
     409static int
     410bucket_random(struct bucket *b, unsigned char *id_return)
     411{
     412    int bit1 = lowbit(b->first);
     413    int bit2 = b->next ? lowbit(b->next->first) : -1;
     414    int bit = MAX(bit1, bit2) + 1;
     415    int i;
     416
     417    if(bit >= 160) {
     418        memcpy(id_return, b->first, 20);
     419        return 1;
     420    }
     421
     422    memcpy(id_return, b->first, bit / 8);
     423    id_return[bit / 8] = b->first[bit / 8] & (0xFF00 >> (bit % 8));
     424    id_return[bit / 8] |= random() & 0xFF >> (bit % 8);
     425    for(i = bit / 8 + 1; i < 20; i++)
     426        id_return[i] = random() & 0xFF;
     427    return 1;
     428}   
     429
     430/* Insert a new node into a bucket. */
     431static struct node *
     432insert_node(struct node *node)
     433{
     434    struct bucket *b = find_bucket(node->id);
     435
     436    node->next = b->nodes;
     437    b->nodes = node;
     438    b->count++;
     439    return node;
     440}
     441
     442/* This is our definition of a known-good node. */
     443static int
     444node_good(struct node *node)
     445{
     446    return
     447        node->pinged <= 2 &&
     448        node->reply_time >= now.tv_sec - 7200 &&
     449        node->time >= now.tv_sec - 900;
     450}
     451
     452/* Our transaction-ids are 4-bytes long, with the first two bytes identi-
     453   fying the kind of request, and the remaining two a sequence number in
     454   host order. */
     455
     456static void
     457make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
     458{
     459    tid_return[0] = prefix[0] & 0xFF;
     460    tid_return[1] = prefix[1] & 0xFF;
     461    memcpy(tid_return + 2, &seqno, 2);
     462}
     463
     464static int
     465tid_match(const unsigned char *tid, const char *prefix,
     466          unsigned short *seqno_return)
     467{
     468    if(tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
     469        if(seqno_return)
     470            memcpy(seqno_return, tid + 2, 2);
     471        return 1;
     472    } else
     473        return 0;
     474}
     475
     476/* Every bucket caches the address of a likely node.  Ping it. */
     477static int
     478send_cached_ping(int s, struct bucket *b)
     479{
     480    int rc;
     481    /* We set family to 0 when there's no cached node. */
     482    if(b->cached.sin_family == AF_INET) {
     483        unsigned char tid[4];
     484        debugf("Sending ping to cached node.\n");
     485        make_tid(tid, "pn", 0);
     486        rc = send_ping(s, (struct sockaddr*)&b->cached,
     487                       sizeof(struct sockaddr_in),
     488                       tid, 4);
     489        b->cached.sin_family = 0;
     490        return rc;
     491    }
     492    return 0;
     493}
     494
     495/* Split a bucket into two equal parts. */
     496static struct bucket *
     497split_bucket(int s, struct bucket *b)
     498{
     499    struct bucket *new;
     500    struct node *nodes;
     501    int rc;
     502    unsigned char new_id[20];
     503
     504    rc = bucket_middle(b, new_id);
     505    if(rc < 0)
     506        return NULL;
     507
     508    new = calloc(1, sizeof(struct bucket));
     509    if(new == NULL)
     510        return NULL;
     511
     512    send_cached_ping(s, b);
     513
     514    memcpy(new->first, new_id, 20);
     515    new->time = b->time;
     516
     517    nodes = b->nodes;
     518    b->nodes = NULL;
     519    b->count = 0;
     520    new->next = b->next;
     521    b->next = new;
     522    while(nodes) {
     523        struct node *n;
     524        n = nodes;
     525        nodes = nodes->next;
     526        insert_node(n);
     527    }
     528    return b;
     529}
     530
     531/* Called whenever we send a request to a node. */
     532static void
     533pinged(int s, struct node *n, struct bucket *b)
     534{
     535    n->pinged++;
     536    n->pinged_time = now.tv_sec;
     537    if(n->pinged >= 3)
     538        send_cached_ping(s, b ? b : find_bucket(n->id));
     539}
     540
     541/* We just learnt about a node, not necessarily a new one.  Confirm is 1 if
     542   the node sent a message, 2 if it sent us a reply. */
     543static struct node *
     544new_node(int s, const unsigned char *id, struct sockaddr_in *sin,
     545         int confirm)
     546{
     547    struct bucket *b = find_bucket(id);
     548    struct node *n;
     549    int mybucket = in_bucket(myid, b);
     550
     551    if(id_cmp(id, myid) == 0)
     552        return NULL;
     553
     554    if(confirm == 2)
     555        b->time = now.tv_sec;
     556
     557    n = b->nodes;
     558    while(n) {
     559        if(id_cmp(n->id, id) == 0) {
     560            if(confirm || n->time < now.tv_sec - 15 * 60) {
     561                /* Known node.  Update stuff. */
     562                n->sin = *sin;
     563                if(confirm)
     564                    n->time = now.tv_sec;
     565                if(confirm >= 2) {
     566                    n->reply_time = now.tv_sec;
     567                    n->pinged = 0;
     568                    n->pinged_time = 0;
     569                }
     570            }
     571            return n;
     572        }
     573        n = n->next;
     574    }
     575
     576    /* New node.  First, try to get rid of a known-bad node. */
     577    n = b->nodes;
     578    while(n) {
     579        if(n->pinged >= 3) {
     580            memcpy(n->id, id, 20);
     581            n->sin = *sin;
     582            n->time = confirm ? now.tv_sec : 0;
     583            n->reply_time = confirm >= 2 ? now.tv_sec : 0;
     584            n->pinged_time = 0;
     585            n->pinged = 0;
     586            if(mybucket)
     587                mybucket_grow_time = now.tv_sec;
     588            return n;
     589        }
     590        n = n->next;
     591    }
     592
     593    if(b->count >= 8) {
     594        /* Bucket full.  Ping a dubious node */
     595        int dubious = 0;
     596        n = b->nodes;
     597        while(n) {
     598            /* Pick the first dubious node that we haven't pinged in the
     599               last 15 seconds.  This gives nodes the time to reply, but
     600               tends to concentrate on the same nodes. */
     601            if(!node_good(n)) {
     602                dubious = 1;
     603                if(n->pinged_time < now.tv_sec - 15) {
     604                    unsigned char tid[4];
     605                    debugf("Sending ping to dubious node.\n");
     606                    make_tid(tid, "pn", 0);
     607                    send_ping(s,
     608                              (struct sockaddr*)&n->sin,
     609                              sizeof(struct sockaddr_in),
     610                              tid, 4);
     611                    n->pinged++;
     612                    n->pinged_time = now.tv_sec;
     613                    break;
     614                }
     615            }
     616            n = n->next;
     617        }
     618       
     619        if(!dubious && mybucket) {
     620            debugf("Splitting.\n");
     621            b = split_bucket(s, b);
     622            mybucket_grow_time = now.tv_sec;
     623            return new_node(s, id, sin, confirm);
     624        }
     625
     626        /* No space for this node.  Cache it away for later. */
     627        if(confirm || b->cached.sin_family == 0)
     628            b->cached = *sin;
     629
     630        return NULL;
     631    }
     632
     633    /* Create a new node. */
     634    n = calloc(1, sizeof(struct node));
     635    if(n == NULL)
     636        return NULL;
     637    memcpy(n->id, id, 20);
     638    n->sin = *sin;
     639    n->time = confirm ? now.tv_sec : 0;
     640    n->reply_time = confirm >= 2 ? now.tv_sec : 0;
     641    n->next = b->nodes;
     642    b->nodes = n;
     643    b->count++;
     644    if(mybucket)
     645        mybucket_grow_time = now.tv_sec;
     646    return n;
     647}
     648
     649/* Called periodically to purge known-bad nodes.  Note that we're very
     650   conservative here: broken nodes in the table don't do much harm, we'll
     651   recover as soon as we find better ones. */
     652static int
     653expire_buckets(int s)
     654{
     655    struct bucket *b = buckets;
     656
     657    while(b) {
     658        struct node *n, *p;
     659        int changed = 0;
     660
     661        while(b->nodes && b->nodes->pinged >= 4) {
     662            n = b->nodes;
     663            b->nodes = n->next;
     664            b->count--;
     665            changed = 1;
     666            free(n);
     667        }
     668
     669        p = b->nodes;
     670        while(p) {
     671            while(p->next && p->next->pinged >= 4) {
     672                n = p->next;
     673                p->next = n->next;
     674                b->count--;
     675                changed = 1;
     676                free(n);
     677            }
     678            p = p->next;
     679        }
     680
     681        if(changed)
     682            send_cached_ping(s, b);
     683
     684        b = b->next;
     685    }
     686    expire_stuff_time = now.tv_sec + 120 + random() % 240;
     687    return 1;
     688}
     689
     690/* While a search is in progress, we don't necessarily keep the nodes being
     691   walked in the main bucket table.  A search in progress is identified by
     692   a unique transaction id, a short (and hence small enough to fit in the
     693   transaction id of the protocol packets). */
     694
     695static struct search *
     696find_search(unsigned short tid)
     697{
     698    int i;
     699    for(i = 0; i < numsearches; i++) {
     700        if(searches[i].tid == tid)
     701            return &searches[i];
     702    }
     703    return NULL;
     704}
     705
     706/* A search contains a list of nodes, sorted by decreasing distance to the
     707   target.  We just got a new candidate, insert it at the right spot or
     708   discard it. */
     709
     710static int
     711insert_search_node(unsigned char *id, struct sockaddr_in *sin,
     712                   struct search *sr, int replied,
     713                   unsigned char *token, int token_len)
     714{
     715    int bits = common_bits(id, sr->id);
     716    struct search_node *n;
     717    int i, j;
     718
     719    for(i = 0; i < sr->numnodes; i++) {
     720        if(id_cmp(id, sr->nodes[i].id) == 0) {
     721            n = &sr->nodes[i];
     722            goto found;
     723        }
     724        if(common_bits(sr->id, sr->nodes[i].id) < bits)
     725            break;
     726    }
     727
     728    if(i == SEARCH_NODES)
     729        return 0;
     730
     731    if(sr->numnodes < SEARCH_NODES)
     732        sr->numnodes++;
     733
     734    for(j = sr->numnodes - 1; j > i; j--) {
     735        sr->nodes[j] = sr->nodes[j - 1];
     736    }
     737
     738    n = &sr->nodes[i];
     739
     740    memset(n, 0, sizeof(struct search_node));
     741    memcpy(n->id, id, 20);
     742
     743found:
     744    n->sin = *sin;
     745
     746    if(replied) {
     747        n->replied = 1;
     748        n->reply_time = now.tv_sec;
     749        n->request_time = 0;
     750        n->pinged = 0;
     751    }
     752    if(token) {
     753        if(token_len >= 40) {
     754            debugf("Eek!  Overlong token.\n");
     755        } else {
     756            memcpy(n->token, token, token_len);
     757            n->token_len = token_len;
     758        }
     759    }
     760
     761    return 1;
     762}
     763
     764static void
     765flush_search_node(struct search_node *n, struct search *sr)
     766{
     767    int i = n - sr->nodes, j;
     768    for(j = i; j < sr->numnodes - 1; j++)
     769        sr->nodes[j] = sr->nodes[j + 1];
     770    sr->numnodes--;
     771}
     772
     773/* This must always return 0 or 1, never -1, not even on failure (see below). */
     774static int
     775search_send_get_peers(int s, struct search *sr, struct search_node *n)
     776{
     777    struct node *node;
     778    unsigned char tid[4];
     779
     780    if(n == NULL) {
     781        int i;
     782        for(i = 0; i < sr->numnodes; i++) {
     783            if(sr->nodes[i].pinged < 3 && !sr->nodes[i].replied &&
     784               sr->nodes[i].request_time < now.tv_sec - 15)
     785                n = &sr->nodes[i];
     786        }
     787    }
     788
     789    if(!n || n->pinged >= 3 || n->replied ||
     790       n->request_time >= now.tv_sec - 15)
     791        return 0;
     792
     793    debugf("Sending get_peers.\n");
     794    make_tid(tid, "gp", sr->tid);
     795    send_get_peers(s, (struct sockaddr*)&n->sin,
     796                   sizeof(struct sockaddr_in),
     797                   tid, 4, sr->id, sr->tid,
     798                   n->reply_time >= now.tv_sec - 15);
     799    n->pinged++;
     800    n->request_time = now.tv_sec;
     801    /* If the node happens to be in our main routing table, mark it
     802       as pinged. */
     803    node = find_node(n->id);
     804    if(node) pinged(s, node, NULL);
     805    return 1;
     806}
     807
     808/* When a search is in progress, we periodically call search_step to send
     809   further requests. */
     810static void
     811search_step(int s, struct search *sr, dht_callback *callback, void *closure)
     812{
     813    int i, j;
     814    int all_done = 1;
     815
     816    /* Check if the first 8 live nodes have replied. */
     817    j = 0;
     818    for(i = 0; i < sr->numnodes && j < 8; i++) {
     819        struct search_node *n = &sr->nodes[i];
     820        if(n->pinged >= 3)
     821            continue;
     822        if(!n->replied) {
     823            all_done = 0;
     824            break;
     825        }
     826        j++;
     827    }
     828
     829    if(all_done) {
     830        if(sr->port == 0) {
     831            goto done;
     832        } else {
     833            int all_acked = 1;
     834            j = 0;
     835            for(i = 0; i < sr->numnodes && j < 8; i++) {
     836                struct search_node *n = &sr->nodes[i];
     837                struct node *node;
     838                unsigned char tid[4];
     839                if(n->pinged >= 3)
     840                    continue;
     841                if(!n->acked) {
     842                    all_acked = 0;
     843                    debugf("Sending announce_peer.\n");
     844                    make_tid(tid, "ap", sr->tid);
     845                    send_announce_peer(s,
     846                                       (struct sockaddr*)&n->sin,
     847                                       sizeof(struct sockaddr_in),
     848                                       tid, 4, sr->id, sr->port,
     849                                       n->token, n->token_len,
     850                                       n->reply_time >= now.tv_sec - 15);
     851                    n->pinged++;
     852                    n->request_time = now.tv_sec;
     853                    node = find_node(n->id);
     854                    if(node) pinged(s, node, NULL);
     855                }
     856                j++;
     857            }
     858            if(all_acked)
     859                goto done;
     860        }
     861        sr->step_time = now.tv_sec;
     862        return;
     863    }
     864
     865    if(sr->step_time + 15 >= now.tv_sec)
     866        return;
     867
     868    j = 0;
     869    for(i = 0; i < sr->numnodes; i++) {
     870        j += search_send_get_peers(s, sr, &sr->nodes[i]);
     871        if(j >= 3)
     872            break;
     873    }
     874    sr->step_time = now.tv_sec;
     875    return;
     876
     877 done:
     878    sr->done = 1;
     879    if(callback)
     880        (*callback)(closure, DHT_EVENT_SEARCH_DONE, sr->id, NULL, 0);
     881    sr->step_time = now.tv_sec;
     882}
     883
     884static struct search *
     885find_free_search_slot(void)
     886{
     887    int i;
     888    struct search *sr = NULL;
     889
     890    if(numsearches < DHT_MAX_SEARCHES)
     891        return &searches[numsearches++];
     892
     893    for(i = 0; i < numsearches; i++) {
     894        if(searches[i].done &&
     895           (sr == NULL || searches[i].step_time < sr->step_time))
     896            sr = &searches[i];
     897    }
     898    return sr;
     899}
     900
     901/* Insert the contents of a bucket into a search structure. */
     902static void
     903insert_search_bucket(struct bucket *b, struct search *sr)
     904{
     905    struct node *n;
     906    n = b->nodes;
     907    while(n) {
     908        insert_search_node(n->id, &n->sin, sr, 0, NULL, 0);
     909        n = n->next;
     910    }
     911}
     912
     913/* Start a search.  If port is non-zero, perform an announce when the
     914   search is complete. */
     915int
     916dht_search(int s, const unsigned char *id, int port,
     917           dht_callback *callback, void *closure)
     918{
     919    struct search *sr;
     920    struct bucket *b;
     921    int i;
     922
     923    for(i = 0; i < numsearches; i++) {
     924        if(id_cmp(searches[i].id, id) == 0)
     925            break;
     926    }
     927
     928    if(i < numsearches) {
     929        /* We're reusing data from an old search.  Reusing the same tid
     930           means that we can merge replies for both searches. */
     931        int j;
     932        sr = searches + i;
     933        sr->done = 0;
     934    again:
     935        for(j = 0; j < sr->numnodes; j++) {
     936            struct search_node *n;
     937            n = &sr->nodes[j];
     938            /* Discard any doubtful nodes. */
     939            if(n->pinged >= 3 || n->reply_time < now.tv_sec - 7200) {
     940                flush_search_node(n, sr);
     941                goto again;
     942            }
     943            n->pinged = 0;
     944            n->token_len = 0;
     945            n->replied = 0;
     946            n->acked = 0;
     947        }
     948    } else {
     949        sr = find_free_search_slot();
     950        if(sr == NULL) {
     951            errno = ENOSPC;
     952            return -1;
     953        }
     954        memset(sr, 0, sizeof(struct search));
     955        sr->tid = search_id++;
     956        memcpy(sr->id, id, 20);
     957        sr->numnodes = 0;
     958    }
     959
     960    sr->port = port;
     961
     962    b = find_bucket(id);
     963    insert_search_bucket(b, sr);
     964
     965    if(sr->numnodes < 8) {
     966        struct bucket *p = previous_bucket(b);
     967        if(b->next)
     968            insert_search_bucket(b->next, sr);
     969        if(p)
     970            insert_search_bucket(p, sr);
     971    }
     972    if(sr->numnodes < SEARCH_NODES)
     973        insert_search_bucket(find_bucket(myid), sr);
     974
     975    search_step(s, sr, callback, closure);
     976    search_time = now.tv_sec;
     977    return 1;
     978}
     979
     980/* A struct storage stores all the stored peer addresses for a given info
     981   hash. */
     982
     983static struct storage *
     984find_storage(const unsigned char *id)
     985{
     986    struct storage *st = storage;
     987
     988    while(st) {
     989        if(id_cmp(id, st->id) == 0)
     990            break;
     991        st = st->next;
     992    }
     993    return st;
     994}
     995
     996static int
     997storage_store(const unsigned char *id, const unsigned char *ip,
     998              unsigned short port)
     999{
     1000    int i;
     1001    struct storage *st = storage;
     1002
     1003    st = find_storage(id);
     1004
     1005    if(st == NULL) {
     1006        st = calloc(1, sizeof(struct storage));
     1007        if(st == NULL) return -1;
     1008        memcpy(st->id, id, 20);
     1009        st->next = storage;
     1010        storage = st;
     1011    }
     1012
     1013    for(i = 0; i < st->numpeers; i++) {
     1014        if(st->peers[i].port == port && memcmp(st->peers[i].ip, ip, 4) == 0)
     1015            break;
     1016    }
     1017    if(i < st->numpeers) {
     1018        /* Already there, only need to refresh */
     1019        st->peers[i].time = now.tv_sec;
     1020        return 0;
     1021    } else {
     1022        struct peer *p;
     1023        if(i >= st->maxpeers) {
     1024            /* Need to expand the array. */
     1025            int n;
     1026            struct peer *new_peers;
     1027            if(st->maxpeers > DHT_MAX_PEERS / 2)
     1028                return 0;
     1029            n = st->maxpeers == 0 ? 2 : 2 * st->maxpeers;
     1030            new_peers = realloc(st->peers, n * sizeof(struct peer));
     1031            if(new_peers == NULL)
     1032                return -1;
     1033            st->peers = new_peers;
     1034            st->maxpeers = n;
     1035        }
     1036        p = &st->peers[st->numpeers++];
     1037        p->time = now.tv_sec;
     1038        memcpy(p->ip, ip, 4);
     1039        p->port = port;
     1040        return 1;
     1041    }
     1042}
     1043
     1044static int
     1045expire_storage( void )
     1046{
     1047    struct storage *st = storage, *previous = NULL;
     1048    while(st) {
     1049        int i = 0;
     1050        while(i < st->numpeers) {
     1051            if(st->peers[i].time < now.tv_sec - 32 * 60) {
     1052                if(i != st->numpeers - 1)
     1053                    st->peers[i] = st->peers[st->numpeers - 1];
     1054                st->numpeers--;
     1055            } else {
     1056                i++;
     1057            }
     1058        }
     1059
     1060        if(st->numpeers == 0) {
     1061            free(st->peers);
     1062            if(previous)
     1063                previous->next = st->next;
     1064            else
     1065                storage = st->next;
     1066            free(st);
     1067            if(previous)
     1068                st = previous->next;
     1069            else
     1070                st = storage;
     1071        } else {
     1072            previous = st;
     1073            st = st->next;
     1074        }
     1075    }
     1076    return 1;
     1077}
     1078
     1079/* We've just found out that a node is buggy. */
     1080static void
     1081broken_node(int s, const unsigned char *id, struct sockaddr_in *sin)
     1082{
     1083    int i, j;
     1084
     1085    debugf("Blacklisting broken node.\n");
     1086
     1087    if(id) {
     1088        /* Make the node easy to discard. */
     1089        struct node *n;
     1090        n = find_node(id);
     1091        if(n) {
     1092            n->pinged = 3;
     1093            pinged(s, n, NULL);
     1094        }
     1095        /* Discard it from any searches in progress. */
     1096        for(i = 0; i < numsearches; i++) {
     1097            for(j = 0; j < searches[i].numnodes; j++)
     1098                if(id_cmp(searches[i].nodes[j].id, id) == 0)
     1099                    flush_search_node(&searches[i].nodes[j],
     1100                                      &searches[i]);
     1101        }
     1102    }
     1103    /* And make sure we don't hear from it again. */
     1104    blacklist[next_blacklisted] = *sin;
     1105    next_blacklisted = (next_blacklisted + 1) % DHT_MAX_BLACKLISTED;
     1106}
     1107
     1108static int
     1109rotate_secrets( void )
     1110{
     1111    int fd;
     1112    unsigned seed;
     1113
     1114    fd = open("/dev/urandom", O_RDONLY);
     1115    if(fd < 0)
     1116        return -1;
     1117
     1118    memcpy(oldsecret, secret, sizeof(secret));
     1119    read(fd, secret, sizeof(secret));
     1120
     1121    read(fd, &seed, sizeof(seed));
     1122    srandom(seed);
     1123
     1124    close(fd);
     1125    rotate_secrets_time = now.tv_sec + 900 + random() % 1800;
     1126    return 1;
     1127}
     1128
     1129#ifndef TOKEN_SIZE
     1130#define TOKEN_SIZE 8
     1131#endif
     1132
     1133static void
     1134make_token(const unsigned char *ipv4, unsigned short port, int old,
     1135           unsigned char *token_return)
     1136{
     1137    dht_hash(token_return, TOKEN_SIZE,
     1138             old ? oldsecret : secret, sizeof(secret),
     1139             ipv4, 4,
     1140             (unsigned char*)&port, 2);
     1141}
     1142static int
     1143token_match(unsigned char *token, int token_len,
     1144            const unsigned char *ipv4, unsigned short port)
     1145{
     1146    unsigned char t[TOKEN_SIZE];
     1147    if(token_len != TOKEN_SIZE)
     1148        return 0;
     1149    make_token(ipv4, port, 0, t);
     1150    if(memcmp(t, token, TOKEN_SIZE) == 0)
     1151        return 1;
     1152    make_token(ipv4, port, 1, t);
     1153    if(memcmp(t, token, TOKEN_SIZE) == 0)
     1154        return 1;
     1155    return 0;
     1156}
     1157
     1158int
     1159dht_nodes(int *good_return, int *dubious_return, int *cached_return,
     1160          int *incoming_return)
     1161{
     1162    int good = 0, dubious = 0, cached = 0, incoming = 0;
     1163    struct bucket *b = buckets;
     1164    while(b) {
     1165        struct node *n = b->nodes;
     1166        while(n) {
     1167            if(node_good(n)) {
     1168                good++;
     1169                if(n->time > n->reply_time)
     1170                    incoming++;
     1171            } else {
     1172                dubious++;
     1173            }
     1174            n = n->next;
     1175        }
     1176        if(b->cached.sin_family == AF_INET)
     1177            cached++;
     1178        b = b->next;
     1179    }
     1180    if(good_return)
     1181        *good_return = good;
     1182    if(dubious_return)
     1183        *dubious_return = dubious;
     1184    if(cached_return)
     1185        *cached_return = cached;
     1186    if(incoming_return)
     1187        *incoming_return = cached;
     1188    return good + dubious;
     1189}
     1190               
     1191
     1192void
     1193dht_dump_tables(FILE *f)
     1194{
     1195    int i, j;
     1196    struct bucket *b = buckets;
     1197    struct storage *st = storage;
     1198
     1199    fprintf(f, "My id ");
     1200    print_hex(f, myid, 20);
     1201    fprintf(f, "\n");
     1202    while(b) {
     1203        struct node *n = b->nodes;
     1204        fprintf(f, "Bucket ");
     1205        print_hex(f, b->first, 20);
     1206        fprintf(f, " count %d age %d%s%s:\n",
     1207               b->count, (int)(now.tv_sec - b->time),
     1208               in_bucket(myid, b) ? " (mine)" : "",
     1209               b->cached.sin_family ? " (cached)" : "");
     1210        while(n) {
     1211            char buf[512];
     1212            fprintf(f, "    Node ");
     1213            print_hex(f, n->id, 20);
     1214            inet_ntop(AF_INET, &n->sin.sin_addr, buf, 512);
     1215            fprintf(f, " %s:%d ", buf, ntohs(n->sin.sin_port));
     1216            if(n->time != n->reply_time)
     1217                fprintf(f, "age %ld, %ld",
     1218                       (long)(now.tv_sec - n->time),
     1219                       (long)(now.tv_sec - n->reply_time));
     1220            else
     1221                fprintf(f, "age %ld", (long)(now.tv_sec - n->time));
     1222            if(n->pinged)
     1223                fprintf(f, " (%d)", n->pinged);
     1224            if(node_good(n))
     1225                fprintf(f, " (good)");
     1226            fprintf(f, "\n");
     1227            n = n->next;
     1228        }
     1229        b = b->next;
     1230    }
     1231    for(i = 0; i < numsearches; i++) {
     1232        struct search *sr = &searches[i];
     1233        fprintf(f, "\nSearch %d id ", i);
     1234        print_hex(f, sr->id, 20);
     1235        fprintf(f, " age %d%s\n", (int)(now.tv_sec - sr->step_time),
     1236               sr->done ? " (done)" : "");
     1237        for(j = 0; j < sr->numnodes; j++) {
     1238            struct search_node *n = &sr->nodes[j];
     1239            fprintf(f, "Node %d id ", j);
     1240            print_hex(f, n->id, 20);
     1241            fprintf(f, " bits %d age ", common_bits(sr->id, n->id));
     1242            if(n->request_time)
     1243                fprintf(f, "%d, ", (int)(now.tv_sec - n->request_time));
     1244            fprintf(f, "%d", (int)(now.tv_sec - n->reply_time));
     1245            if(n->pinged)
     1246                fprintf(f, " (%d)", n->pinged);
     1247            fprintf(f, "%s%s.\n",
     1248                   find_node(n->id) ? " (known)" : "",
     1249                   n->replied ? " (replied)" : "");
     1250        }
     1251    }
     1252
     1253   
     1254    while(st) {
     1255        fprintf(f, "\nStorage ");
     1256        print_hex(f, st->id, 20);
     1257        fprintf(f, " %d/%d nodes:", st->numpeers, st->maxpeers);
     1258        for(i = 0; i < st->numpeers; i++) {
     1259            char buf[20];
     1260            inet_ntop(AF_INET, st->peers[i].ip, buf, 20);
     1261            fprintf(f, " %s:%u (%ld)",
     1262                    buf, st->peers[i].port,
     1263                    (long)(now.tv_sec - st->peers[i].time));
     1264        }
     1265        st = st->next;
     1266    }
     1267   
     1268    fprintf(f, "\n\n");
     1269    fflush(f);
     1270}
     1271
     1272int
     1273dht_init(int s, const unsigned char *id)
     1274{
     1275    int rc;
     1276
     1277    if(buckets) {
     1278        errno = EBUSY;
     1279        return -1;
     1280    }
     1281
     1282    buckets = calloc(sizeof(struct bucket), 1);
     1283    if(buckets == NULL)
     1284        return -1;
     1285
     1286    numsearches = 0;
     1287
     1288    storage = NULL;
     1289
     1290    rc = fcntl(s, F_GETFL, 0);
     1291    if(rc < 0)
     1292        return -1;
     1293
     1294    rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
     1295    if(rc < 0)
     1296        return -1;
     1297
     1298    memcpy(myid, id, 20);
     1299
     1300    gettimeofday(&now, NULL);
     1301
     1302    mybucket_grow_time = now.tv_sec;
     1303    confirm_nodes_time = now.tv_sec + random() % 3;
     1304
     1305    search_id = random() & 0xFFFF;
     1306    search_time = 0;
     1307
     1308    next_blacklisted = 0;
     1309
     1310    leaky_bucket_time = now.tv_sec;
     1311    leaky_bucket_tokens = MAX_LEAKY_BUCKET_TOKENS;
     1312
     1313    memset(secret, 0, sizeof(secret));
     1314    rotate_secrets();
     1315    expire_buckets(s);
     1316
     1317    return 1;
     1318}
     1319
     1320int
     1321dht_uninit(int s, int dofree)
     1322{
     1323    if(!dofree)
     1324        return 1;
     1325
     1326    while(buckets) {
     1327        struct bucket *b = buckets;
     1328        buckets = b->next;
     1329        while(b->nodes) {
     1330            struct node *n = b->nodes;
     1331            b->nodes = n->next;
     1332            free(n);
     1333        }
     1334        free(b);
     1335    }
     1336
     1337    while(storage) {
     1338        struct storage *st = storage;
     1339        storage = storage->next;
     1340        free(st->peers);
     1341        free(st);
     1342    }
     1343   
     1344    return 1;
     1345}
     1346
     1347/* Rate control for requests we receive. */
     1348
     1349static int
     1350leaky_bucket( void )
     1351{
     1352    if(leaky_bucket_tokens == 0) {
     1353        leaky_bucket_tokens = MIN(MAX_LEAKY_BUCKET_TOKENS,
     1354                                  2 * (now.tv_sec - leaky_bucket_time));
     1355        leaky_bucket_time = now.tv_sec;
     1356    }
     1357
     1358    if(leaky_bucket_tokens == 0)
     1359        return 0;
     1360
     1361    leaky_bucket_tokens--;
     1362    return 1;
     1363}
     1364
     1365int
     1366dht_periodic(int s, int available, time_t *tosleep,
     1367             dht_callback *callback, void *closure)
     1368{
     1369    gettimeofday(&now, NULL);
     1370
     1371    if(available) {
     1372        int rc, i, message;
     1373        unsigned char tid[16], id[20], info_hash[20], target[20];
     1374        unsigned char buf[1024], nodes[256], token[128];
     1375        int tid_len = 16, token_len = 128;
     1376        int nodes_len = 256;
     1377        unsigned short port;
     1378        unsigned char values[2048];
     1379        int values_len = 2048;
     1380        struct sockaddr_in source;
     1381        socklen_t source_len = sizeof(struct sockaddr_in);
     1382        unsigned short ttid;
     1383
     1384        rc = recvfrom(s, buf, 1024, 0,
     1385                      (struct sockaddr*)&source, &source_len);
     1386        if(rc < 0) {
     1387            if(errno == EAGAIN)
     1388                goto dontread;
     1389            else
     1390                return rc;
     1391        }
     1392
     1393        if(source_len != sizeof(struct sockaddr_in)) {
     1394            /* Hmm... somebody gave us an IPv6 socket. */
     1395            errno = EINVAL;
     1396            return -1;
     1397        }
     1398
     1399        for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
     1400            if(blacklist[i].sin_family == AF_INET &&
     1401               blacklist[i].sin_port == source.sin_port &&
     1402               memcmp(&blacklist[i].sin_addr, &source.sin_addr, 4) == 0) {
     1403                debugf("Received packet from blacklisted node.\n");
     1404                goto dontread;
     1405            }
     1406        }
     1407
     1408        message = parse_message(buf, rc, tid, &tid_len, id, info_hash,
     1409                                target, &port, token, &token_len,
     1410                                nodes, &nodes_len, values, &values_len);
     1411        if(id_cmp(id, zeroes) == 0) {
     1412            debugf("Message with no id: ");
     1413            debug_printable(buf, rc);
     1414            debugf("\n");
     1415            goto dontread;
     1416        }
     1417
     1418        if(id_cmp(id, myid) == 0) {
     1419            debugf("Received message from self.\n");
     1420            goto dontread;
     1421        }
     1422
     1423        if(message > REPLY) {
     1424            /* Rate limit requests. */
     1425            if(!leaky_bucket()) {
     1426                debugf("Dropping request due to rate limiting.\n");
     1427                goto dontread;
     1428            }
     1429        }
     1430
     1431        switch(message) {
     1432        case REPLY:
     1433            if(tid_len != 4) {
     1434                debugf("Broken node truncates transaction ids: ");
     1435                debug_printable(buf, rc);
     1436                printf("\n");
     1437                /* This is really annoying, as it means that we will
     1438                   time-out all our searches that go through this node.
     1439                   Kill it. */
     1440                broken_node(s, id, &source);
     1441                goto dontread;
     1442            }
     1443            if(tid_match(tid, "pn", NULL)) {
     1444                debugf("Pong!\n");
     1445                new_node(s, id, &source, 2);
     1446            } else if(tid_match(tid, "fn", NULL) ||
     1447                      tid_match(tid, "gp", NULL)) {
     1448                int gp = 0;
     1449                struct search *sr = NULL;
     1450                if(tid_match(tid, "gp", &ttid)) {
     1451                    gp = 1;
     1452                    sr = find_search(ttid);
     1453                }
     1454                debugf("Nodes found (%d)%s!\n", nodes_len / 26,
     1455                       gp ? " for get_peers" : "");
     1456                if(nodes_len % 26 != 0) {
     1457                    debugf("Unexpected length for node info!\n");
     1458                    broken_node(s, id, &source);
     1459                } else if(gp && sr == NULL) {
     1460                    debugf("Unknown search!\n");
     1461                    new_node(s, id, &source, 1);
     1462                } else {
     1463                    int i;
     1464                    new_node(s, id, &source, 2);
     1465                    for(i = 0; i < nodes_len / 26; i++) {
     1466                        unsigned char *ni = nodes + i * 26;
     1467                        struct sockaddr_in sin;
     1468                        if(id_cmp(ni, myid) == 0)
     1469                            continue;
     1470                        memset(&sin, 0, sizeof(sin));
     1471                        sin.sin_family = AF_INET;
     1472                        memcpy(&sin.sin_addr, ni + 20, 4);
     1473                        memcpy(&sin.sin_port, ni + 24, 2);
     1474                        new_node(s, ni, &sin, 0);
     1475                        if(sr) {
     1476                            insert_search_node(ni, &sin, sr, 0, NULL, 0);
     1477                        }
     1478                    }
     1479                    if(sr)
     1480                        /* Since we received a reply, the number of
     1481                           requests in flight has decreased.  Let's push
     1482                           another request. */
     1483                        search_send_get_peers(s, sr, NULL);
     1484                }
     1485                if(sr) {
     1486                    insert_search_node(id, &source, sr,
     1487                                       1, token, token_len);
     1488                    if(values_len > 0) {
     1489                        debugf("Got values (%d)!\n", values_len / 6);
     1490                        if(callback) {
     1491                            (*callback)(closure, DHT_EVENT_VALUES,
     1492                                        sr->id, (void*)values, values_len);
     1493                        }
     1494                    }
     1495                }
     1496            } else if(tid_match(tid, "ap", &ttid)) {
     1497                struct search *sr;
     1498                debugf("Got reply to announce_peer.\n");
     1499                sr = find_search(ttid);
     1500                if(!sr) {
     1501                    debugf("Unknown search!");
     1502                    new_node(s, id, &source, 1);
     1503                } else {
     1504                    int i;
     1505                    new_node(s, id, &source, 2);
     1506                    for(i = 0; i < sr->numnodes; i++)
     1507                        if(id_cmp(sr->nodes[i].id, id) == 0) {
     1508                            sr->nodes[i].request_time = 0;
     1509                            sr->nodes[i].reply_time = now.tv_sec;
     1510                            sr->nodes[i].acked = 1;
     1511                            sr->nodes[i].pinged = 0;
     1512                            break;
     1513                        }
     1514                    /* See comment for gp above. */
     1515                    search_send_get_peers(s, sr, NULL);
     1516                }
     1517            } else {
     1518                debugf("Unexpected reply: ");
     1519                debug_printable(buf, rc);
     1520                debugf("\n");
     1521            }
     1522            break;
     1523        case PING:
     1524            debugf("Ping (%d)!\n", tid_len);
     1525            new_node(s, id, &source, 1);
     1526            debugf("Sending pong!\n");
     1527            send_pong(s, (struct sockaddr*)&source, sizeof(source),
     1528                      tid, tid_len);
     1529            break;
     1530        case FIND_NODE:
     1531            debugf("Find node!\n");
     1532            new_node(s, id, &source, 1);
     1533            {
     1534                struct bucket *b = find_bucket(target);
     1535                if(b) {
     1536                    debugf("Sending nodes from bucket.\n");
     1537                    send_bucket_nodes(s,
     1538                                      (struct sockaddr*)&source,
     1539                                      sizeof(source),
     1540                                      tid, tid_len, b, NULL, 0);
     1541                }
     1542            }
     1543            break;
     1544        case GET_PEERS:
     1545            debugf("Get_peers!\n");
     1546            new_node(s, id, &source, 1);
     1547            if(id_cmp(info_hash, zeroes) == 0) {
     1548                debugf("Eek!  Got get_peers with no info_hash.\n");
     1549                break;
     1550            } else {
     1551                struct storage *st = find_storage(info_hash);
     1552                if(st && st->numpeers > 0) {
     1553                    int i0, n0, n1;
     1554                    unsigned char token[TOKEN_SIZE];
     1555                    make_token((unsigned char*)&source.sin_addr,
     1556                               ntohs(source.sin_port),
     1557                               0, token);
     1558                    i0 = random() % st->numpeers;
     1559                    /* We treat peers as a circular list, and choose 50
     1560                       peers starting at i0. */
     1561                    n0 = MIN(st->numpeers - i0, 50);
     1562                    n1 = n0 >= 50 ? 0 : MIN(50, i0);
     1563
     1564                    debugf("Sending found peers (%d).\n", n0 + n1);
     1565                    send_peers_found(s, (struct sockaddr*)&source,
     1566                                     sizeof(source), tid, tid_len,
     1567                                     st->peers + i0, n0,
     1568                                     st->peers, n1,
     1569                                     token, TOKEN_SIZE);
     1570
     1571                } else {
     1572                    struct bucket *b = find_bucket(info_hash);
     1573                    if(b) {
     1574                        unsigned char token[TOKEN_SIZE];
     1575                        make_token((unsigned char*)&source.sin_addr,
     1576                                   ntohs(source.sin_port),
     1577                                   0, token);
     1578                        debugf("Sending nodes for get_peers.\n");
     1579                        send_bucket_nodes(s, (struct sockaddr*)&source,
     1580                                          sizeof(source),
     1581                                          tid, tid_len, b,
     1582                                          token, TOKEN_SIZE);
     1583                    }
     1584                }
     1585            }
     1586            break;
     1587        case ANNOUNCE_PEER:
     1588            debugf("Announce peer!\n");
     1589            new_node(s, id, &source, 1);
     1590            if(id_cmp(info_hash, zeroes) == 0) {
     1591                debugf("Announce_peer with no info_hash.\n");
     1592                break;
     1593            }
     1594            if(!token_match(token, token_len,
     1595                            (unsigned char*)&source.sin_addr,
     1596                            ntohs(source.sin_port))) {
     1597                debugf("Incorrect token for announce_peer.\n");
     1598                break;
     1599            }
     1600            if(port == 0) {
     1601                debugf("Announce_peer with forbidden port %d.\n", port);
     1602                break;
     1603            }
     1604            storage_store(info_hash,
     1605                          (unsigned char*)&source.sin_addr, port);
     1606            debugf("Sending peer announced.\n");
     1607            send_peer_announced(s, (struct sockaddr*)&source,
     1608                                sizeof(source), tid, tid_len);
     1609        }
     1610    }
     1611
     1612 dontread:
     1613    if(now.tv_sec >= rotate_secrets_time)
     1614        rotate_secrets();
     1615
     1616    if(now.tv_sec >= expire_stuff_time) {
     1617        expire_buckets(s);
     1618        expire_storage();
     1619    }
     1620
     1621    if(search_time > 0 && now.tv_sec >= search_time) {
     1622        int i;
     1623        for(i = 0; i < numsearches; i++) {
     1624            struct search *sr = &searches[i];
     1625            if(!sr->done && sr->step_time + 5 <= now.tv_sec) {
     1626                search_step(s, sr, callback, closure);
     1627            }
     1628        }
     1629                   
     1630        search_time = 0;
     1631       
     1632        for(i = 0; i < numsearches; i++) {
     1633            struct search *sr = &searches[i];
     1634            if(!sr->done) {
     1635                time_t tm = sr->step_time + 15 + random() % 10;
     1636                if(search_time == 0 || search_time > tm)
     1637                    search_time = tm;
     1638            }
     1639        }
     1640    }
     1641
     1642    if(now.tv_sec >= confirm_nodes_time) {
     1643        struct bucket *b;
     1644        int soon = 0;
     1645        b = buckets;
     1646        while(!soon && b) {
     1647            struct bucket *q;
     1648            if(b->time < now.tv_sec - 900) {
     1649                /* This bucket hasn't seen any activity for a long
     1650                   time.  Pick a random id in this bucket's range, and
     1651                   send a request to a random node. */
     1652                unsigned char id[20];
     1653                struct node *n;
     1654                int rc;
     1655               
     1656                rc = bucket_random(b, id);
     1657                if(rc < 0)
     1658                    memcpy(id, b->first, 20);
     1659               
     1660                q = b;
     1661                /* If the bucket is empty, we try to fill it from
     1662                   a neighbour.  We also sometimes do it gratuitiously
     1663                   to recover from buckets full of broken nodes. */
     1664                if(q->next && (q->count == 0 || random() % 7 == 0))
     1665                    q = b->next;
     1666                if(q->count == 0 || random() % 7 == 0) {
     1667                    struct bucket *r;
     1668                    r = previous_bucket(b);
     1669                    if(r && r->count > 0)
     1670                        q = r;
     1671                }
     1672
     1673                if(q) {
     1674                    n = random_node(q);
     1675                    if(n) {
     1676                        unsigned char tid[4];
     1677                        debugf("Sending find_node "
     1678                               "for bucket maintenance.\n");
     1679                        make_tid(tid, "fn", 0);
     1680                        send_find_node(s, (struct sockaddr*)&n->sin,
     1681                                       sizeof(struct sockaddr_in),
     1682                                       tid, 4, id,
     1683                                       n->reply_time >= now.tv_sec - 15);
     1684                        pinged(s, n, q);
     1685                        /* In order to avoid sending queries back-to-back,
     1686                           give up for now and reschedule us soon. */
     1687                        soon = 1;
     1688                    }
     1689                }
     1690            }
     1691            b = b->next;
     1692        }
     1693
     1694        if(!soon && mybucket_grow_time >= now.tv_sec - 150) {
     1695            /* We've seen updates to our own bucket recently.  Try to
     1696               improve our neighbourship. */
     1697            unsigned char id[20];
     1698            struct bucket *b, *q;
     1699            struct node *n;
     1700           
     1701            memcpy(id, myid, 20);
     1702            id[19] = random() % 0xFF;
     1703            b = find_bucket(myid);
     1704            q = b;
     1705            if(q->next && (q->count == 0 || random() % 7 == 0))
     1706                q = b->next;
     1707            if(q->count == 0 || random() % 7 == 0) {
     1708                struct bucket *r;
     1709                r = previous_bucket(b);
     1710                if(r && r->count > 0)
     1711                    q = r;
     1712            }
     1713
     1714            if(q) {
     1715                n = random_node(q);
     1716                if(n) {
     1717                    unsigned char tid[4];
     1718                    debugf("Sending find_node "
     1719                           "for neighborhood maintenance.\n");
     1720                    make_tid(tid, "fn", 0);
     1721                    send_find_node(s, (struct sockaddr*)&n->sin,
     1722                                   sizeof(struct sockaddr_in),
     1723                                   tid, 4, id,
     1724                                   n->reply_time >= now.tv_sec - 15);
     1725                    pinged(s, n, q);
     1726                }
     1727            }
     1728            soon = 1;
     1729        }
     1730
     1731        /* In order to maintain all buckets' age within 900 seconds, worst
     1732           case is roughly 40 seconds, assuming the table is 22 bits deep.
     1733           We want to keep a margin for neighborhood maintenance, so keep
     1734           this within 30 seconds. */
     1735        if(soon)
     1736            confirm_nodes_time = now.tv_sec + 10 + random() % 20;
     1737        else
     1738            confirm_nodes_time = now.tv_sec + 60 + random() % 120;
     1739    }
     1740
     1741    if(confirm_nodes_time > now.tv_sec)
     1742        *tosleep = confirm_nodes_time - now.tv_sec;
     1743    else
     1744        *tosleep = 0;
     1745
     1746    if(search_time > 0) {
     1747        if(search_time <= now.tv_sec)
     1748            *tosleep = 0;
     1749        else if(*tosleep > search_time - now.tv_sec)
     1750            *tosleep = search_time - now.tv_sec;
     1751    }
     1752   
     1753    return find_bucket(myid)->count > 2;
     1754}
     1755
     1756int
     1757dht_get_nodes(struct sockaddr_in *sins, int num)
     1758{
     1759    int i;
     1760    struct bucket *b;
     1761    struct node *n;
     1762
     1763    i = 0;
     1764
     1765    /* For restoring to work without discarding too many nodes, the list
     1766       must start with the contents of our bucket. */
     1767    b = find_bucket(myid);
     1768    n = b->nodes;
     1769    while(n && i < num) {
     1770        if(node_good(n)) {
     1771            sins[i] = n->sin;
     1772            i++;
     1773        }
     1774        n = n->next;
     1775    }
     1776
     1777    b = buckets;
     1778    while(b && i < num) {
     1779        if(!in_bucket(myid, b)) {
     1780            n = b->nodes;
     1781            while(n && i < num) {
     1782                if(node_good(n)) {
     1783                    sins[i] = n->sin;
     1784                    i++;
     1785                }
     1786                n = n->next;
     1787            }
     1788        }
     1789        b = b->next;
     1790    }
     1791    return i;
     1792}
     1793
     1794int
     1795dht_insert_node(int s, const unsigned char *id, struct sockaddr_in *sin)
     1796{
     1797    struct node *n;
     1798    n = new_node(s, id, sin, 0);
     1799    return !!n;
     1800}
     1801
     1802int
     1803dht_ping_node(int s, struct sockaddr_in *sin)
     1804{
     1805    unsigned char tid[4];
     1806    debugf("Sending ping.\n");
     1807    make_tid(tid, "pn", 0);
     1808    return send_ping(s, (struct sockaddr*)sin, sizeof(struct sockaddr_in),
     1809                     tid, 4);
     1810}
     1811
     1812/* We could use a proper bencoding printer and parser, but the format of
     1813   DHT messages is fairly stylised, so this seemed simpler. */
     1814
     1815#define CHECK(offset, delta, size)                      \
     1816    if(delta < 0 || offset + delta > size) goto fail
     1817
     1818#define INC(offset, delta, size)                        \
     1819    CHECK(offset, delta, size);                         \
     1820    offset += delta
     1821
     1822#define COPY(buf, offset, src, delta, size)             \
     1823    CHECK(offset, delta, size);                         \
     1824    memcpy(buf + offset, src, delta);                   \
     1825    i += delta;
     1826
     1827int
     1828send_ping(int s, struct sockaddr *sa, int salen,
     1829          const unsigned char *tid, int tid_len)
     1830{
     1831    char buf[512];
     1832    int i = 0, rc;
     1833    rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
     1834    COPY(buf, i, myid, 20, 512);
     1835    rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
     1836    INC(i, rc, 512);
     1837    COPY(buf, i, tid, tid_len, 512);
     1838    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
     1839    return sendto(s, buf, i, 0, sa, salen);
     1840
     1841 fail:
     1842    errno = ENOSPC;
     1843    return -1;
     1844}
     1845
     1846int
     1847send_pong(int s, struct sockaddr *sa, int salen,
     1848          const unsigned char *tid, int tid_len)
     1849{
     1850    char buf[512];
     1851    int i = 0, rc;
     1852    rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
     1853    COPY(buf, i, myid, 20, 512);
     1854    rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
     1855    COPY(buf, i, tid, tid_len, 512);
     1856    rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
     1857    return sendto(s, buf, i, 0, sa, salen);
     1858
     1859 fail:
     1860    errno = ENOSPC;
     1861    return -1;
     1862}
     1863
     1864int
     1865send_find_node(int s, struct sockaddr *sa, int salen,
     1866               const unsigned char *tid, int tid_len,
     1867               const unsigned char *target, int confirm)
     1868{
     1869    char buf[512];
     1870    int i = 0, rc;
     1871    rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
     1872    COPY(buf, i, myid, 20, 512);
     1873    rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
     1874    COPY(buf, i, target, 20, 512);
     1875    rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
     1876    INC(i, rc, 512);
     1877    COPY(buf, i, tid, tid_len, 512);
     1878    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
     1879    return sendto(s, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
     1880
     1881 fail:
     1882    errno = ENOSPC;
     1883    return -1;
     1884}
     1885
     1886int
     1887send_found_nodes(int s, struct sockaddr *sa, int salen,
     1888                 const unsigned char *tid, int tid_len,
     1889                 const unsigned char *nodes, int nodes_len,
     1890                 const unsigned char *token, int token_len)
     1891{
     1892    char buf[2048];
     1893    int i = 0, rc;
     1894    rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
     1895    COPY(buf, i, myid, 20, 2048);
     1896    if(nodes) {
     1897        rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
     1898        INC(i, rc, 2048);
     1899        COPY(buf, i, nodes, nodes_len, 2048);
     1900    }
     1901    if(token) {
     1902        rc = snprintf(buf + i, 2048 - i, "5:token%d:", token_len);
     1903        INC(i, rc, 2048);
     1904        COPY(buf, i, token, token_len, 2048);
     1905    }
     1906    rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048);
     1907    COPY(buf, i, tid, tid_len, 2048);
     1908    rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
     1909
     1910    return sendto(s, buf, i, 0, sa, salen);
     1911
     1912 fail:
     1913    errno = ENOSPC;
     1914    return -1;
     1915}
     1916
     1917static int
     1918buffer_bucket(unsigned char *buf, int bufsize, struct bucket *b)
     1919{
     1920    int i = 0;
     1921    struct node *n = b->nodes;
     1922    while(n && i < bufsize - 26) {
     1923        if(node_good(n)) {
     1924            memcpy(buf + i, n->id, 20);
     1925            memcpy(buf + i + 20, &n->sin.sin_addr, 4);
     1926            memcpy(buf + i + 24, &n->sin.sin_port, 2);
     1927            i += 26;
     1928        }
     1929        n = n->next;
     1930    }
     1931    return i;
     1932}
     1933
     1934int
     1935send_bucket_nodes(int s, struct sockaddr *sa, int salen,
     1936                  const unsigned char *tid, int tid_len,
     1937                  struct bucket *b,
     1938                  const unsigned char *token, int token_len)
     1939{
     1940    unsigned char nodes[8 * 26];
     1941    int nodeslen = 0;
     1942
     1943    nodeslen = buffer_bucket(nodes, 8 * 26, b);
     1944    return send_found_nodes(s, sa, salen, tid, tid_len,
     1945                            nodes, nodeslen,
     1946                            token, token_len);
     1947}
     1948
     1949int
     1950send_get_peers(int s, struct sockaddr *sa, int salen,
     1951               unsigned char *tid, int tid_len,
     1952               unsigned char *infohash, unsigned short port, int confirm)
     1953{
     1954    char buf[512];
     1955    int i = 0, rc;
     1956
     1957    rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
     1958    COPY(buf, i, myid, 20, 512);
     1959    rc = snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512);
     1960    COPY(buf, i, infohash, 20, 512);
     1961    rc = snprintf(buf + i, 512 - i, "e1:q9:get_peers1:t%d:", tid_len);
     1962    INC(i, rc, 512);
     1963    COPY(buf, i, tid, tid_len, 512);
     1964    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
     1965    return sendto(s, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
     1966
     1967 fail:
     1968    errno = ENOSPC;
     1969    return -1;
     1970}
     1971
     1972int
     1973send_announce_peer(int s, struct sockaddr *sa, int salen,
     1974                   unsigned char *tid, int tid_len,
     1975                   unsigned char *infohash, unsigned short port,
     1976                   unsigned char *token, int token_len, int confirm)
     1977{
     1978    char buf[512];
     1979    int i = 0, rc;
     1980
     1981    rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
     1982    COPY(buf, i, myid, 20, 512);
     1983    rc = snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512);
     1984    COPY(buf, i, infohash, 20, 512);
     1985    rc = snprintf(buf + i, 512 - i, "4:porti%ue5:token%d:", (unsigned)port,
     1986                  token_len);
     1987    INC(i, rc, 512);
     1988    COPY(buf, i, token, token_len, 512);
     1989    rc = snprintf(buf + i, 512 - i, "e1:q13:announce_peer1:t%d:", tid_len);
     1990    INC(i, rc, 512);
     1991    COPY(buf, i, tid, tid_len, 512);
     1992    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
     1993
     1994    return sendto(s, buf, i, confirm ? 0 : MSG_CONFIRM, sa, salen);
     1995
     1996 fail:
     1997    errno = ENOSPC;
     1998    return -1;
     1999}
     2000
     2001int
     2002send_peers_found(int s, struct sockaddr *sa, int salen,
     2003                 unsigned char *tid, int tid_len,
     2004                 struct peer *peers1, int numpeers1,
     2005                 struct peer *peers2, int numpeers2,
     2006                 unsigned char *token, int token_len)
     2007{
     2008    char buf[1400];
     2009    int i = 0, rc, j;
     2010
     2011    rc = snprintf(buf + i, 1400 - i, "d1:rd2:id20:"); INC(i, rc, 1400);
     2012    COPY(buf, i, myid, 20, 1400);
     2013    rc = snprintf(buf + i, 1400 - i, "5:token%d:", token_len); INC(i, rc, 1400);
     2014    COPY(buf, i, token, token_len, 1400);
     2015    rc = snprintf(buf + i, 1400 - i, "6:valuesl"); INC(i, rc, 1400);
     2016    for(j = 0; j < numpeers1; j++) {
     2017        unsigned short swapped = htons(peers1[j].port);
     2018        rc = snprintf(buf + i, 1400 - i, "6:"); INC(i, rc, 1400);
     2019        COPY(buf, i, peers1[j].ip, 4, 1400);
     2020        COPY(buf, i, &swapped, 2, 1400);
     2021    }
     2022    for(j = 0; j < numpeers2; j++) {
     2023        unsigned short swapped = htons(peers2[j].port);
     2024        rc = snprintf(buf + i, 1400 - i, "6:"); INC(i, rc, 1400);
     2025        COPY(buf, i, peers2[j].ip, 4, 1400);
     2026        COPY(buf, i, &swapped, 2, 1400);
     2027    }
     2028    rc = snprintf(buf + i, 1400 - i, "ee1:t%d:", tid_len);
     2029    INC(i, rc, 1400);
     2030    COPY(buf, i, tid, tid_len, 1400);
     2031    rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
     2032    return sendto(s, buf, i, 0, sa, salen);
     2033
     2034 fail:
     2035    errno = ENOSPC;
     2036    return -1;
     2037}
     2038
     2039int
     2040send_peer_announced(int s, struct sockaddr *sa, int salen,
     2041                    unsigned char *tid, int tid_len)
     2042{
     2043    char buf[512];
     2044    int i = 0, rc;
     2045
     2046    rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
     2047    COPY(buf, i, myid, 20, 512);
     2048    rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
     2049    INC(i, rc, 512);
     2050    COPY(buf, i, tid, tid_len, 512);
     2051    rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
     2052    return sendto(s, buf, i, 0, sa, salen);
     2053
     2054 fail:
     2055    errno = ENOSPC;
     2056    return -1;
     2057}
     2058
     2059static int
     2060parse_message(const unsigned char *buf, int buflen,
     2061              unsigned char *tid_return, int *tid_len,
     2062              unsigned char *id_return, unsigned char *info_hash_return,
     2063              unsigned char *target_return, unsigned short *port_return,
     2064              unsigned char *token_return, int *token_len,
     2065              unsigned char *nodes_return, int *nodes_len,
     2066              const unsigned char *values_return, int *values_len)
     2067{
     2068    const unsigned char *p;
     2069
     2070    if(tid_return) {
     2071        p = memmem(buf, buflen, "1:t", 3);
     2072        if(p) {
     2073            long l;
     2074            char *q;
     2075            l = strtol((char*)p + 3, &q, 10);
     2076            if(q && *q == ':' && l > 0 && l < *tid_len) {
     2077                memcpy(tid_return, q + 1, l);
     2078                *tid_len = l;
     2079            } else
     2080                *tid_len = 0;
     2081        }
     2082    }
     2083    if(id_return) {
     2084        p = memmem(buf, buflen, "2:id20:", 7);
     2085        if(p) {
     2086            memcpy(id_return, p + 7, 20);
     2087        } else {
     2088            memset(id_return, 0, 20);
     2089        }
     2090    }
     2091    if(info_hash_return) {
     2092        p = memmem(buf, buflen, "9:info_hash20:", 14);
     2093        if(p) {
     2094            memcpy(info_hash_return, p + 14, 20);
     2095        } else {
     2096            memset(info_hash_return, 0, 20);
     2097        }
     2098    }
     2099    if(port_return) {
     2100        p = memmem(buf, buflen, "porti", 5);
     2101        if(p) {
     2102            long l;
     2103            char *q;
     2104            l = strtol((char*)p + 5, &q, 10);
     2105            if(q && *q == 'e' && l > 0 && l < 0x10000)
     2106                *port_return = l;
     2107            else
     2108                *port_return = 0;
     2109        } else
     2110            *port_return = 0;
     2111    }
     2112    if(target_return) {
     2113        p = memmem(buf, buflen, "6:target20:", 11);
     2114        if(p) {
     2115            memcpy(target_return, p + 11, 20);
     2116        } else {
     2117            memset(target_return, 0, 20);
     2118        }
     2119    }
     2120    if(token_return) {
     2121        p = memmem(buf, buflen, "5:token", 7);
     2122        if(p) {
     2123            long l;
     2124            char *q;
     2125            l = strtol((char*)p + 7, &q, 10);
     2126            if(q && *q == ':' && l > 0 && l < *token_len) {
     2127                memcpy(token_return, q + 1, l);
     2128                *token_len = l;
     2129            } else
     2130                *token_len = 0;
     2131        } else
     2132            *token_len = 0;
     2133    }
     2134       
     2135    if(nodes_return) {
     2136        p = memmem(buf, buflen, "5:nodes", 7);
     2137        if(p) {
     2138            long l;
     2139            char *q;
     2140            l = strtol((char*)p + 7, &q, 10);
     2141            if(q && *q == ':' && l > 0 && l < *nodes_len) {
     2142                memcpy(nodes_return, q + 1, l);
     2143                *nodes_len = l;
     2144            } else
     2145                *nodes_len = 0;
     2146        } else
     2147            *nodes_len = 0;
     2148    }
     2149
     2150    if(values_return) {
     2151        p = memmem(buf, buflen, "6:valuesl", 9);
     2152        if(p) {
     2153            int i = p - buf + 9;
     2154            int j = 0;
     2155            while(buf[i] == '6' && buf[i + 1] == ':' && i + 8 < buflen) {
     2156                if(j + 6 > *values_len)
     2157                    break;
     2158                memcpy((char*)values_return + j, buf + i + 2, 6);
     2159                i += 8;
     2160                j += 6;
     2161            }
     2162            if(buf[i] != 'e')
     2163                debugf("Eek... unexpected end for values.\n");
     2164            *values_len = j;
     2165        } else {
     2166            *values_len = 0;
     2167        }
     2168    }
     2169               
     2170    if(memmem(buf, buflen, "1:y1:r", 6))
     2171        return REPLY;
     2172    if(!memmem(buf, buflen, "1:y1:q", 6))
     2173        return -1;
     2174    if(memmem(buf, buflen, "1:q4:ping", 9))
     2175        return PING;
     2176    if(memmem(buf, buflen, "1:q9:find_node", 14))
     2177       return FIND_NODE;
     2178    if(memmem(buf, buflen, "1:q9:get_peers", 14))
     2179        return GET_PEERS;
     2180    if(memmem(buf, buflen, "1:q13:announce_peer", 19))
     2181       return ANNOUNCE_PEER;
     2182    return -1;
     2183}
  • third-party/dht/LICENCE

     
     1Copyright (c) 2009 by Juliusz Chroboczek
     2
     3Permission is hereby granted, free of charge, to any person obtaining a copy
     4of this software and associated documentation files (the "Software"), to deal
     5in the Software without restriction, including without limitation the rights
     6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7copies of the Software, and to permit persons to whom the Software is
     8furnished to do so, subject to the following conditions:
     9
     10The above copyright notice and this permission notice shall be included in
     11all copies or substantial portions of the Software.
     12
     13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     19THE SOFTWARE.
  • third-party/dht/Makefile.in

     
     1# Makefile.in generated by automake 1.9.6 from Makefile.am.
     2# @configure_input@
     3
     4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
     5# 2003, 2004, 2005  Free Software Foundation, Inc.
     6# This Makefile.in is free software; the Free Software Foundation
     7# gives unlimited permission to copy and/or distribute it,
     8# with or without modifications, as long as this notice is preserved.
     9
     10# This program is distributed in the hope that it will be useful,
     11# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
     12# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
     13# PARTICULAR PURPOSE.
     14
     15@SET_MAKE@
     16
     17
     18srcdir = @srcdir@
     19top_srcdir = @top_srcdir@
     20VPATH = @srcdir@
     21pkgdatadir = $(datadir)/@PACKAGE@
     22pkglibdir = $(libdir)/@PACKAGE@
     23pkgincludedir = $(includedir)/@PACKAGE@
     24top_builddir = ../..
     25am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
     26INSTALL = @INSTALL@
     27install_sh_DATA = $(install_sh) -c -m 644
     28install_sh_PROGRAM = $(install_sh) -c
     29install_sh_SCRIPT = $(install_sh) -c
     30INSTALL_HEADER = $(INSTALL_DATA)
     31transform = $(program_transform_name)
     32NORMAL_INSTALL = :
     33PRE_INSTALL = :
     34POST_INSTALL = :
     35NORMAL_UNINSTALL = :
     36PRE_UNINSTALL = :
     37POST_UNINSTALL = :
     38build_triplet = @build@
     39host_triplet = @host@
     40subdir = third-party/dht
     41DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \
     42        $(srcdir)/Makefile.in
     43ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
     44am__aclocal_m4_deps = $(top_srcdir)/m4/acx-pthread.m4 \
     45        $(top_srcdir)/m4/check-ssl.m4 $(top_srcdir)/m4/glib-gettext.m4 \
     46        $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/pkg.m4 \
     47        $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
     48am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
     49        $(ACLOCAL_M4)
     50mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
     51CONFIG_CLEAN_FILES =
     52LIBRARIES = $(noinst_LIBRARIES)
     53ARFLAGS = cru
     54libdht_a_AR = $(AR) $(ARFLAGS)
     55libdht_a_LIBADD =
     56am_libdht_a_OBJECTS = dht.$(OBJEXT)
     57libdht_a_OBJECTS = $(am_libdht_a_OBJECTS)
     58DEFAULT_INCLUDES = -I. -I$(srcdir)
     59depcomp = $(SHELL) $(top_srcdir)/depcomp
     60am__depfiles_maybe = depfiles
     61COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
     62        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
     63LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
     64        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
     65        $(AM_CFLAGS) $(CFLAGS)
     66CCLD = $(CC)
     67LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     68        $(AM_LDFLAGS) $(LDFLAGS) -o $@
     69SOURCES = $(libdht_a_SOURCES)
     70DIST_SOURCES = $(libdht_a_SOURCES)
     71HEADERS = $(noinst_HEADERS)
     72ETAGS = etags
     73CTAGS = ctags
     74DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
     75ACLOCAL = @ACLOCAL@
     76ALL_LINGUAS = @ALL_LINGUAS@
     77AMDEP_FALSE = @AMDEP_FALSE@
     78AMDEP_TRUE = @AMDEP_TRUE@
     79AMTAR = @AMTAR@
     80AR = @AR@
     81AUTOCONF = @AUTOCONF@
     82AUTOHEADER = @AUTOHEADER@
     83AUTOMAKE = @AUTOMAKE@
     84AWK = @AWK@
     85BUILD_CLI_FALSE = @BUILD_CLI_FALSE@
     86BUILD_CLI_TRUE = @BUILD_CLI_TRUE@
     87BUILD_DAEMON_FALSE = @BUILD_DAEMON_FALSE@
     88BUILD_DAEMON_TRUE = @BUILD_DAEMON_TRUE@
     89BUILD_GTK_FALSE = @BUILD_GTK_FALSE@
     90BUILD_GTK_TRUE = @BUILD_GTK_TRUE@
     91BUILD_MAC_FALSE = @BUILD_MAC_FALSE@
     92BUILD_MAC_TRUE = @BUILD_MAC_TRUE@
     93CATALOGS = @CATALOGS@
     94CATOBJEXT = @CATOBJEXT@
     95CC = @CC@
     96CCDEPMODE = @CCDEPMODE@
     97CFLAGS = @CFLAGS@
     98CPP = @CPP@
     99CPPFLAGS = @CPPFLAGS@
     100CURL_MINIMUM = @CURL_MINIMUM@
     101CXX = @CXX@
     102CXXCPP = @CXXCPP@
     103CXXDEPMODE = @CXXDEPMODE@
     104CXXFLAGS = @CXXFLAGS@
     105CYGPATH_W = @CYGPATH_W@
     106DATADIRNAME = @DATADIRNAME@
     107DBUS_BINDING_TOOL = @DBUS_BINDING_TOOL@
     108DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
     109DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
     110DBUS_GLIB_MINIMUM = @DBUS_GLIB_MINIMUM@
     111DEFS = @DEFS@
     112DEPDIR = @DEPDIR@
     113ECHO = @ECHO@
     114ECHO_C = @ECHO_C@
     115ECHO_N = @ECHO_N@
     116ECHO_T = @ECHO_T@
     117EGREP = @EGREP@
     118EXEEXT = @EXEEXT@
     119F77 = @F77@
     120FFLAGS = @FFLAGS@
     121GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
     122GIO_CFLAGS = @GIO_CFLAGS@
     123GIO_LIBS = @GIO_LIBS@
     124GIO_MINIMUM = @GIO_MINIMUM@
     125GLIB_MINIMUM = @GLIB_MINIMUM@
     126GMOFILES = @GMOFILES@
     127GMSGFMT = @GMSGFMT@
     128GTK_CFLAGS = @GTK_CFLAGS@
     129GTK_LIBS = @GTK_LIBS@
     130GTK_MINIMUM = @GTK_MINIMUM@
     131INSTALL_DATA = @INSTALL_DATA@
     132INSTALL_PROGRAM = @INSTALL_PROGRAM@
     133INSTALL_SCRIPT = @INSTALL_SCRIPT@
     134INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     135INSTOBJEXT = @INSTOBJEXT@
     136INTLLIBS = @INTLLIBS@
     137INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@
     138INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@
     139INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@
     140INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
     141INTLTOOL_ICONV = @INTLTOOL_ICONV@
     142INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@
     143INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@
     144INTLTOOL_MERGE = @INTLTOOL_MERGE@
     145INTLTOOL_MSGFMT = @INTLTOOL_MSGFMT@
     146INTLTOOL_MSGMERGE = @INTLTOOL_MSGMERGE@
     147INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@
     148INTLTOOL_PERL = @INTLTOOL_PERL@
     149INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@
     150INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@
     151INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@
     152INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@
     153INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@
     154INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@
     155INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@
     156INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@
     157INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@
     158INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
     159INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@
     160INTLTOOL_XGETTEXT = @INTLTOOL_XGETTEXT@
     161INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@
     162INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@
     163LDFLAGS = @LDFLAGS@
     164LIBCURL_CFLAGS = @LIBCURL_CFLAGS@
     165LIBCURL_LIBS = @LIBCURL_LIBS@
     166LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
     167LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
     168LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
     169LIBNOTIFY_MINIMUM = @LIBNOTIFY_MINIMUM@
     170LIBOBJS = @LIBOBJS@
     171LIBS = @LIBS@
     172LIBTOOL = @LIBTOOL@
     173LN_S = @LN_S@
     174LTLIBOBJS = @LTLIBOBJS@
     175MAKEINFO = @MAKEINFO@
     176MKINSTALLDIRS = @MKINSTALLDIRS@
     177MSGFMT = @MSGFMT@
     178OBJEXT = @OBJEXT@
     179OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
     180OPENSSL_LIBS = @OPENSSL_LIBS@
     181OPENSSL_MINIMUM = @OPENSSL_MINIMUM@
     182PACKAGE = @PACKAGE@
     183PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     184PACKAGE_NAME = @PACKAGE_NAME@
     185PACKAGE_STRING = @PACKAGE_STRING@
     186PACKAGE_TARNAME = @PACKAGE_TARNAME@
     187PACKAGE_VERSION = @PACKAGE_VERSION@
     188PATH_SEPARATOR = @PATH_SEPARATOR@
     189PEERID_PREFIX = @PEERID_PREFIX@
     190PKG_CONFIG = @PKG_CONFIG@
     191POFILES = @POFILES@
     192POSUB = @POSUB@
     193PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
     194PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
     195PTHREAD_CC = @PTHREAD_CC@
     196PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
     197PTHREAD_LIBS = @PTHREAD_LIBS@
     198RANLIB = @RANLIB@
     199SED = @SED@
     200SET_MAKE = @SET_MAKE@
     201SHELL = @SHELL@
     202STRIP = @STRIP@
     203TR_UNSTABLE_FALSE = @TR_UNSTABLE_FALSE@
     204TR_UNSTABLE_TRUE = @TR_UNSTABLE_TRUE@
     205USERAGENT_PREFIX = @USERAGENT_PREFIX@
     206USE_NLS = @USE_NLS@
     207VERSION = @VERSION@
     208WIN32_FALSE = @WIN32_FALSE@
     209WIN32_TRUE = @WIN32_TRUE@
     210WINDRES = @WINDRES@
     211WX_MINIMUM = @WX_MINIMUM@
     212XGETTEXT = @XGETTEXT@
     213ZLIB_CFLAGS = @ZLIB_CFLAGS@
     214ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
     215ZLIB_LIBS = @ZLIB_LIBS@
     216ac_ct_AR = @ac_ct_AR@
     217ac_ct_CC = @ac_ct_CC@
     218ac_ct_CXX = @ac_ct_CXX@
     219ac_ct_F77 = @ac_ct_F77@
     220ac_ct_RANLIB = @ac_ct_RANLIB@
     221ac_ct_STRIP = @ac_ct_STRIP@
     222ac_ct_WINDRES = @ac_ct_WINDRES@
     223ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
     224acx_pthread_config = @acx_pthread_config@
     225am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
     226am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
     227am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
     228am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
     229am__include = @am__include@
     230am__leading_dot = @am__leading_dot@
     231am__quote = @am__quote@
     232am__tar = @am__tar@
     233am__untar = @am__untar@
     234bindir = @bindir@
     235build = @build@
     236build_alias = @build_alias@
     237build_cpu = @build_cpu@
     238build_os = @build_os@
     239build_vendor = @build_vendor@
     240datadir = @datadir@
     241exec_prefix = @exec_prefix@
     242host = @host@
     243host_alias = @host_alias@
     244host_cpu = @host_cpu@
     245host_os = @host_os@
     246host_vendor = @host_vendor@
     247includedir = @includedir@
     248infodir = @infodir@
     249install_sh = @install_sh@
     250libdir = @libdir@
     251libexecdir = @libexecdir@
     252localstatedir = @localstatedir@
     253mandir = @mandir@
     254mkdir_p = @mkdir_p@
     255oldincludedir = @oldincludedir@
     256prefix = @prefix@
     257program_transform_name = @program_transform_name@
     258sbindir = @sbindir@
     259sharedstatedir = @sharedstatedir@
     260subdirs = @subdirs@
     261sysconfdir = @sysconfdir@
     262target_alias = @target_alias@
     263transmissionlocaledir = @transmissionlocaledir@
     264noinst_LIBRARIES = libdht.a
     265libdht_a_SOURCES = dht.c
     266noinst_HEADERS = dht.h
     267extra_DIST = CHANGES dht-example.c LICENCE README
     268all: all-am
     269
     270.SUFFIXES:
     271.SUFFIXES: .c .lo .o .obj
     272$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
     273        @for dep in $?; do \
     274          case '$(am__configure_deps)' in \
     275            *$$dep*) \
     276              cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
     277                && exit 0; \
     278              exit 1;; \
     279          esac; \
     280        done; \
     281        echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  third-party/dht/Makefile'; \
     282        cd $(top_srcdir) && \
     283          $(AUTOMAKE) --gnu  third-party/dht/Makefile
     284.PRECIOUS: Makefile
     285Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
     286        @case '$?' in \
     287          *config.status*) \
     288            cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
     289          *) \
     290            echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
     291            cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
     292        esac;
     293
     294$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
     295        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
     296
     297$(top_srcdir)/configure:  $(am__configure_deps)
     298        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
     299$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
     300        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
     301
     302clean-noinstLIBRARIES:
     303        -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
     304libdht.a: $(libdht_a_OBJECTS) $(libdht_a_DEPENDENCIES)
     305        -rm -f libdht.a
     306        $(libdht_a_AR) libdht.a $(libdht_a_OBJECTS) $(libdht_a_LIBADD)
     307        $(RANLIB) libdht.a
     308
     309mostlyclean-compile:
     310        -rm -f *.$(OBJEXT)
     311
     312distclean-compile:
     313        -rm -f *.tab.c
     314
     315@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dht.Po@am__quote@
     316
     317.c.o:
     318@am__fastdepCC_TRUE@    if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
     319@am__fastdepCC_TRUE@    then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
     320@AMDEP_TRUE@@am__fastdepCC_FALSE@       source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
     321@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     322@am__fastdepCC_FALSE@   $(COMPILE) -c $<
     323
     324.c.obj:
     325@am__fastdepCC_TRUE@    if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
     326@am__fastdepCC_TRUE@    then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
     327@AMDEP_TRUE@@am__fastdepCC_FALSE@       source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
     328@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     329@am__fastdepCC_FALSE@   $(COMPILE) -c `$(CYGPATH_W) '$<'`
     330
     331.c.lo:
     332@am__fastdepCC_TRUE@    if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
     333@am__fastdepCC_TRUE@    then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
     334@AMDEP_TRUE@@am__fastdepCC_FALSE@       source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
     335@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     336@am__fastdepCC_FALSE@   $(LTCOMPILE) -c -o $@ $<
     337
     338mostlyclean-libtool:
     339        -rm -f *.lo
     340
     341clean-libtool:
     342        -rm -rf .libs _libs
     343
     344distclean-libtool:
     345        -rm -f libtool
     346uninstall-info-am:
     347
     348ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
     349        list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
     350        unique=`for i in $$list; do \
     351            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
     352          done | \
     353          $(AWK) '    { files[$$0] = 1; } \
     354               END { for (i in files) print i; }'`; \
     355        mkid -fID $$unique
     356tags: TAGS
     357
     358TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
     359                $(TAGS_FILES) $(LISP)
     360        tags=; \
     361        here=`pwd`; \
     362        list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
     363        unique=`for i in $$list; do \
     364            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
     365          done | \
     366          $(AWK) '    { files[$$0] = 1; } \
     367               END { for (i in files) print i; }'`; \
     368        if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
     369          test -n "$$unique" || unique=$$empty_fix; \
     370          $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
     371            $$tags $$unique; \
     372        fi
     373ctags: CTAGS
     374CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
     375                $(TAGS_FILES) $(LISP)
     376        tags=; \
     377        here=`pwd`; \
     378        list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
     379        unique=`for i in $$list; do \
     380            if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
     381          done | \
     382          $(AWK) '    { files[$$0] = 1; } \
     383               END { for (i in files) print i; }'`; \
     384        test -z "$(CTAGS_ARGS)$$tags$$unique" \
     385          || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
     386             $$tags $$unique
     387
     388GTAGS:
     389        here=`$(am__cd) $(top_builddir) && pwd` \
     390          && cd $(top_srcdir) \
     391          && gtags -i $(GTAGS_ARGS) $$here
     392
     393distclean-tags:
     394        -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
     395
     396distdir: $(DISTFILES)
     397        @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
     398        topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
     399        list='$(DISTFILES)'; for file in $$list; do \
     400          case $$file in \
     401            $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
     402            $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
     403          esac; \
     404          if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
     405          dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
     406          if test "$$dir" != "$$file" && test "$$dir" != "."; then \
     407            dir="/$$dir"; \
     408            $(mkdir_p) "$(distdir)$$dir"; \
     409          else \
     410            dir=''; \
     411          fi; \
     412          if test -d $$d/$$file; then \
     413            if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
     414              cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
     415            fi; \
     416            cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
     417          else \
     418            test -f $(distdir)/$$file \
     419            || cp -p $$d/$$file $(distdir)/$$file \
     420            || exit 1; \
     421          fi; \
     422        done
     423check-am: all-am
     424check: check-am
     425all-am: Makefile $(LIBRARIES) $(HEADERS)
     426installdirs:
     427install: install-am
     428install-exec: install-exec-am
     429install-data: install-data-am
     430uninstall: uninstall-am
     431
     432install-am: all-am
     433        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
     434
     435installcheck: installcheck-am
     436install-strip:
     437        $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
     438          install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
     439          `test -z '$(STRIP)' || \
     440            echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
     441mostlyclean-generic:
     442
     443clean-generic:
     444
     445distclean-generic:
     446        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
     447
     448maintainer-clean-generic:
     449        @echo "This command is intended for maintainers to use"
     450        @echo "it deletes files that may require special tools to rebuild."
     451clean: clean-am
     452
     453clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
     454        mostlyclean-am
     455
     456distclean: distclean-am
     457        -rm -rf ./$(DEPDIR)
     458        -rm -f Makefile
     459distclean-am: clean-am distclean-compile distclean-generic \
     460        distclean-libtool distclean-tags
     461
     462dvi: dvi-am
     463
     464dvi-am:
     465
     466html: html-am
     467
     468info: info-am
     469
     470info-am:
     471
     472install-data-am:
     473
     474install-exec-am:
     475
     476install-info: install-info-am
     477
     478install-man:
     479
     480installcheck-am:
     481
     482maintainer-clean: maintainer-clean-am
     483        -rm -rf ./$(DEPDIR)
     484        -rm -f Makefile
     485maintainer-clean-am: distclean-am maintainer-clean-generic
     486
     487mostlyclean: mostlyclean-am
     488
     489mostlyclean-am: mostlyclean-compile mostlyclean-generic \
     490        mostlyclean-libtool
     491
     492pdf: pdf-am
     493
     494pdf-am:
     495
     496ps: ps-am
     497
     498ps-am:
     499
     500uninstall-am: uninstall-info-am
     501
     502.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
     503        clean-libtool clean-noinstLIBRARIES ctags distclean \
     504        distclean-compile distclean-generic distclean-libtool \
     505        distclean-tags distdir dvi dvi-am html html-am info info-am \
     506        install install-am install-data install-data-am install-exec \
     507        install-exec-am install-info install-info-am install-man \
     508        install-strip installcheck installcheck-am installdirs \
     509        maintainer-clean maintainer-clean-generic mostlyclean \
     510        mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
     511        pdf pdf-am ps ps-am tags uninstall uninstall-am \
     512        uninstall-info-am
     513
     514# Tell versions [3.59,3.63) of GNU make to not export all variables.
     515# Otherwise a system limit (for SysV at least) may be exceeded.
     516.NOEXPORT:
  • third-party/dht/dht.h

     
     1/*
     2Copyright (c) 2009 by Juliusz Chroboczek
     3
     4Permission is hereby granted, free of charge, to any person obtaining a copy
     5of this software and associated documentation files (the "Software"), to deal
     6in the Software without restriction, including without limitation the rights
     7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8copies of the Software, and to permit persons to whom the Software is
     9furnished to do so, subject to the following conditions:
     10
     11The above copyright notice and this permission notice shall be included in
     12all copies or substantial portions of the Software.
     13
     14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20THE SOFTWARE.
     21*/
     22
     23typedef void
     24dht_callback(void *closure, int event,
     25             unsigned char *info_hash,
     26             void *data, size_t data_len);
     27
     28#define DHT_EVENT_NONE 0
     29#define DHT_EVENT_VALUES 1
     30#define DHT_EVENT_SEARCH_DONE 2
     31
     32extern FILE *dht_debug;
     33
     34int dht_init(int s, const unsigned char *id);
     35int dht_insert_node(int s, const unsigned char *id, struct sockaddr_in *sin);
     36int dht_ping_node(int s, struct sockaddr_in *sin);
     37int dht_periodic(int s, int available, time_t *tosleep,
     38                 dht_callback *callback, void *closure);
     39int dht_search(int s, const unsigned char *id, int port,
     40               dht_callback *callback, void *closure);
     41int dht_nodes(int *good_return, int *dubious_return, int *cached_return,
     42              int *incoming_return);
     43void dht_dump_tables(FILE *f);
     44int dht_get_nodes(struct sockaddr_in *sins, int num);
     45int dht_uninit(int s, int dofree);
     46
     47/* This must be provided by the user. */
     48void dht_hash(void *hash_return, int hash_size,
     49              const void *v1, int len1,
     50              const void *v2, int len2,
     51              const void *v3, int len3);
  • third-party/dht/CHANGES

     
     118 May 2009: dht-0.4
     2
     3  * Fixed the handling of tokens in announce_peer messages.
     4  * Implemented backtracking during search when nodes turn out to be dead.
     5
     617 May 2009: dht-0.3
     7
     8  * Fixed a number of incorrectly formatted messages.
     9  * Changed reply to find_peers to spread the load more uniformly.
     10  * Fixed a bug that could cause premature splitting.
     11  * Implemented rate limiting.
     12  * Changed some time constants to be less chatty.
     13  * When determining if a bucket is fresh enough, we now only take replies
     14    into account.
     15  * dht_get_nodes now returns nodes starting with our own bucket.
     16  * Tweaked the memory allocation strategy for stored peers.
     17
     1817 May 2009: dht-0.2
     19
     20  * Fixed a crash in dht_uninit.
     21  * Added support for saving the list of known-good nodes.
     22  * Changed the interface of dht_nodes to provide the number of nodes that
     23    recently sent incoming requests.
     24
     2513 May 2009: dht-0.1
     26
     27  * Initial public release.
  • third-party/dht/Makefile.am

     
     1noinst_LIBRARIES = libdht.a
     2libdht_a_SOURCES = dht.c
     3noinst_HEADERS = dht.h
     4extra_DIST = CHANGES dht-example.c LICENCE README
  • third-party/dht/dht-example.c

     
     1/* This example code was written by Juliusz Chroboczek.
     2   You are free to cut'n'paste from it to your heart's content. */
     3
     4/* For crypt */
     5#define _GNU_SOURCE
     6
     7#include <stdio.h>
     8#include <stdlib.h>
     9#include <errno.h>
     10#include <string.h>
     11#include <unistd.h>
     12#include <fcntl.h>
     13#include <sys/time.h>
     14#include <arpa/inet.h>
     15#include <sys/types.h>
     16#include <sys/socket.h>
     17#include <netdb.h>
     18#include <sys/signal.h>
     19
     20#include "dht.h"
     21
     22#define MAX_BOOTSTRAP_NODES 20
     23static struct sockaddr_in bootstrap_nodes[MAX_BOOTSTRAP_NODES];
     24static int num_bootstrap_nodes = 0;
     25
     26static volatile sig_atomic_t dumping = 0, searching = 0, exiting = 0;
     27
     28static void
     29sigdump(int signo)
     30{
     31    dumping = 1;
     32}
     33
     34static void
     35sigtest(int signo)
     36{
     37    searching = 1;
     38}
     39
     40static void
     41sigexit(int signo)
     42{
     43    exiting = 1;
     44}
     45
     46static void
     47init_signals(void)
     48{
     49    struct sigaction sa;
     50    sigset_t ss;
     51
     52    sigemptyset(&ss);
     53    sa.sa_handler = sigdump;
     54    sa.sa_mask = ss;
     55    sa.sa_flags = 0;
     56    sigaction(SIGUSR1, &sa, NULL);
     57
     58    sigemptyset(&ss);
     59    sa.sa_handler = sigtest;
     60    sa.sa_mask = ss;
     61    sa.sa_flags = 0;
     62    sigaction(SIGUSR2, &sa, NULL);
     63
     64    sigemptyset(&ss);
     65    sa.sa_handler = sigexit;
     66    sa.sa_mask = ss;
     67    sa.sa_flags = 0;
     68    sigaction(SIGINT, &sa, NULL);
     69}
     70
     71const unsigned char hash[20] = {
     72    0x54, 0x57, 0x87, 0x89, 0xdf, 0xc4, 0x23, 0xee, 0xf6, 0x03,
     73    0x1f, 0x81, 0x94, 0xa9, 0x3a, 0x16, 0x98, 0x8b, 0x72, 0x7b
     74};
     75
     76/* The call-back function is called by the DHT whenever something
     77   interesting happens.  Right now, it only happens when we get a new value or
     78   when a search completes, but this may be extended in future versions. */
     79static void
     80callback(void *closure,
     81         int event,
     82         unsigned char *info_hash,
     83         void *data, size_t data_len)
     84{
     85    if(event == DHT_EVENT_SEARCH_DONE)
     86        printf("Search done.\n");
     87    else if(event == DHT_EVENT_VALUES)
     88        printf("Received %d values.\n", (int)(data_len / 6));
     89}
     90
     91int
     92main(int argc, char **argv)
     93{
     94    int i, rc, fd;
     95    int s, port;
     96    int have_id = 0;
     97    unsigned char myid[20];
     98    time_t tosleep = 0;
     99
     100    /* Ids need to be distributed evenly, so you cannot just use your
     101       bittorrent id.  Either generate it randomly, or take the SHA-1 of
     102       something. */
     103    fd = open("dht-example.id", O_RDONLY);
     104    if(fd >= 0) {
     105        rc = read(fd, myid, 20);
     106        if(rc == 20)
     107            have_id = 1;
     108        close(fd);
     109    }
     110   
     111    if(!have_id) {
     112        fd = open("/dev/urandom", O_RDONLY);
     113        if(fd < 0) {
     114            perror("open(random)");
     115            exit(1);
     116        }
     117        rc = read(fd, myid, 20);
     118        if(rc < 0) {
     119            perror("read(random)");
     120            exit(1);
     121        }
     122        have_id = 1;
     123        close(fd);
     124
     125        fd = open("dht-example.id", O_WRONLY | O_CREAT | O_TRUNC, 0666);
     126        if(fd >= 0) {
     127            rc = write(fd, myid, 20);
     128            if(rc < 20)
     129                unlink("dht-example.id");
     130            close(fd);
     131        }
     132    }
     133
     134    if(argc < 2)
     135        goto usage;
     136
     137    i = 1;
     138
     139    if(argc < i + 1)
     140        goto usage;
     141
     142    port = atoi(argv[i++]);
     143    if(port <= 0 || port >= 0x10000)
     144        goto usage;
     145
     146    while(i < argc) {
     147        struct addrinfo hints, *info, *infop;
     148        memset(&hints, 0, sizeof(hints));
     149        hints.ai_family = AF_INET;
     150        hints.ai_socktype = SOCK_DGRAM;
     151        rc = getaddrinfo(argv[i], NULL, &hints, &info);
     152        if(rc != 0) {
     153            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
     154            exit(1);
     155        }
     156
     157        i++;
     158
     159        infop = info;
     160        while(infop) {
     161            if(infop->ai_addr->sa_family == AF_INET) {
     162                struct sockaddr_in sin;
     163                memcpy(&sin, infop->ai_addr, infop->ai_addrlen);
     164                sin.sin_port = htons(atoi(argv[i]));
     165                bootstrap_nodes[num_bootstrap_nodes] = sin;
     166                num_bootstrap_nodes++;
     167            }
     168            infop = infop->ai_next;
     169        }
     170        freeaddrinfo(info);
     171
     172        i++;
     173    }
     174
     175    if(i < argc)
     176        goto usage;
     177
     178    /* If you set dht_debug to a stream, every action taken by the DHT will
     179       be logged. */
     180    dht_debug = stdout;
     181
     182    /* We need an IPv4 socket, bound to a stable port.  Rumour has it that
     183       uTorrent works better when it is the same as your Bittorrent port. */
     184    s = socket(PF_INET, SOCK_DGRAM, 0);
     185    if(s < 0) {
     186        perror("socket");
     187        exit(1);
     188    }
     189
     190    {
     191        struct sockaddr_in sin;
     192        memset(&sin, 0, sizeof(sin));
     193        sin.sin_family = AF_INET;
     194        sin.sin_port = htons(port);
     195        rc = bind(s, (struct sockaddr*)&sin, sizeof(sin));
     196        if(rc < 0) {
     197            perror("bind");
     198            exit(1);
     199        }
     200    }
     201
     202    /* Init the dht.  This sets the socket into non-blocking mode. */
     203    rc = dht_init(s, myid);
     204    if(rc < 0) {
     205        perror("dht_init");
     206        exit(1);
     207    }
     208
     209    init_signals();
     210
     211    /* For bootstrapping, we need an initial list of nodes.  This could be
     212       hard-wired, but can also be obtained from the nodes key of a torrent
     213       file, or from the PORT bittorrent message.
     214
     215       Dht_ping_node is the brutal way of bootstrapping -- it actually
     216       sends a message to the peer.  If you're going to bootstrap from
     217       a massive number of nodes (for example because you're restoring from
     218       a dump) and you already know their ids, it's better to use
     219       dht_insert_node.  If the ids are incorrect, the DHT will recover. */
     220    for(i = 0; i < num_bootstrap_nodes; i++) {
     221        dht_ping_node(s, &bootstrap_nodes[i]);
     222        usleep(random() % 100000);
     223    }
     224
     225    while(1) {
     226        struct timeval tv;
     227        fd_set readfds;
     228        tv.tv_sec = tosleep;
     229        tv.tv_usec = random() % 1000000;
     230
     231        FD_ZERO(&readfds);
     232        FD_SET(s, &readfds);
     233        rc = select(s + 1, &readfds, NULL, NULL, &tv);
     234        if(rc < 0) {
     235            if(errno != EINTR) {
     236                perror("select");
     237                sleep(1);
     238            }
     239        }
     240       
     241        if(exiting)
     242            break;
     243
     244        rc = dht_periodic(s, rc > 0, &tosleep, callback, NULL);
     245        if(rc < 0) {
     246            if(errno == EINTR) {
     247                continue;
     248            } else {
     249                perror("dht_periodic");
     250                if(rc == EINVAL || rc == EFAULT)
     251                    abort();
     252                tosleep = 1;
     253            }
     254        }
     255
     256        /* This is how you trigger a search for a torrent hash.  If port
     257           (the third argument) is non-zero, it also performs an announce.
     258           Since peers expire announced data after 30 minutes, it's a good
     259           idea to reannounce every 28 minutes or so. */
     260        if(searching) {
     261            dht_search(s, hash, 0, callback, NULL);
     262            searching = 0;
     263        }
     264
     265        /* For debugging, or idle curiosity. */
     266        if(dumping) {
     267            dht_dump_tables(stdout);
     268            dumping = 0;
     269        }
     270    }
     271
     272    {
     273        struct sockaddr_in sins[500];
     274        int i;
     275        i = dht_get_nodes(sins, 500);
     276        printf("Found %d good nodes.\n", i);
     277    }
     278
     279    dht_uninit(s, 1);
     280    return 0;
     281   
     282 usage:
     283    fprintf(stderr, "Foo!\n");
     284    exit(1);
     285}
     286
     287/* We need to provide a reasonably strong cryptographic hashing function.
     288   Here's how we'd do it if we had RSA's MD5 code. */
     289#if 0
     290void
     291dht_hash(void *hash_return, int hash_size,
     292         const void *v1, int len1,
     293         const void *v2, int len2,
     294         const void *v3, int len3)
     295{
     296    static MD5_CTX ctx;
     297    MD5Init(&ctx);
     298    MD5Update(&ctx, v1, len1);
     299    MD5Update(&ctx, v2, len2);
     300    MD5Update(&ctx, v3, len3);
     301    MD5Final(&ctx);
     302    if(hash_size > 16)
     303        memset((char*)hash_return + 16, 0, hash_size - 16);
     304    memcpy(hash_return, ctx.digest, hash_size > 16 ? 16 : hash_size);
     305}
     306#else
     307/* But for this example, we might as well use something weaker. */
     308void
     309dht_hash(void *hash_return, int hash_size,
     310         const void *v1, int len1,
     311         const void *v2, int len2,
     312         const void *v3, int len3)
     313{
     314    const char *c1 = v1, *c2 = v2, *c3 = v3;
     315    char key[9];                /* crypt is limited to 8 characters */
     316    int i;
     317
     318    memset(key, 0, 9);
     319#define CRYPT_HAPPY(c) ((c % 0x60) + 0x20)
     320
     321    for(i = 0; i < 2 && i < len1; i++)
     322        key[i] = CRYPT_HAPPY(c1[i]);
     323    for(i = 0; i < 4 && i < len1; i++)
     324        key[2 + i] = CRYPT_HAPPY(c2[i]);
     325    for(i = 0; i < 2 && i < len1; i++)
     326        key[6 + i] = CRYPT_HAPPY(c3[i]);
     327    strncpy(hash_return, crypt(key, "jc"), hash_size);
     328}
     329#endif
  • third-party/dht/README

     
     1The files dht.c and dht.h implement the variant of the Kademlia Distributed
     2Hash Table (DHT) used in the Bittorrent network (``mainline'' variant).
     3
     4The file dht-example.c is a stand-alone program that participates in the
     5DHT.  Another example is a patch against Transmission, which you might or
     6might not be able to find somewhere.
     7
     8The code is designed to work well in both event-driven and threaded code.
     9The caller, which is either an event-loop or a dedicated thread, must
     10periodically call the function dht_periodic.  In addition, it must call
     11dht_periodic whenever any data has arrived from the network.
     12
     13All functions return -1 in case of failure, in which case errno is set, or
     14a positive value in case of success.
     15
     16Initialisation
     17**************
     18
     19* dht_init
     20
     21This must be called before using the library.  You pass it a bound IPv4
     22datagram socket, and your node id, a 20-octet array that should be globally
     23unique.
     24
     25Node ids must be well distributed, so you cannot just use your Bittorrent
     26id; you should either generate a truly random value (using plenty of
     27entropy), or at least take the SHA-1 of something.  However, it is a good
     28idea to keep the id stable, so you may want to store it in stable storage
     29at client shutdown.
     30 
     31* dht_uninit
     32
     33This may be called at the end of the session.  If dofree is true, it frees
     34all the memory allocated for the DHT.  If dofree is false, this function
     35currently does nothing.
     36
     37Bootstrapping
     38*************
     39
     40The DHT needs to be taught a small number of contacts to begin functioning.
     41You can hard-wire a small number of stable nodes in your application, but
     42this obviously fails to scale.  You may save the list of known good nodes
     43at shutdown, and restore it at restart.  You may also grab nodes from
     44torrent files (the nodes field), and you may exchange contacts with other
     45Bittorrent peers using the PORT extension.
     46
     47* dht_ping
     48
     49This is the main bootstrapping primitive.  You pass it an address at which
     50you believe that a DHT node may be living, and a query will be sent.  If
     51a node replies, and if there is space in the routing table, it will be
     52inserted.
     53
     54* dht_insert_node
     55
     56This is a softer bootstrapping method, which doesn't actually send
     57a query -- it only stores the node in the routing table for later use.  It
     58is a good idea to use that when e.g. restoring your routing table from
     59disk.
     60
     61Note that dht_insert_node requires that you supply a node id.  If the id
     62turns out to be wrong, the DHT will eventually recover; still, inserting
     63massive amounts of incorrect information into your routing table is
     64certainly not a good idea.
     65
     66An additionaly difficulty with dht_insert_node is that, for various
     67reasons, a Kademlia routing table cannot absorb nodes faster than a certain
     68rate.  Dumping a large number of nodes into a table using dht_insert_node
     69will probably cause most of these nodes to be discarded straight away.
     70(The tolerable rate is difficult to estimate; it is probably on the order
     71of one node every few seconds per node already in the table divided by 8,
     72for some suitable value of 8.)
     73
     74Doing some work
     75***************
     76
     77* dht_periodic
     78
     79This function should be called by your main loop periodically, and also
     80whenever data is available on the socket.  The time after which
     81dht_periodic should be called if no data is available is returned in the
     82parameter tosleep.  (You do not need to be particularly accurate; actually,
     83it is a good idea to be late by a random value.)
     84
     85The parameter available indicates whether any data is available on the
     86socket.  If it is 0, dht_periodic will not try to read data; if it is 1, it
     87will.
     88
     89Dht_periodic also takes a callback, which will be called whenever something
     90interesting happens (see below).
     91
     92* dht_search
     93
     94This schedules a search for information about the info-hash specified in
     95id.  If port is not 0, it specifies the TCP port on which the current peer
     96is litening; in that case, when the search is complete it will be announced
     97to the network.  The port is in host order, beware if you got it from
     98a struct sockaddr_in.
     99
     100In either case, data is passed to the callback function as soon as it is
     101available, possibly in multiple pieces.  The callback function will
     102additionally be called when the search is complete.
     103
     104Up to DHT_MAX_SEARCHES (20) searches can be in progress at a given time;
     105any more, and dht_search will return -1.  If you specify a new search for
     106the same info hash as a search still in progress, the previous search is
     107combined with the new one -- you will only receive a completion indication
     108once.
     109
     110Information queries
     111*******************
     112
     113* dht_nodes
     114
     115This returns the number of known good, dubious and cached nodes in our
     116routing table.  This can be used to decide whether it's reasonable to start
     117a search; a search is likely to be successful as long as we have a few good
     118nodes; however, in order to avoid overloading your bootstrap nodes, you may
     119want to wait until good is at least 4 and good + doubtful is at least 30 or
     120so.
     121
     122It also includes the number of nodes that recently send us an unsolicited
     123request; this can be used to determine if the UDP port used for the DHT is
     124firewalled.
     125
     126If you want to display a single figure to the user, you should display good
     127+ doubtful, which is the total number of nodes in your routing table.  Some
     128clients try to estimate the total number of nodes, but this doesn't make
     129much sense -- since the result is exponential in the number of nodes in the
     130routing table, small variations in the latter cause huge jumps in the
     131former.
     132
     133* dht_get_nodes
     134
     135This retrieves the list of known good nodes, starting with the nodes in our
     136own bucket.  It is a good idea to save the list of known good nodes at
     137shutdown, and ping them at startup.
     138
     139* dht_dump_tables
     140* dht_debug
     141
     142These are debugging aids.
     143
     144Functions provided by you
     145*************************
     146
     147* The callback function
     148
     149The callback function is called with 5 arguments.  Closure is simply the
     150value that you passed to dht_periodic.  Event is one of DHT_EVENT_VALUES,
     151which indicates that we have new values, or DHT_EVENT_SEARCH_DONE, which
     152indicates that a search has completed.  In either case, info_hash is set to
     153the info-hash of the search.
     154
     155In the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact''
     156format -- 6 bytes per node, 4 for the IP address and 2 for the port.  It's
     157length in bytes is in data_len.
     158
     159* dht_hash
     160
     161This should compute a reasonably strong cryptographic hash of the passed
     162values.  It should map cleanly to your favourite crypto toolkit's MD5 or
     163SHA-1 function.
     164
     165Final notes
     166***********
     167
     168* NAT
     169
     170Nothing works well across NATs, but Kademlia is somewhat less impacted than
     171many other protocols.  The implementation takes care to distinguish between
     172unidirectional and bidirectional reachability, and NATed nodes will
     173eventually fall out from other nodes' routing tables.
     174
     175While there is no periodic pinging in this implementation, maintaining
     176a full routing table requires slightly more than one packet exchange per
     177minute, even in a completely idle network; this should be sufficient to
     178make most full cone NATs happy.
     179
     180* Missing functionality
     181
     182Some of the code has had very little testing.  If it breaks, you get to
     183keep both pieces.
     184
     185There is currently no good way to save and restore your routing table.
     186
     187IPv6 support is deliberately not included: designing a double-stack
     188distributed hash table raises some tricky issues, and doing it naively may
     189break connectivity for everyone.
     190
     191                                        Juliusz Chroboczek
     192                                        <jch@pps.jussieu.fr>
  • third-party/Makefile.am

     
    11SUBDIRS = \
    22    libevent \
    33    libnatpmp \
    4     miniupnp
     4    miniupnp \
     5    dht
    56
    67EXTRA_DIST = \
    78    macosx-libevent-config.h