Changeset 7397


Ignore:
Timestamp:
Dec 15, 2008, 12:17:08 AM (10 years ago)
Author:
charles
Message:

(trunk libT) add ipv6 support by jhujhiti. I think this is the largest user-contributed patch we've ever used... thanks jhujhiti :)

Location:
trunk/libtransmission
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/fdlimit.c

    r7232 r7397  
    451451
    452452int
    453 tr_fdSocketCreate( int type )
     453tr_fdSocketCreate( int domain, int type )
    454454{
    455455    int s = -1;
     
    458458
    459459    if( gFd->socketCount < getSocketMax( gFd ) )
    460         if( ( s = socket( AF_INET, type, 0 ) ) < 0 )
     460        if( ( s = socket( domain, type, 0 ) ) < 0 )
     461        {
    461462            tr_err( _( "Couldn't create socket: %s" ),
    462463                   tr_strerror( sockerrno ) );
     464            s = -sockerrno;
     465        }
    463466
    464467    if( s > -1 )
     
    486489    if( gFd->socketCount < getSocketMax( gFd ) )
    487490    {
    488         len = sizeof( struct sockaddr );
     491        len = sizeof( struct sockaddr_storage );
    489492        s = accept( b, (struct sockaddr *) &sock, &len );
    490493    }
     
    504507            struct sockaddr_in6 * sock6 = (struct sockaddr_in6 *)&sock;
    505508            addr->type = TR_AF_INET6;
    506             memcpy( &addr->addr, &sock6->sin6_addr,
    507                     sizeof( struct sockaddr_in6 ) );
     509            addr->addr.addr6 = sock6->sin6_addr;
    508510            *port = sock6->sin6_port;
    509511        }
  • trunk/libtransmission/fdlimit.h

    r7231 r7397  
    8686 * Sockets
    8787 **********************************************************************/
    88 int      tr_fdSocketCreate( int type );
     88int      tr_fdSocketCreate( int domain, int type );
    8989
    9090int      tr_fdSocketAccept( int           b,
  • trunk/libtransmission/net.c

    r7232 r7397  
    2727#include <stdlib.h>
    2828#include <string.h>
     29#include <assert.h>
    2930
    3031#include <sys/types.h>
     
    108109    dst->type = TR_AF_INET6;
    109110    return dst;
    110 }
     111}
     112
     113void
     114tr_normalizeV4Mapped( tr_address * const addr )
     115{
     116    if( addr->type == TR_AF_INET6 && IN6_IS_ADDR_V4MAPPED( &addr->addr.addr6 ) )
     117    {
     118        addr->type = TR_AF_INET;
     119        memcpy( &addr->addr.addr4.s_addr, addr->addr.addr6.s6_addr + 12, 4 );
     120    }
     121}
    111122
    112123/*
     
    141152
    142153/***********************************************************************
     154 * Socket list housekeeping
     155 **********************************************************************/
     156struct tr_socketList
     157{
     158    int             socket;
     159    tr_address      addr;
     160    tr_socketList * next;
     161};
     162
     163tr_socketList *
     164tr_socketListAppend( tr_socketList * const head,
     165                     const tr_address * const addr )
     166{
     167    tr_socketList * tmp;
     168    assert( head );
     169    for( tmp = head; tmp->next; tmp = tmp->next );
     170    tmp->next = tr_socketListNew( addr );
     171    return tmp->next;
     172}
     173
     174tr_socketList *
     175tr_socketListNew( const tr_address * const addr )
     176{
     177    tr_socketList * tmp;
     178    tmp = tr_new( tr_socketList, 1 );
     179    tmp->socket = -1;
     180    tmp->addr = *addr;
     181    tmp->next = NULL;
     182    return tmp;
     183}
     184
     185void
     186tr_socketListFree( tr_socketList * const head )
     187{
     188    assert( head );
     189    if( head->next )
     190        tr_socketListFree( head->next );
     191    tr_free( head );
     192}
     193
     194void
     195tr_socketListRemove( tr_socketList * const head,
     196                     tr_socketList * const el)
     197{
     198    tr_socketList * tmp;
     199    assert( head );
     200    assert( el );
     201    for( tmp = head; tmp->next && tmp->next != el; tmp = tmp->next );
     202    tmp->next = el->next;
     203    el->next = NULL;
     204    tr_socketListFree(el);
     205}
     206
     207void
     208tr_socketListTruncate( tr_socketList * const head,
     209                       tr_socketList * const start )
     210{
     211    tr_socketList * tmp;
     212    assert( head );
     213    assert( start );
     214    for( tmp = head; tmp->next && tmp->next != start; tmp = tmp->next );
     215    tr_socketListFree( start );
     216    tmp->next = NULL;
     217}
     218
     219int
     220tr_socketListGetSocket( const tr_socketList * const el )
     221{
     222    assert( el );
     223    return el->socket;
     224}
     225
     226const tr_address *
     227tr_socketListGetAddress( const tr_socketList * const el )
     228{
     229    assert( el );
     230    return &el->addr;
     231}
     232
     233void
     234tr_socketListForEach( tr_socketList * const head,
     235                      void ( * cb ) ( int * const,
     236                                      tr_address * const,
     237                                      void * const),
     238                      void * const userData )
     239{
     240    tr_socketList * tmp;
     241    for( tmp = head; tmp; tmp = tmp->next )
     242        cb( &tmp->socket, &tmp->addr, userData );
     243}
     244
     245/***********************************************************************
    143246 * TCP sockets
    144247 **********************************************************************/
     
    162265        if( evutil_make_socket_nonblocking( fd ) )
    163266        {
     267            int tmperrno;
    164268            tr_err( _( "Couldn't create socket: %s" ),
    165269                   tr_strerror( sockerrno ) );
     270            tmperrno = sockerrno;
    166271            tr_netClose( fd );
    167             fd = -1;
     272            fd = -tmperrno;
    168273        }
    169274    }
     
    173278
    174279static int
    175 createSocket( int type )
    176 {
    177     return makeSocketNonBlocking( tr_fdSocketCreate( type ) );
     280createSocket( int domain, int type )
     281{
     282    return makeSocketNonBlocking( tr_fdSocketCreate( domain, type ) );
    178283}
    179284
     
    192297}
    193298
    194 static void
    195 setup_sockaddr( const tr_address        * addr,
    196                 tr_port                   port,
    197                 struct sockaddr_storage * sockaddr)
    198 {
    199     struct sockaddr_in  sock4;
    200     struct sockaddr_in6 sock6;
    201 
    202     if( addr->type == TR_AF_INET )
    203     {
    204         memset( &sock4, 0, sizeof( sock4 ) );
    205         sock4.sin_family      = AF_INET;
    206         sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
    207         sock4.sin_port        = port;
    208         memcpy( sockaddr, &sock4, sizeof( sock4 ) );
    209     }
    210     else
    211     {
    212         memset( &sock6, 0, sizeof( sock6 ) );
    213         sock6.sin6_family = AF_INET6;
    214         sock6.sin6_port = port;
    215         memcpy( &sock6.sin6_addr, &addr->addr, sizeof( struct in6_addr ) );
    216         memcpy( sockaddr, &sock6, sizeof( sock6 ) );
    217     }
    218 }
    219  
    220 int
    221 tr_netOpenTCP( tr_session        * session,
    222                const tr_address  * addr,
    223                tr_port             port )
    224 {
    225     int                     s;
    226     struct sockaddr_storage sock;
    227     const int               type = SOCK_STREAM;
    228 
    229     if( ( s = createSocket( type ) ) < 0 )
    230         return -1;
     299static socklen_t
     300setup_sockaddr( const tr_address        * addr,
     301                tr_port                   port,
     302                struct sockaddr_storage * sockaddr)
     303{
     304    struct sockaddr_in  sock4;
     305    struct sockaddr_in6 sock6;
     306    if( addr->type == TR_AF_INET )
     307    {
     308        memset( &sock4, 0, sizeof( sock4 ) );
     309        sock4.sin_family      = AF_INET;
     310        sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
     311        sock4.sin_port        = port;
     312        memcpy( sockaddr, &sock4, sizeof( sock4 ) );
     313        return sizeof( struct sockaddr_in );
     314    }
     315    else
     316    {
     317        memset( &sock6, 0, sizeof( sock6 ) );
     318        sock6.sin6_family = AF_INET6;
     319        sock6.sin6_port = port;
     320        sock6.sin6_flowinfo = 0;
     321        sock6.sin6_addr = addr->addr.addr6;
     322        memcpy( sockaddr, &sock6, sizeof( sock6 ) );
     323        return sizeof( struct sockaddr_in6 );
     324    }
     325}
     326
     327int
     328tr_netOpenTCP( tr_session        * session,
     329               const tr_address  * addr,
     330               tr_port             port )
     331{
     332    int                     s;
     333    struct sockaddr_storage sock;
     334    const int               type = SOCK_STREAM;
     335    socklen_t               addrlen;
     336
     337    if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ),
     338                            type ) ) < 0 )
     339        return s;
    231340
    232341    setSndBuf( session, s );
    233342
    234     setup_sockaddr( addr, port, &sock );
     343    addrlen = setup_sockaddr( addr, port, &sock );
    235344
    236345    if( ( connect( s, (struct sockaddr *) &sock,
    237                   sizeof( struct sockaddr ) ) < 0 )
     346                  addrlen ) < 0 )
    238347#ifdef WIN32
    239348      && ( sockerrno != WSAEWOULDBLOCK )
     
    241350      && ( sockerrno != EINPROGRESS ) )
    242351    {
     352        int tmperrno;
    243353        tr_err( _( "Couldn't connect socket %d to %s, port %d (errno %d - %s)" ),
    244354               s, tr_ntop_non_ts( addr ), (int)port, sockerrno, tr_strerror( sockerrno ) );
     355        tmperrno = sockerrno;
    245356        tr_netClose( s );
    246         s = -1;
     357        s = -tmperrno;
    247358    }
    248359
     
    254365
    255366int
    256 tr_netBindTCP( const tr_address * addr, tr_port port )
    257 {
    258     int                      s;
    259     struct sockaddr_storage  sock;
    260     const int                type = SOCK_STREAM;
     367tr_netBindTCP( const tr_address * addr, tr_port port, tr_bool suppressMsgs )
     368{
     369    int                     s;
     370    struct sockaddr_storage sock;
     371    const int               type = SOCK_STREAM;
     372    int                     addrlen;
    261373
    262374#if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT )
     
    264376#endif
    265377
    266     if( ( s = createSocket( type ) ) < 0 )
    267         return -1;
     378    if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ),
     379                            type ) ) < 0 )
     380        return s;
    268381
    269382#ifdef SO_REUSEADDR
     
    272385#endif
    273386
    274     setup_sockaddr( addr, htons( port ), &sock );
     387    addrlen = setup_sockaddr( addr, htons( port ), &sock );
    275388
    276389    if( bind( s, (struct sockaddr *) &sock,
    277              sizeof( struct sockaddr ) ) )
    278     {
    279         tr_err( _( "Couldn't bind port %d on %s: %s" ), port,
    280                tr_ntop_non_ts( addr ), tr_strerror( sockerrno ) );
     390             addrlen ) )
     391    {
     392        int tmperrno;
     393        if( !suppressMsgs )
     394            tr_err( _( "Couldn't bind port %d on %s: %s" ), port,
     395                    tr_ntop_non_ts( addr ), tr_strerror( sockerrno ) );
     396        tmperrno = sockerrno;
    281397        tr_netClose( s );
    282         return -1;
    283     }
    284 
    285     tr_dbg(  "Bound socket %d to port %d on %s",
    286              s, port, tr_ntop_non_ts( addr ) );
     398        return -tmperrno;
     399    }
     400    if( !suppressMsgs )
     401        tr_dbg(  "Bound socket %d to port %d on %s",
     402                 s, port, tr_ntop_non_ts( addr ) );
    287403    return s;
    288404}
  • trunk/libtransmission/net.h

    r7232 r7397  
    5656struct tr_session;
    5757
    58 #define TR_AF_INET  0
    59 #define TR_AF_INET6 1
    60  
    61 typedef struct tr_address {
    62     unsigned short type : 1;
    63     union {
    64         /* The order here is important for tr_in{,6}addr_any initialization,
    65          * since we can't use C99 designated initializers */
    66         struct in6_addr addr6;
    67         struct in_addr  addr4;
    68     } addr;
    69 } tr_address;
    70  
    71 extern const tr_address tr_inaddr_any;
    72 extern const tr_address tr_in6addr_any;
    73  
    74 const char *tr_ntop( const tr_address * src,
    75                      char * dst,
    76                      int size );
    77 const char *tr_ntop_non_ts( const tr_address * src );
    78 tr_address *tr_pton( const char * src,
    79                      tr_address * dst );
    80 int tr_compareAddresses( const tr_address * a,
    81                          const tr_address * b);
     58#define TR_AF_INET  0
     59#define TR_AF_INET6 1
     60
     61typedef struct tr_address {
     62    uint8_t type;
     63    union {
     64        /* The order here is important for tr_in{,6}addr_any initialization,
     65         * since we can't use C99 designated initializers */
     66        struct in6_addr addr6;
     67        struct in_addr  addr4;
     68    } addr;
     69} tr_address;
     70
     71extern const tr_address tr_inaddr_any;
     72extern const tr_address tr_in6addr_any;
     73
     74const char *tr_ntop( const tr_address * src,
     75                     char * dst,
     76                     int size );
     77const char *tr_ntop_non_ts( const tr_address * src );
     78tr_address *tr_pton( const char * src,
     79                     tr_address * dst );
     80int tr_compareAddresses( const tr_address * a,
     81                         const tr_address * b);
     82void tr_normalizeV4Mapped( tr_address * const addr );
     83
     84/***********************************************************************
     85 * Socket list housekeeping
     86 **********************************************************************/
     87typedef struct tr_socketList tr_socketList;
     88tr_socketList *tr_socketListAppend( tr_socketList * const head,
     89                                    const tr_address * const addr );
     90tr_socketList *tr_socketListNew( const tr_address * const addr );
     91void tr_socketListFree( tr_socketList * const head );
     92void tr_socketListRemove( tr_socketList * const head,
     93                          tr_socketList * const el);
     94void tr_socketListTruncate( tr_socketList * const head,
     95                            tr_socketList * const start );
     96int tr_socketListGetSocket( const tr_socketList * const el );
     97const tr_address *tr_socketListGetAddress( const tr_socketList * const el );
     98void tr_socketListForEach( tr_socketList * const head,
     99                           void ( * cb ) ( int * const,
     100                                           tr_address * const,
     101                                           void * const ),
     102                           void * const userData);
    82103
    83104/***********************************************************************
     
    89110
    90111int  tr_netBindTCP( const tr_address * addr,
    91                     tr_port            port );
     112                    tr_port            port,
     113                    tr_bool            suppressMsgs );
    92114
    93115int  tr_netAccept( struct tr_handle  * session,
  • trunk/libtransmission/peer-mgr.c

    r7361 r7397  
    13471347    if( !tr_sessionIsAddressBlocked( t->manager->session, &pex->addr ) )
    13481348        ensureAtomExists( t, &pex->addr, pex->port, pex->flags, from );
    1349 
     1349   
    13501350    managerUnlock( manager );
    13511351}
     
    13721372    }
    13731373
     1374    *pexCount = n;
     1375    return pex;
     1376}
     1377
     1378tr_pex *
     1379tr_peerMgrCompact6ToPex( const void    * compact,
     1380                         size_t          compactLen,
     1381                         const uint8_t * added_f,
     1382                         size_t          added_f_len,
     1383                         size_t        * pexCount )
     1384{
     1385    size_t          i;
     1386    size_t          n = compactLen / 18;
     1387    const uint8_t * walk = compact;
     1388    tr_pex *        pex = tr_new0( tr_pex, n );
     1389   
     1390    for( i = 0; i < n; ++i )
     1391    {
     1392        pex[i].addr.type = TR_AF_INET6;
     1393        memcpy( &pex[i].addr.addr.addr6.s6_addr, walk, 16 ); walk += 16;
     1394        memcpy( &pex[i].port, walk, 2 ); walk += 2;
     1395        if( added_f && ( n == added_f_len ) )
     1396            pex[i].flags = added_f[i];
     1397    }
     1398   
     1399    *pexCount = n;
     1400    return pex;
     1401}
     1402
     1403tr_pex *
     1404tr_peerMgrArrayToPex( const void * array,
     1405                      size_t       arrayLen,
     1406                      size_t      * pexCount )
     1407{
     1408    size_t          i;
     1409    size_t          n = arrayLen / ( sizeof( tr_address ) + 2 );
     1410    /*size_t          n = arrayLen / sizeof( tr_peerArrayElement );*/
     1411    const uint8_t * walk = array;
     1412    tr_pex        * pex = tr_new0( tr_pex, n );
     1413   
     1414    for( i = 0 ; i < n ; i++ ) {
     1415        memcpy( &pex[i].addr, walk, sizeof( tr_address ) );
     1416        memcpy( &pex[i].port, walk + sizeof( tr_address ), 2 );
     1417        pex[i].flags = 0x00;
     1418        walk += sizeof( tr_address ) + 2;
     1419    }
     1420   
    13741421    *pexCount = n;
    13751422    return pex;
     
    14351482
    14361483int
    1437 tr_peerMgrGetPeers( tr_peerMgr *    manager,
     1484tr_peerMgrGetPeers( tr_peerMgr    * manager,
    14381485                    const uint8_t * torrentHash,
    1439                     tr_pex **       setme_pex )
     1486                    tr_pex       ** setme_pex,
     1487                    uint8_t         af)
    14401488{
    14411489    int peerCount = 0;
     1490    int peersReturning = 0;
    14421491    const Torrent *  t;
    14431492
     
    14531502        int i;
    14541503        const tr_peer ** peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
     1504        /* for now, this will waste memory on torrents that have both
     1505         * ipv6 and ipv4 peers */
    14551506        tr_pex * pex = tr_new( tr_pex, peerCount );
    14561507        tr_pex * walk = pex;
     
    14591510        {
    14601511            const tr_peer * peer = peers[i];
    1461             const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
    1462 
    1463             walk->addr = peer->addr;
    1464             walk->port = peer->port;
    1465             walk->flags = 0;
    1466             if( peerPrefersCrypto( peer ) )
    1467                 walk->flags |= ADDED_F_ENCRYPTION_FLAG;
    1468             if( ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 ) )
    1469                 walk->flags |= ADDED_F_SEED_FLAG;
     1512            if( peer->addr.type == af )
     1513            {
     1514                const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
     1515                memcpy( &walk->addr, &peer->addr, sizeof( walk->addr ) );
     1516                walk->port = peer->port;
     1517                walk->flags = 0;
     1518                if( peerPrefersCrypto( peer ) )
     1519                    walk->flags |= ADDED_F_ENCRYPTION_FLAG;
     1520                if( ( atom->uploadOnly == UPLOAD_ONLY_YES ) ||
     1521                    ( peer->progress >= 1.0 ) )
     1522                    walk->flags |= ADDED_F_SEED_FLAG;
     1523                peersReturning++;
     1524            }
    14701525        }
    14711526
    14721527        assert( ( walk - pex ) == peerCount );
    1473         qsort( pex, peerCount, sizeof( tr_pex ), tr_pexCompare );
     1528        qsort( pex, peersReturning, sizeof( tr_pex ), tr_pexCompare );
    14741529        *setme_pex = pex;
    14751530    }
    14761531
    14771532    managerUnlock( manager );
    1478     return peerCount;
     1533    return peersReturning;
    14791534}
    14801535
     
    17861841        const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
    17871842        tr_peer_stat *           stat = ret + i;
    1788 
    1789         tr_ntop( &peer->addr, stat->addr, sizeof(stat->addr) );
    1790         tr_strlcpy( stat->client, (peer->client ? peer->client : ""), sizeof(stat->client) );
     1843        tr_address               norm_addr;
     1844
     1845        memcpy( &norm_addr, &peer->addr, sizeof( tr_address ) );
     1846        tr_normalizeV4Mapped( &norm_addr );
     1847        tr_ntop( &norm_addr, stat->addr, sizeof( stat->addr ) );
     1848        tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ),
     1849                   sizeof( stat->client ) );
    17911850        stat->port               = ntohs( peer->port );
    17921851        stat->from               = atom->from;
  • trunk/libtransmission/peer-mgr.h

    r7385 r7397  
    6868                                 size_t        * setme_pex_count );
    6969
     70tr_pex * tr_peerMgrCompact6ToPex( const void    * compact,
     71                                  size_t          compactLen,
     72                                  const uint8_t * added_f,
     73                                  size_t          added_f_len,
     74                                  size_t        * pexCount );
     75
     76tr_pex * tr_peerMgrArrayToPex( const void * array,
     77                               size_t       arrayLen,
     78                               size_t      * setme_pex_count );
     79
    7080void tr_peerMgrAddPex( tr_peerMgr     * manager,
    7181                       const uint8_t  * torrentHash,
     
    8090int  tr_peerMgrGetPeers( tr_peerMgr      * manager,
    8191                         const uint8_t   * torrentHash,
    82                          tr_pex         ** setme_pex );
     92                         tr_pex         ** setme_pex,
     93                         uint8_t           af);
    8394
    8495void tr_peerMgrStartTorrent( tr_peerMgr     * manager,
  • trunk/libtransmission/peer-msgs.c

    r7361 r7397  
    283283    uint8_t         ut_pex_id;
    284284    uint16_t        pexCount;
     285    uint16_t        pexCount6;
    285286    uint16_t        minActiveRequests;
    286287    uint16_t        maxActiveRequests;
     
    309310    tr_timer             * pexTimer;
    310311    tr_pex               * pex;
     312    tr_pex               * pex6;
    311313
    312314    time_t                 clientSentPexAt;
     
    11821184
    11831185    if( tr_torrentAllowsPex( tor )
    1184       && (( loaded = !tr_bencLoad( tmp, msglen, &val, NULL )))
    1185       && tr_bencDictFindRaw( &val, "added", &added, &added_len ))
    1186     {
    1187         const uint8_t * added_f = NULL;
    1188         tr_pex *        pex;
    1189         size_t          i, n;
    1190         size_t          added_f_len = 0;
    1191         tr_bencDictFindRaw( &val, "added.f", &added_f, &added_f_len );
    1192         pex = tr_peerMgrCompactToPex( added, added_len, added_f, added_f_len, &n );
    1193         for( i=0; i<n; ++i )
    1194             tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
    1195                               TR_PEER_FROM_PEX, pex + i );
    1196         tr_free( pex );
     1186      && ( ( loaded = !tr_bencLoad( tmp, msglen, &val, NULL ) ) ) )
     1187    {
     1188        if( tr_bencDictFindRaw( &val, "added", &added, &added_len ) )
     1189        {
     1190            const uint8_t * added_f = NULL;
     1191            tr_pex *        pex;
     1192            size_t          i, n;
     1193            size_t          added_f_len = 0;
     1194            tr_bencDictFindRaw( &val, "added.f", &added_f, &added_f_len );
     1195            pex =
     1196                tr_peerMgrCompactToPex( added, added_len, added_f, added_f_len,
     1197                                        &n );
     1198            for( i = 0; i < n; ++i )
     1199                tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
     1200                                  TR_PEER_FROM_PEX, pex + i );
     1201            tr_free( pex );
     1202        }
     1203       
     1204        if( tr_bencDictFindRaw( &val, "added6", &added, &added_len ) )
     1205        {
     1206            const uint8_t * added_f = NULL;
     1207            tr_pex *        pex;
     1208            size_t          i, n;
     1209            size_t          added_f_len = 0;
     1210            tr_bencDictFindRaw( &val, "added6.f", &added_f, &added_f_len );
     1211            pex =
     1212                tr_peerMgrCompact6ToPex( added, added_len, added_f, added_f_len,
     1213                                         &n );
     1214            for( i = 0; i < n; ++i )
     1215                tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
     1216                                  TR_PEER_FROM_PEX, pex + i );
     1217            tr_free( pex );
     1218        }
     1219       
    11971220    }
    11981221
     
    20062029}
    20072030
    2008 /* TODO: ipv6 pex */
    20092031static void
    20102032sendPex( tr_peermsgs * msgs )
     
    20132035    {
    20142036        PexDiffs diffs;
     2037        PexDiffs diffs6;
    20152038        tr_pex * newPex = NULL;
     2039        tr_pex * newPex6 = NULL;
    20162040        const int newCount = tr_peerMgrGetPeers( msgs->session->peerMgr,
    20172041                                                 msgs->torrent->info.hash,
    2018                                                  &newPex );
     2042                                                 &newPex, TR_AF_INET );
     2043        const int newCount6 = tr_peerMgrGetPeers( msgs->session->peerMgr,
     2044                                                  msgs->torrent->info.hash,
     2045                                                  &newPex6, TR_AF_INET6 );
    20192046
    20202047        /* build the diffs */
     
    20292056                        tr_pexCompare, sizeof( tr_pex ),
    20302057                        pexDroppedCb, pexAddedCb, pexElementCb, &diffs );
     2058        diffs6.added = tr_new( tr_pex, newCount6 );
     2059        diffs6.addedCount = 0;
     2060        diffs6.dropped = tr_new( tr_pex, msgs->pexCount6 );
     2061        diffs6.droppedCount = 0;
     2062        diffs6.elements = tr_new( tr_pex, newCount6 + msgs->pexCount6 );
     2063        diffs6.elementCount = 0;
     2064        tr_set_compare( msgs->pex6, msgs->pexCount6,
     2065                        newPex6, newCount6,
     2066                        tr_pexCompare, sizeof( tr_pex ),
     2067                        pexDroppedCb, pexAddedCb, pexElementCb, &diffs6 );
    20312068        dbgmsg(
    20322069            msgs,
    20332070            "pex: old peer count %d, new peer count %d, added %d, removed %d",
    2034             msgs->pexCount, newCount, diffs.addedCount, diffs.droppedCount );
    2035 
    2036         if( !diffs.addedCount && !diffs.droppedCount )
     2071            msgs->pexCount, newCount + newCount6,
     2072            diffs.addedCount + diffs6.addedCount,
     2073            diffs.droppedCount + diffs6.droppedCount );
     2074
     2075        if( !diffs.addedCount && !diffs.droppedCount && !diffs6.addedCount &&
     2076            !diffs6.droppedCount )
    20372077        {
    20382078            tr_free( diffs.elements );
     2079            tr_free( diffs6.elements );
    20392080        }
    20402081        else
     
    20512092            msgs->pex = diffs.elements;
    20522093            msgs->pexCount = diffs.elementCount;
     2094            tr_free( msgs->pex6 );
     2095            msgs->pex6 = diffs6.elements;
     2096            msgs->pexCount6 = diffs6.elementCount;
    20532097
    20542098            /* build the pex payload */
    2055             tr_bencInitDict( &val, 3 );
     2099            tr_bencInitDict( &val, 3 ); /* ipv6 support: left as 3:
     2100                                         * speed vs. likelihood? */
    20562101
    20572102            /* "added" */
    20582103            tmp = walk = tr_new( uint8_t, diffs.addedCount * 6 );
    2059             for( i = 0; i < diffs.addedCount; ++i ) {
     2104            for( i = 0; i < diffs.addedCount; ++i )
     2105            {
    20602106                memcpy( walk, &diffs.added[i].addr.addr, 4 ); walk += 4;
    20612107                memcpy( walk, &diffs.added[i].port, 2 ); walk += 2;
     
    20752121            /* "dropped" */
    20762122            tmp = walk = tr_new( uint8_t, diffs.droppedCount * 6 );
    2077             for( i = 0; i < diffs.droppedCount; ++i ) {
     2123            for( i = 0; i < diffs.droppedCount; ++i )
     2124            {
    20782125                memcpy( walk, &diffs.dropped[i].addr.addr, 4 ); walk += 4;
    20792126                memcpy( walk, &diffs.dropped[i].port, 2 ); walk += 2;
     
    20812128            assert( ( walk - tmp ) == diffs.droppedCount * 6 );
    20822129            tr_bencDictAddRaw( &val, "dropped", tmp, walk - tmp );
     2130            tr_free( tmp );
     2131           
     2132            /* "added6" */
     2133            tmp = walk = tr_new( uint8_t, diffs6.addedCount * 18 );
     2134            for( i = 0; i < diffs6.addedCount; ++i )
     2135            {
     2136                memcpy( walk, &diffs6.added[i].addr.addr.addr6.s6_addr, 16 );
     2137                walk += 16;
     2138                memcpy( walk, &diffs6.added[i].port, 2 );
     2139                walk += 2;
     2140            }
     2141            assert( ( walk - tmp ) == diffs6.addedCount * 18 );
     2142            tr_bencDictAddRaw( &val, "added6", tmp, walk - tmp );
     2143            tr_free( tmp );
     2144           
     2145            /* "added6.f" */
     2146            tmp = walk = tr_new( uint8_t, diffs6.addedCount );
     2147            for( i = 0; i < diffs6.addedCount; ++i )
     2148                *walk++ = diffs6.added[i].flags;
     2149            assert( ( walk - tmp ) == diffs6.addedCount );
     2150            tr_bencDictAddRaw( &val, "added6.f", tmp, walk - tmp );
     2151            tr_free( tmp );
     2152           
     2153            /* "dropped6" */
     2154            tmp = walk = tr_new( uint8_t, diffs6.droppedCount * 18 );
     2155            for( i = 0; i < diffs6.droppedCount; ++i )
     2156            {
     2157                memcpy( walk, &diffs6.dropped[i].addr.addr.addr6.s6_addr, 16 );
     2158                walk += 16;
     2159                memcpy( walk, &diffs6.dropped[i].port, 2 );
     2160                walk += 2;
     2161            }
     2162            assert( ( walk - tmp ) == diffs6.droppedCount * 18);
     2163            tr_bencDictAddRaw( &val, "dropped6", tmp, walk - tmp );
    20832164            tr_free( tmp );
    20842165
     
    21002181        tr_free( diffs.dropped );
    21012182        tr_free( newPex );
     2183        tr_free( diffs6.added );
     2184        tr_free( diffs6.dropped );
     2185        tr_free( newPex6 );
    21022186
    21032187        msgs->clientSentPexAt = time( NULL );
     
    21762260        evbuffer_free( msgs->incoming.block );
    21772261        evbuffer_free( msgs->outMessages );
     2262        tr_free( msgs->pex6 );
    21782263        tr_free( msgs->pex );
    21792264
  • trunk/libtransmission/port-forwarding.c

    r7392 r7397  
    3939    tr_port_forwarding    upnpStatus;
    4040
    41     int                   bindPort;
    42     int                   bindSocket;
    43     int                   publicPort;
     41    tr_bool               shouldChange;
     42    tr_socketList       * bindSockets;
     43    tr_port               publicPort;
    4444
    4545    tr_timer            * pulseTimer;
     
    8585natPulse( tr_shared * s )
    8686{
    87     const int port = s->publicPort;
    88     const int isEnabled = s->isEnabled && !s->isShuttingDown;
    89     int       oldStatus;
    90     int       newStatus;
     87    const tr_port port = s->publicPort;
     88    const int     isEnabled = s->isEnabled && !s->isShuttingDown;
     89    int           oldStatus;
     90    int           newStatus;
    9191
    9292    oldStatus = tr_sharedTraversalStatus( s );
     
    101101}
    102102
    103 static void
    104 incomingPeersPulse( tr_shared * s )
    105 {
    106     tr_bool allPaused;
    107     tr_torrent * tor;
    108 
    109     if( s->bindSocket >= 0 && ( s->bindPort != s->publicPort ) )
    110     {
    111         tr_ninf( getKey( ), _( "Closing port %d" ), s->bindPort );
    112         tr_netClose( s->bindSocket );
    113         s->bindSocket = -1;
    114     }
    115 
    116     if( ( s->publicPort > 0 ) && ( s->bindPort != s->publicPort ) )
    117     {
    118         int socket;
    119         errno = 0;
    120         socket = tr_netBindTCP( &tr_inaddr_any, s->publicPort );
    121         if( socket >= 0 )
    122         {
    123             tr_ninf( getKey( ),
    124                      _(
    125                          "Opened port %d to listen for incoming peer connections" ),
    126                      s->publicPort );
    127             s->bindPort = s->publicPort;
    128             s->bindSocket = socket;
    129             listen( s->bindSocket, 5 );
    130         }
    131         else
    132         {
    133             tr_nerr( getKey( ),
    134                     _(
    135                         "Couldn't open port %d to listen for incoming peer connections (errno %d - %s)" ),
    136                     s->publicPort, errno, tr_strerror( errno ) );
    137             s->bindPort = -1;
    138             s->bindSocket = -1;
    139         }
    140     }
    141 
    142     /* see if any torrents aren't paused */
    143     allPaused = 1;
    144     tor = NULL;
    145     while(( tor = tr_torrentNext( s->session, tor ))) {
    146         if( TR_STATUS_IS_ACTIVE( tr_torrentGetActivity( tor ))) {
    147             allPaused = 0;
    148             break;
    149         }
    150     }
    151 
    152     /* if we have any running torrents, check for new incoming peer connections */
    153     while( !allPaused ) 
    154     {
    155         int         socket;
    156         tr_port     port;
    157         tr_address  addr;
    158 
    159         if( s->bindSocket < 0 )
    160             break;
    161 
    162         socket = tr_netAccept( s->session, s->bindSocket, &addr, &port );
    163         if( socket < 0 )
    164             break;
    165 
     103/*
     104 * Callbacks for socket list
     105 */
     106static void
     107closeCb( int * const socket,
     108         tr_address * const addr,
     109         void * const userData )
     110{
     111    tr_shared * s = ( tr_shared * )userData;
     112    if( *socket >= 0 )
     113    {
     114        tr_ninf( getKey( ), _( "Closing port %d on %s" ), s->publicPort,
     115                tr_ntop_non_ts( addr ) );
     116        tr_netClose( *socket );
     117    }
     118}
     119
     120static void
     121acceptCb( int * const socket,
     122          tr_address * const addr,
     123          void * const userData )
     124{
     125    tr_shared * s = ( tr_shared * )userData;
     126    tr_address clientAddr;
     127    tr_port clientPort;
     128    int clientSocket;
     129    clientSocket = tr_netAccept( s->session, *socket, &clientAddr, &clientPort );
     130    if( clientSocket > 0 )
     131    {
    166132        tr_deepLog( __FILE__, __LINE__, NULL,
    167133                   "New INCOMING connection %d (%s)",
    168                    socket, tr_peerIoAddrStr( &addr, port ) );
    169 
    170         tr_peerMgrAddIncoming( s->session->peerMgr, &addr, port, socket );
    171     }
     134                   clientSocket, tr_peerIoAddrStr( &clientAddr, clientPort ) );
     135       
     136        tr_peerMgrAddIncoming( s->session->peerMgr, &clientAddr, clientPort,
     137                              clientSocket );
     138    }
     139}
     140
     141static void
     142bindCb( int * const socket,
     143        tr_address * const addr,
     144        void * const userData )
     145{
     146    tr_shared * s = ( tr_shared * )userData;
     147    *socket = tr_netBindTCP( addr, s->publicPort, FALSE );
     148    if( *socket >= 0 )
     149    {
     150        tr_ninf( getKey( ),
     151                _( "Opened port %d on %s to listen for incoming peer connections" ),
     152                s->publicPort, tr_ntop_non_ts( addr ) );
     153        listen( *socket, 10 );
     154    }
     155    else
     156    {
     157        tr_nerr( getKey( ),
     158                _(
     159                  "Couldn't open port %d on %s to listen for incoming peer connections (errno %d - %s)" ),
     160                s->publicPort, tr_ntop_non_ts( addr ), errno, tr_strerror( errno ) );
     161    }
     162}
     163
     164static void
     165incomingPeersPulse( tr_shared * s )
     166{
     167    int allPaused;
     168    tr_torrent * tor;
     169   
     170    if( s->shouldChange )
     171    {
     172        tr_socketListForEach( s->bindSockets, &closeCb, s );
     173        s->shouldChange = FALSE;
     174        if( s->publicPort > 0 )
     175            tr_socketListForEach( s->bindSockets, &bindCb, s );
     176    }
     177   
     178    /* see if any torrents aren't paused */
     179    allPaused = 1;
     180    tor = NULL;
     181    while( ( tor = tr_torrentNext( s->session, tor ) ) )
     182    {
     183        if( TR_STATUS_IS_ACTIVE( tr_torrentGetActivity( tor ) ) )
     184        {
     185            allPaused = 0;
     186            break;
     187        }
     188    }
     189   
     190    /* if we have any running torrents, check for new incoming peer connections */
     191    /* (jhujhiti):
     192     * This has been changed from a loop that will end when the listener queue
     193     * is exhausted to one that will only check for one connection at a time.
     194     * I think it unlikely that we get many more than one connection in the
     195     * time between pulses (currently one second). However, just to be safe,
     196     * I have increased the length of the listener queue from 5 to 10
     197     * (see acceptCb() above). */
     198    if( !allPaused )
     199        tr_socketListForEach( s->bindSockets, &acceptCb, s );
    172200}
    173201
     
    188216        tr_ninf( getKey( ), _( "Stopped" ) );
    189217        tr_timerFree( &shared->pulseTimer );
    190         tr_netClose( shared->bindSocket );
     218        tr_socketListForEach( shared->bindSockets, &closeCb, shared );
    191219        tr_natpmpClose( shared->natpmp );
    192220        tr_upnpClose( shared->upnp );
     
    203231***/
    204232
     233static tr_socketList *
     234setupBindSockets( tr_port port )
     235{
     236    /* Do we care if an address is in use? Probably not, since it will be
     237     * caught later. This will only set up the list of sockets to bind. */
     238    int s4, s6;
     239    tr_socketList * socks = NULL;
     240    s6 = tr_netBindTCP( &tr_in6addr_any, port, TRUE );
     241    if( s6 >= 0 || -s6 != EAFNOSUPPORT ) /* we support ipv6 */
     242    {
     243        socks = tr_socketListNew( &tr_in6addr_any );
     244        listen( s6, 1 );
     245    }
     246    s4 = tr_netBindTCP( &tr_inaddr_any, port, TRUE );
     247    if( s4 >= 0 ) /* we bound *with* the ipv6 socket bound (need both)
     248                   * or only have ipv4 */
     249    {
     250        if( socks )
     251            tr_socketListAppend( socks, &tr_inaddr_any );
     252        else
     253            socks = tr_socketListNew( &tr_inaddr_any );
     254        tr_netClose( s4 );
     255    }
     256    if( s6 >= 0 )
     257        tr_netClose( s6 );
     258    return socks;
     259}
     260
    205261tr_shared *
    206262tr_sharedInit( tr_session  * session,
     
    212268    s->session      = session;
    213269    s->publicPort   = publicPort;
    214     s->bindPort     = -1;
    215     s->bindSocket   = -1;
     270    s->shouldChange = TRUE;
     271    s->bindSockets  = setupBindSockets( publicPort );
     272    s->shouldChange = TRUE;
    216273    s->natpmp       = tr_natpmpInit( );
    217274    s->upnp         = tr_upnpInit( );
     
    235292    tr_torrent * tor = NULL;
    236293
    237     s->publicPort = port;
     294    s->publicPort   = port;
     295    s->shouldChange = TRUE;
    238296
    239297    while( ( tor = tr_torrentNext( s->session, tor ) ) )
  • trunk/libtransmission/resume.c

    r7249 r7397  
    3535#define KEY_PAUSED          "paused"
    3636#define KEY_PEERS           "peers"
     37#define KEY_PEERS6          "peers6"
    3738#define KEY_PRIORITY        "priority"
    3839#define KEY_PROGRESS        "progress"
     
    6263***/
    6364
    64 /* TODO: resume peers6 */
    6565static void
    6666savePeers( tr_benc *          dict,
    6767           const tr_torrent * tor )
    6868{
    69     tr_pex *  pex = NULL;
    70     const int count = tr_peerMgrGetPeers( tor->session->peerMgr,
    71                                           tor->info.hash, &pex );
     69    tr_pex * pex = NULL;
     70    int count = tr_peerMgrGetPeers( tor->session->peerMgr,
     71                                    tor->info.hash, &pex, TR_AF_INET );
    7272
    7373    if( count > 0 )
    7474        tr_bencDictAddRaw( dict, KEY_PEERS, pex, sizeof( tr_pex ) * count );
     75   
     76    count = tr_peerMgrGetPeers( tor->session->peerMgr, tor->info.hash, &pex,
     77                                TR_AF_INET6 );
     78    if( count > 0 )
     79        tr_bencDictAddRaw( dict, KEY_PEERS6, pex, sizeof( tr_pex ) * count );
     80   
    7581    tr_free( pex );
    7682}
     
    95101                              tor->info.hash, TR_PEER_FROM_CACHE, &pex );
    96102        }
    97         tr_tordbg( tor, "Loaded %d peers from resume file", count );
     103        tr_tordbg( tor, "Loaded %d IPv4 peers from resume file", count );
     104        ret = TR_FR_PEERS;
     105    }
     106   
     107    if( tr_bencDictFindRaw( dict, KEY_PEERS6, &str, &len ) )
     108    {
     109        int       i;
     110        const int count = len / sizeof( tr_pex );
     111        for( i = 0; i < count; ++i )
     112        {
     113            tr_pex pex;
     114            memcpy( &pex, str + ( i * sizeof( tr_pex ) ), sizeof( tr_pex ) );
     115            tr_peerMgrAddPex( tor->session->peerMgr,
     116                              tor->info.hash, TR_PEER_FROM_CACHE, &pex );
     117        }
     118        tr_tordbg( tor, "Loaded %d IPv6 peers from resume file", count );
    98119        ret = TR_FR_PEERS;
    99120    }
  • trunk/libtransmission/torrent.c

    r7385 r7397  
    223223        {
    224224            size_t   i, n;
    225             tr_pex * pex = tr_peerMgrCompactToPex( event->compact,
    226                                                    event->compactLen,
    227                                                    NULL, 0, &n );
    228             if( event->allAreSeeds )
     225            tr_pex * pex = tr_peerMgrArrayToPex( event->compact,
     226                                                 event->compactLen, &n );
     227             if( event->allAreSeeds )
    229228                tr_tordbg( tor, "Got %d seeds from tracker", (int)n );
    230229            else
  • trunk/libtransmission/tracker.c

    r7266 r7397  
    241241}
    242242
     243static void
     244publishNewPeersCompact( tr_tracker * t,
     245                        int          allAreSeeds,
     246                        void       * compact,
     247                        int          compactLen )
     248{
     249    int i;
     250    uint8_t *array, *walk, *compactWalk;
     251    const int peerCount = compactLen / 6;
     252    const int arrayLen = peerCount * ( sizeof( tr_address ) + 2 );
     253    tr_address addr;
     254    tr_port port;
     255   
     256    addr.type = TR_AF_INET;
     257    memset( &addr.addr, 0x00, sizeof( addr.addr ) );
     258    array = tr_new( uint8_t, arrayLen );
     259    for ( i = 0, walk = array, compactWalk = compact ; i < peerCount ; i++ )
     260    {
     261        memcpy( &addr.addr.addr4, compactWalk, 4 );
     262        memcpy( &port, compactWalk + 4, 2 );
     263       
     264        memcpy( walk, &addr, sizeof( addr ) );
     265        memcpy( walk + sizeof( addr ), &port, 2 );
     266       
     267        walk += sizeof( tr_address ) + 2;
     268        compactWalk += 6;
     269    }
     270    publishNewPeers( t, allAreSeeds, array, arrayLen );
     271    tr_free( array );
     272}
     273
     274static void
     275publishNewPeersCompact6( tr_tracker * t,
     276                         int          allAreSeeds,
     277                         void       * compact,
     278                         int          compactLen )
     279{
     280    int i;
     281    uint8_t *array, *walk, *compactWalk;
     282    const int peerCount = compactLen / 18;
     283    const int arrayLen = peerCount * ( sizeof( tr_address ) + 2 );
     284    tr_address addr;
     285    tr_port port;
     286   
     287    addr.type = TR_AF_INET6;
     288    memset( &addr.addr, 0x00, sizeof( addr.addr ) );
     289    array = tr_new( uint8_t, arrayLen );
     290    for ( i = 0, walk = array, compactWalk = compact ; i < peerCount ; i++ )
     291    {
     292        memcpy( &addr.addr.addr6, compactWalk, 16 );
     293        memcpy( &port, compactWalk + 16, 2 );
     294       
     295        memcpy( walk, &addr, sizeof( addr ) );
     296        memcpy( walk + sizeof( addr ), &port, 2 );
     297       
     298        walk += sizeof( tr_address ) + 2;
     299        compactWalk += 6;
     300    }
     301    publishNewPeers( t, allAreSeeds, array, arrayLen );
     302    tr_free( array );
     303}
     304
    243305/***
    244306****
     
    277339}
    278340
    279 /* Convert to compact form */
    280341static uint8_t *
    281342parseOldPeers( tr_benc * bePeers,
    282343               size_t *  byteCount )
    283344{
    284     /* TODO: IPv6 wtf */
    285345    int       i;
    286     uint8_t * compact, *walk;
     346    uint8_t * array, *walk;
    287347    const int peerCount = bePeers->val.l.count;
    288348
    289349    assert( bePeers->type == TYPE_LIST );
    290350
    291     compact = tr_new( uint8_t, peerCount * 6 );
    292 
    293     for( i = 0, walk = compact; i < peerCount; ++i )
    294     {
    295         const char * s;
    296         int64_t      itmp;
    297         tr_address   addr;
    298         tr_port      port;
    299         tr_benc    * peer = &bePeers->val.l.vals[i];
    300  
    301         if( tr_bencDictFindStr( peer, "ip", &s ) )
    302         {
    303             if( tr_pton( s, &addr ) == NULL )
    304                 continue;
    305             if( addr.type != TR_AF_INET )
    306                 continue;
    307         }
    308  
    309         memcpy( walk, &addr.addr.addr4.s_addr, 4 );
    310         walk += 4;
    311 
     351    array = tr_new( uint8_t, peerCount * ( sizeof( tr_address ) + 2 ) );
     352
     353    for( i = 0, walk = array; i < peerCount; ++i )
     354    {
     355        const char * s;
     356        int64_t      itmp;
     357        tr_address   addr;
     358        tr_port    port;
     359        tr_benc *    peer = &bePeers->val.l.vals[i];
     360
     361        if( tr_bencDictFindStr( peer, "ip", &s ) )
     362        {
     363            if( tr_pton( s, &addr ) == NULL )
     364                continue;
     365        }
    312366        if( !tr_bencDictFindInt( peer, "port",
    313367                                 &itmp ) || itmp < 0 || itmp > 0xffff )
    314368            continue;
    315369
     370        memcpy( walk, &addr, sizeof( tr_address ) );
    316371        port = htons( itmp );
    317         memcpy( walk, &port, 2 );
    318         walk += 2;
    319     }
    320 
    321     *byteCount = peerCount * 6;
    322     return compact;
     372        memcpy( walk + sizeof( tr_address ), &port, 2 );
     373        walk += sizeof( tr_address ) + 2;
     374    }
     375
     376    *byteCount = peerCount * sizeof( tr_address ) + 2;
     377    return array;
    323378}
    324379
     
    433488                if( tmp->type == TYPE_STR ) /* "compact" extension */
    434489                {
    435                     publishNewPeers( t, allAreSeeds, tmp->val.s.s,
    436                                      tmp->val.s.i );
     490                    publishNewPeersCompact( t, allAreSeeds, tmp->val.s.s,
     491                                            tmp->val.s.i );
    437492                }
    438493                else if( tmp->type == TYPE_LIST ) /* original protocol */
    439494                {
    440495                    size_t    byteCount = 0;
    441                     uint8_t * compact = parseOldPeers( tmp, &byteCount );
    442                     publishNewPeers( t, allAreSeeds, compact, byteCount );
    443                     tr_free( compact );
     496                    uint8_t * array = parseOldPeers( tmp, &byteCount );
     497                    publishNewPeers( t, allAreSeeds, array, byteCount );
     498                    tr_free( array );
     499                }
     500            }
     501           
     502            if( ( tmp = tr_bencDictFind( &benc, "peers6" ) ) )
     503            {
     504                const int allAreSeeds = incomplete == 0;
     505               
     506                if( tmp->type == TYPE_STR ) /* "compact" extension */
     507                {
     508                    publishNewPeersCompact6( t, allAreSeeds, tmp->val.s.s,
     509                                             tmp->val.s.i );
    444510                }
    445511            }
Note: See TracChangeset for help on using the changeset viewer.