Ticket #252: ipv6-phase-3.diff

File ipv6-phase-3.diff, 40.3 KB (added by jhujhiti, 12 years ago)

final patch against r7306

  • libtransmission/peer-io.c

     
    260260    io->magicNumber = MAGIC_NUMBER;
    261261    io->crypto = tr_cryptoNew( torrentHash, isIncoming );
    262262    io->session = session;
    263     io->addr = *addr;
     263    memcpy( &io->addr, addr, sizeof( tr_address ) );
    264264    io->port = port;
    265265    io->socket = socket;
    266266    io->isIncoming = isIncoming != 0;
  • libtransmission/peer-msgs.c

     
    268268    uint8_t         state;
    269269    uint8_t         ut_pex_id;
    270270    uint16_t        pexCount;
     271    uint16_t        pexCount6;
    271272    uint16_t        minActiveRequests;
    272273    uint16_t        maxActiveRequests;
    273274
     
    306307    struct tr_incoming    incoming;
    307308
    308309    tr_pex *              pex;
     310    tr_pex *              pex6;
    309311};
    310312
    311313/**
     
    11621164    tr_peerIoReadBytes( msgs->io, inbuf, tmp, msglen );
    11631165
    11641166    if( tr_torrentAllowsPex( tor )
    1165       && (( loaded = !tr_bencLoad( tmp, msglen, &val, NULL )))
    1166       && tr_bencDictFindRaw( &val, "added", &added, &added_len ))
     1167      && ( ( loaded = !tr_bencLoad( tmp, msglen, &val, NULL ) ) ) )
    11671168    {
    1168         const uint8_t * added_f = NULL;
    1169         tr_pex *        pex;
    1170         size_t          i, n;
    1171         size_t          added_f_len = 0;
    1172         tr_bencDictFindRaw( &val, "added.f", &added_f, &added_f_len );
    1173         pex = tr_peerMgrCompactToPex( added, added_len, added_f, added_f_len, &n );
    1174         for( i=0; i<n; ++i )
    1175             tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
    1176                               TR_PEER_FROM_PEX, pex + i );
    1177         tr_free( pex );
     1169        if( tr_bencDictFindRaw( &val, "added", &added, &added_len ) )
     1170        {
     1171            const uint8_t * added_f = NULL;
     1172            tr_pex *        pex;
     1173            size_t          i, n;
     1174            size_t          added_f_len = 0;
     1175            tr_bencDictFindRaw( &val, "added.f", &added_f, &added_f_len );
     1176            pex =
     1177                tr_peerMgrCompactToPex( added, added_len, added_f, added_f_len,
     1178                                        &n );
     1179            for( i = 0; i < n; ++i )
     1180                tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
     1181                                  TR_PEER_FROM_PEX, pex + i );
     1182            tr_free( pex );
     1183        }
     1184       
     1185        if( tr_bencDictFindRaw( &val, "added6", &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, "added6.f", &added_f, &added_f_len );
     1192            pex =
     1193                tr_peerMgrCompact6ToPex( added, added_len, added_f, added_f_len,
     1194                                         &n );
     1195            for( i = 0; i < n; ++i )
     1196                tr_peerMgrAddPex( msgs->session->peerMgr, tor->info.hash,
     1197                                  TR_PEER_FROM_PEX, pex + i );
     1198            tr_free( pex );
     1199        }
     1200       
    11781201    }
    11791202
    11801203    if( loaded )
     
    19872010    diffs->elements[diffs->elementCount++] = *pex;
    19882011}
    19892012
    1990 /* TODO: ipv6 pex */
    19912013static void
    19922014sendPex( tr_peermsgs * msgs )
    19932015{
    19942016    if( msgs->peerSupportsPex && tr_torrentAllowsPex( msgs->torrent ) )
    19952017    {
    19962018        PexDiffs diffs;
     2019        PexDiffs diffs6;
    19972020        tr_pex * newPex = NULL;
     2021        tr_pex * newPex6 = NULL;
    19982022        const int newCount = tr_peerMgrGetPeers( msgs->session->peerMgr,
    19992023                                                 msgs->torrent->info.hash,
    2000                                                  &newPex );
     2024                                                 &newPex, TR_AF_INET );
     2025        const int newCount6 = tr_peerMgrGetPeers( msgs->session->peerMgr,
     2026                                                  msgs->torrent->info.hash,
     2027                                                  &newPex6, TR_AF_INET6 );
    20012028
    20022029        /* build the diffs */
    20032030        diffs.added = tr_new( tr_pex, newCount );
     
    20102037                        newPex, newCount,
    20112038                        tr_pexCompare, sizeof( tr_pex ),
    20122039                        pexDroppedCb, pexAddedCb, pexElementCb, &diffs );
     2040        diffs6.added = tr_new( tr_pex, newCount6 );
     2041        diffs6.addedCount = 0;
     2042        diffs6.dropped = tr_new( tr_pex, msgs->pexCount6 );
     2043        diffs6.droppedCount = 0;
     2044        diffs6.elements = tr_new( tr_pex, newCount6 + msgs->pexCount6 );
     2045        diffs6.elementCount = 0;
     2046        tr_set_compare( msgs->pex6, msgs->pexCount6,
     2047                        newPex6, newCount6,
     2048                        tr_pexCompare, sizeof( tr_pex ),
     2049                        pexDroppedCb, pexAddedCb, pexElementCb, &diffs6 );
    20132050        dbgmsg(
    20142051            msgs,
    20152052            "pex: old peer count %d, new peer count %d, added %d, removed %d",
    2016             msgs->pexCount, newCount, diffs.addedCount, diffs.droppedCount );
     2053            msgs->pexCount, newCount + newCount6,
     2054            diffs.addedCount + diffs6.addedCount,
     2055            diffs.droppedCount + diffs6.droppedCount );
    20172056
    2018         if( !diffs.addedCount && !diffs.droppedCount )
     2057        if( !diffs.addedCount && !diffs.droppedCount && !diffs6.addedCount &&
     2058            !diffs6.droppedCount )
    20192059        {
    20202060            tr_free( diffs.elements );
     2061            tr_free( diffs6.elements );
    20212062        }
    20222063        else
    20232064        {
     
    20322073            tr_free( msgs->pex );
    20332074            msgs->pex = diffs.elements;
    20342075            msgs->pexCount = diffs.elementCount;
     2076            tr_free( msgs->pex6 );
     2077            msgs->pex6 = diffs6.elements;
     2078            msgs->pexCount6 = diffs6.elementCount;
    20352079
    20362080            /* build the pex payload */
    2037             tr_bencInitDict( &val, 3 );
     2081            tr_bencInitDict( &val, 3 ); /* ipv6 support: left as 3:
     2082                                         * speed vs. likelihood? */
    20382083
    20392084            /* "added" */
    20402085            tmp = walk = tr_new( uint8_t, diffs.addedCount * 6 );
    2041             for( i = 0; i < diffs.addedCount; ++i ) {
     2086            for( i = 0; i < diffs.addedCount; ++i )
     2087            {
    20422088                memcpy( walk, &diffs.added[i].addr.addr, 4 ); walk += 4;
    20432089                memcpy( walk, &diffs.added[i].port, 2 ); walk += 2;
    20442090            }
     
    20562102
    20572103            /* "dropped" */
    20582104            tmp = walk = tr_new( uint8_t, diffs.droppedCount * 6 );
    2059             for( i = 0; i < diffs.droppedCount; ++i ) {
     2105            for( i = 0; i < diffs.droppedCount; ++i )
     2106            {
    20602107                memcpy( walk, &diffs.dropped[i].addr.addr, 4 ); walk += 4;
    20612108                memcpy( walk, &diffs.dropped[i].port, 2 ); walk += 2;
    20622109            }
    20632110            assert( ( walk - tmp ) == diffs.droppedCount * 6 );
    20642111            tr_bencDictAddRaw( &val, "dropped", tmp, walk - tmp );
    20652112            tr_free( tmp );
     2113           
     2114            /* "added6" */
     2115            tmp = walk = tr_new( uint8_t, diffs6.addedCount * 18 );
     2116            for( i = 0; i < diffs6.addedCount; ++i )
     2117            {
     2118                memcpy( walk, &diffs6.added[i].addr.addr.addr6.s6_addr, 16 );
     2119                walk += 16;
     2120                memcpy( walk, &diffs6.added[i].port, 2 );
     2121                walk += 2;
     2122            }
     2123            assert( ( walk - tmp ) == diffs6.addedCount * 18 );
     2124            tr_bencDictAddRaw( &val, "added6", tmp, walk - tmp );
     2125            tr_free( tmp );
     2126           
     2127            /* "added6.f" */
     2128            tmp = walk = tr_new( uint8_t, diffs6.addedCount );
     2129            for( i = 0; i < diffs6.addedCount; ++i )
     2130                *walk++ = diffs6.added[i].flags;
     2131            assert( ( walk - tmp ) == diffs6.addedCount );
     2132            tr_bencDictAddRaw( &val, "added6.f", tmp, walk - tmp );
     2133            tr_free( tmp );
     2134           
     2135            /* "dropped6" */
     2136            tmp = walk = tr_new( uint8_t, diffs6.droppedCount * 18 );
     2137            for( i = 0; i < diffs6.droppedCount; ++i )
     2138            {
     2139                memcpy( walk, &diffs6.dropped[i].addr.addr.addr6.s6_addr, 16 );
     2140                walk += 16;
     2141                memcpy( walk, &diffs6.dropped[i].port, 2 );
     2142                walk += 2;
     2143            }
     2144            assert( ( walk - tmp ) == diffs6.droppedCount * 18);
     2145            tr_bencDictAddRaw( &val, "dropped6", tmp, walk - tmp );
     2146            tr_free( tmp );
    20662147
    20672148            /* write the pex message */
    20682149            benc = tr_bencSave( &val, &bencLen );
     
    20812162        tr_free( diffs.added );
    20822163        tr_free( diffs.dropped );
    20832164        tr_free( newPex );
     2165        tr_free( diffs6.added );
     2166        tr_free( diffs6.dropped );
     2167        tr_free( newPex6 );
    20842168
    20852169        msgs->clientSentPexAt = time( NULL );
    20862170    }
     
    21602244        tr_bitfieldFree( msgs->peerAllowedPieces );
    21612245        evbuffer_free( msgs->incoming.block );
    21622246        evbuffer_free( msgs->outMessages );
     2247        tr_free( msgs->pex6 );
    21632248        tr_free( msgs->pex );
    21642249
    21652250        memset( msgs, ~0, sizeof( tr_peermsgs ) );
  • libtransmission/peer-mgr.c

     
    13391339    t = getExistingTorrent( manager, torrentHash );
    13401340    if( !tr_sessionIsAddressBlocked( t->manager->session, &pex->addr ) )
    13411341        ensureAtomExists( t, &pex->addr, pex->port, pex->flags, from );
    1342 
     1342   
    13431343    managerUnlock( manager );
    13441344}
    13451345
     
    13681368    return pex;
    13691369}
    13701370
     1371tr_pex *
     1372tr_peerMgrCompact6ToPex( const void    * compact,
     1373                         size_t          compactLen,
     1374                         const uint8_t * added_f,
     1375                         size_t          added_f_len,
     1376                         size_t        * pexCount )
     1377{
     1378    size_t          i;
     1379    size_t          n = compactLen / 18;
     1380    const uint8_t * walk = compact;
     1381    tr_pex *        pex = tr_new0( tr_pex, n );
     1382   
     1383    for( i = 0; i < n; ++i )
     1384    {
     1385        pex[i].addr.type = TR_AF_INET6;
     1386        memcpy( &pex[i].addr.addr.addr6.s6_addr, walk, 16 ); walk += 16;
     1387        memcpy( &pex[i].port, walk, 2 ); walk += 2;
     1388        if( added_f && ( n == added_f_len ) )
     1389            pex[i].flags = added_f[i];
     1390    }
     1391   
     1392    *pexCount = n;
     1393    return pex;
     1394}
     1395
     1396tr_pex *
     1397tr_peerMgrArrayToPex( const void * array,
     1398                      size_t       arrayLen,
     1399                      size_t      * pexCount )
     1400{
     1401    size_t          i;
     1402    size_t          n = arrayLen / ( sizeof( tr_address ) + 2 );
     1403    /*size_t          n = arrayLen / sizeof( tr_peerArrayElement );*/
     1404    const uint8_t * walk = array;
     1405    tr_pex        * pex = tr_new0( tr_pex, n );
     1406   
     1407    for( i = 0 ; i < n ; i++ ) {
     1408        memcpy( &pex[i].addr, walk, sizeof( tr_address ) );
     1409        memcpy( &pex[i].port, walk + sizeof( tr_address ), 2 );
     1410        pex[i].flags = 0x00;
     1411        walk += sizeof( tr_address ) + 2;
     1412    }
     1413   
     1414    *pexCount = n;
     1415    return pex;
     1416}
     1417
    13711418/**
    13721419***
    13731420**/
     
    14271474}
    14281475
    14291476int
    1430 tr_peerMgrGetPeers( tr_peerMgr *    manager,
     1477tr_peerMgrGetPeers( tr_peerMgr    * manager,
    14311478                    const uint8_t * torrentHash,
    1432                     tr_pex **       setme_pex )
     1479                    tr_pex       ** setme_pex,
     1480                    uint8_t         af)
    14331481{
    14341482    int peerCount = 0;
     1483    int peersReturning = 0;
    14351484    const Torrent *  t;
    14361485
    14371486    managerLock( manager );
     
    14451494    {
    14461495        int i;
    14471496        const tr_peer ** peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
     1497        /* for now, this will waste memory on torrents that have both
     1498         * ipv6 and ipv4 peers */
    14481499        tr_pex * pex = tr_new( tr_pex, peerCount );
    14491500        tr_pex * walk = pex;
    14501501
    14511502        for( i=0; i<peerCount; ++i, ++walk )
    14521503        {
    14531504            const tr_peer * peer = peers[i];
    1454             const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
    1455 
    1456             walk->addr = peer->addr;
    1457             walk->port = peer->port;
    1458             walk->flags = 0;
    1459             if( peerPrefersCrypto( peer ) )
    1460                 walk->flags |= ADDED_F_ENCRYPTION_FLAG;
    1461             if( ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 ) )
    1462                 walk->flags |= ADDED_F_SEED_FLAG;
     1505            if( peer->addr.type == af )
     1506            {
     1507                const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
     1508                memcpy( &walk->addr, &peer->addr, sizeof( walk->addr ) );
     1509                walk->port = peer->port;
     1510                walk->flags = 0;
     1511                if( peerPrefersCrypto( peer ) )
     1512                    walk->flags |= ADDED_F_ENCRYPTION_FLAG;
     1513                if( ( atom->uploadOnly == UPLOAD_ONLY_YES ) ||
     1514                    ( peer->progress >= 1.0 ) )
     1515                    walk->flags |= ADDED_F_SEED_FLAG;
     1516                peersReturning++;
     1517            }
    14631518        }
    14641519
    14651520        assert( ( walk - pex ) == peerCount );
    1466         qsort( pex, peerCount, sizeof( tr_pex ), tr_pexCompare );
     1521        qsort( pex, peersReturning, sizeof( tr_pex ), tr_pexCompare );
    14671522        *setme_pex = pex;
    14681523    }
    14691524
    14701525    managerUnlock( manager );
    1471     return peerCount;
     1526    return peersReturning;
    14721527}
    14731528
    14741529static int reconnectPulse( void * vtorrent );
     
    17781833        const tr_peer *          peer = peers[i];
    17791834        const struct peer_atom * atom = getExistingAtom( t, &peer->addr );
    17801835        tr_peer_stat *           stat = ret + i;
     1836        tr_address               norm_addr;
    17811837
    1782         tr_ntop( &peer->addr, stat->addr, sizeof(stat->addr) );
    1783         tr_strlcpy( stat->client, (peer->client ? peer->client : ""), sizeof(stat->client) );
     1838        memcpy( &norm_addr, &peer->addr, sizeof( tr_address ) );
     1839        tr_normalizeV4Mapped( &norm_addr );
     1840        tr_ntop( &norm_addr, stat->addr, sizeof( stat->addr ) );
     1841        tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ),
     1842                   sizeof( stat->client ) );
    17841843        stat->port               = ntohs( peer->port );
    17851844        stat->from               = atom->from;
    17861845        stat->progress           = peer->progress;
  • libtransmission/peer-mgr.h

     
    6868                                 size_t          added_f_len,
    6969                                 size_t        * setme_pex_count );
    7070
     71tr_pex * tr_peerMgrCompact6ToPex( const void    * compact,
     72                                  size_t          compactLen,
     73                                  const uint8_t * added_f,
     74                                  size_t          added_f_len,
     75                                  size_t        * pexCount );
     76
     77tr_pex * tr_peerMgrArrayToPex( const void * array,
     78                               size_t       arrayLen,
     79                               size_t      * setme_pex_count );
     80
    7181void tr_peerMgrAddPex( tr_peerMgr     * manager,
    7282                       const uint8_t  * torrentHash,
    7383                       uint8_t          from,
     
    8090
    8191int  tr_peerMgrGetPeers( tr_peerMgr      * manager,
    8292                         const uint8_t   * torrentHash,
    83                          tr_pex         ** setme_pex );
     93                         tr_pex         ** setme_pex,
     94                         uint8_t           af);
    8495
    8596void tr_peerMgrStartTorrent( tr_peerMgr     * manager,
    8697                             const uint8_t  * torrentHash );
  • libtransmission/port-forwarding.c

     
    3838    tr_port_forwarding    natpmpStatus;
    3939    tr_port_forwarding    upnpStatus;
    4040
     41    int                   bindPort6;
     42    int                   bindSocket6;
     43    int                   publicPort6;
     44#ifdef TR_NEED_V4SOCKET
    4145    int                   bindPort;
    4246    int                   bindSocket;
    4347    int                   publicPort;
     48#endif
     49   
    4450
    4551    tr_timer            * pulseTimer;
    4652
     
    8490static void
    8591natPulse( tr_shared * s )
    8692{
    87     const int port = s->publicPort;
     93    const int port = s->publicPort6;
    8894    const int isEnabled = s->isEnabled && !s->isShuttingDown;
    8995    int       oldStatus;
    9096    int       newStatus;
     
    106112    tr_bool allPaused;
    107113    tr_torrent * tor;
    108114
    109     if( s->bindSocket >= 0 && ( s->bindPort != s->publicPort ) )
     115    if( s->bindPort6 != s->publicPort6 )
    110116    {
    111         tr_ninf( getKey( ), _( "Closing port %d" ), s->bindPort );
    112         tr_netClose( s->bindSocket );
    113         s->bindSocket = -1;
     117        if( s->bindSocket6 >= 0 )
     118        {
     119            tr_ninf( getKey( ), _( "Closing port %d on %s" ), s->bindPort6,
     120                     tr_ntop_non_ts( &tr_in6addr_any ) );
     121            tr_netClose( s->bindSocket6 );
     122            s->bindSocket6 = -1;
     123        }
     124#ifdef TR_NEED_V4SOCKET
     125        if( s->bindSocket >= 0 )
     126        {
     127            tr_ninf( getKey( ), _( "Closing port %d on %s" ), s->bindPort,
     128                     tr_ntop_non_ts( &tr_inaddr_any ) );
     129            tr_netClose( s->bindSocket );
     130            s->bindSocket = -1;
     131        }
     132#endif
    114133    }
    115134
     135    if( ( s->publicPort6 > 0 ) && ( s->bindPort6 != s->publicPort6 ) )
     136    {
     137        int socket;
     138        errno = 0;
     139        socket = tr_netBindTCP( &tr_in6addr_any, s->publicPort6 );
     140        if( socket >= 0 )
     141        {
     142            tr_ninf( getKey( ),
     143                     _(
     144                         "Opened port %d on %s to listen for incoming peer connections" ),
     145                     s->publicPort6, tr_ntop_non_ts( &tr_in6addr_any ) );
     146            s->bindPort6 = s->publicPort6;
     147            s->bindSocket6 = socket;
     148            listen( s->bindSocket6, 5 );
     149        }
     150        else
     151        {
     152            tr_nerr( getKey( ),
     153                    _(
     154                        "Couldn't open port %d on %s to listen for incoming peer connections (errno %d - %s)" ),
     155                    s->publicPort6, tr_ntop_non_ts( &tr_in6addr_any ), errno, tr_strerror( errno ) );
     156            s->bindPort6 = -1;
     157            s->bindSocket6 = -1;
     158        }
     159    }
     160   
     161#ifdef TR_NEED_V4SOCKET
    116162    if( ( s->publicPort > 0 ) && ( s->bindPort != s->publicPort ) )
    117163    {
    118164        int socket;
     
    122168        {
    123169            tr_ninf( getKey( ),
    124170                     _(
    125                          "Opened port %d to listen for incoming peer connections" ),
    126                      s->publicPort );
     171                       "Opened port %d on %s to listen for incoming peer connections" ),
     172                     s->publicPort, tr_ntop_non_ts( &tr_inaddr_any ) );
    127173            s->bindPort = s->publicPort;
    128174            s->bindSocket = socket;
    129175            listen( s->bindSocket, 5 );
     
    131177        else
    132178        {
    133179            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 ) );
     180                     _(
     181                       "Couldn't open port %d on %s to listen for incoming peer connections (errno %d - %s)" ),
     182                     s->publicPort, tr_ntop_non_ts( &tr_inaddr_any ), errno, tr_strerror( errno ) );
    137183            s->bindPort = -1;
    138184            s->bindSocket = -1;
    139185        }
    140186    }
     187#endif
    141188
    142189    /* see if any torrents aren't paused */
    143190    allPaused = 1;
     
    152199    /* if we have any running torrents, check for new incoming peer connections */
    153200    while( !allPaused ) 
    154201    {
    155         int         socket;
    156         tr_port     port;
    157         tr_address  addr;
     202        int        socket;
     203        tr_port    port;
     204        tr_address addr;
     205        int        bail = 0; /* break when all listeners are exhausted */
     206       
     207        if( s->bindSocket6 >= 0 )
     208        {
     209            socket = tr_netAccept( s->session, s->bindSocket6, &addr, &port );
     210            if( socket < 0 )
     211                bail++;
     212            else
     213            {
     214                tr_deepLog( __FILE__, __LINE__, NULL,
     215                            "New INCOMING connection %d (%s)",
     216                            socket, tr_peerIoAddrStr( &addr, port ) );
    158217
    159         if( s->bindSocket < 0 )
     218                tr_peerMgrAddIncoming( s->session->peerMgr, &addr, port, socket );
     219            }
     220        }
     221        else
     222            bail++;
     223       
     224#ifdef TR_NEED_V4SOCKET
     225        if( s->bindSocket >= 0 )
     226        {
     227            socket = tr_netAccept( s->session, s->bindSocket, &addr, &port );
     228            if( socket < 0 )
     229                bail++;
     230            else
     231            {
     232                tr_deepLog( __FILE__, __LINE__, NULL,
     233                            "New INCOMING connection %d (%s)",
     234                            socket, tr_peerIoAddrStr( &addr, port ) );
     235               
     236                tr_peerMgrAddIncoming( s->session->peerMgr, &addr, port, socket );
     237            }
     238            else
     239                bail++;
     240#endif
     241#ifdef TR_NEED_V4SOCKET
     242        if( bail == 2 )
     243#else
     244        if( bail == 1 )
     245#endif
    160246            break;
    161 
    162         socket = tr_netAccept( s->session, s->bindSocket, &addr, &port );
    163         if( socket < 0 )
    164             break;
    165 
    166         tr_deepLog( __FILE__, __LINE__, NULL,
    167                    "New INCOMING connection %d (%s)",
    168                    socket, tr_peerIoAddrStr( &addr, port ) );
    169 
    170         tr_peerMgrAddIncoming( s->session->peerMgr, &addr, port, socket );
    171247    }
    172248}
    173249
     
    187263    {
    188264        tr_ninf( getKey( ), _( "Stopped" ) );
    189265        tr_timerFree( &shared->pulseTimer );
     266        tr_netClose( shared->bindSocket6 );
     267#ifdef TR_NEED_V4SOCKET
    190268        tr_netClose( shared->bindSocket );
     269#endif
    191270        tr_natpmpClose( shared->natpmp );
    192271        tr_upnpClose( shared->upnp );
    193272        shared->session->shared = NULL;
     
    210289    tr_shared * s = tr_new0( tr_shared, 1 );
    211290
    212291    s->session      = session;
     292    s->publicPort6  = publicPort;
     293    s->bindPort6    = -1;
     294    s->bindSocket6  = -1;
     295#ifdef TR_NEED_V4SOCKET
     296    s->bindSocket   = -1;
    213297    s->publicPort   = publicPort;
    214298    s->bindPort     = -1;
    215     s->bindSocket   = -1;
     299#endif
    216300    s->natpmp       = tr_natpmpInit( );
    217301    s->upnp         = tr_upnpInit( );
    218302    s->pulseTimer   = tr_timerNew( session, sharedPulse, s, 1000 );
     
    235319{
    236320    tr_torrent * tor = NULL;
    237321
     322    s->publicPort6 = port;
     323#ifdef TR_NEED_V4SOCKET
    238324    s->publicPort = port;
     325#endif
    239326
    240327    while( ( tor = tr_torrentNext( s->session, tor ) ) )
    241328        tr_torrentChangeMyPort( tor );
     
    244331int
    245332tr_sharedGetPeerPort( const tr_shared * s )
    246333{
    247     return s->publicPort;
     334    return s->publicPort6; /* they're the same anyway */
    248335}
    249336
    250337void
  • libtransmission/fdlimit.c

     
    450450}
    451451
    452452int
    453 tr_fdSocketCreate( int type )
     453tr_fdSocketCreate( int domain, int type )
    454454{
    455455    int s = -1;
    456456
    457457    tr_lockLock( gFd->lock );
    458458
    459459    if( gFd->socketCount < getSocketMax( gFd ) )
    460         if( ( s = socket( AF_INET, type, 0 ) ) < 0 )
     460        if( ( s = socket( domain, type, 0 ) ) < 0 )
    461461            tr_err( _( "Couldn't create socket: %s" ),
    462462                   tr_strerror( sockerrno ) );
    463463
     
    485485    tr_lockLock( gFd->lock );
    486486    if( gFd->socketCount < getSocketMax( gFd ) )
    487487    {
    488         len = sizeof( struct sockaddr );
     488        len = sizeof( struct sockaddr_storage );
    489489        s = accept( b, (struct sockaddr *) &sock, &len );
    490490    }
    491491    if( s > -1 )
     
    504504            struct sockaddr_in6 * sock6 = (struct sockaddr_in6 *)&sock;
    505505            addr->type = TR_AF_INET6;
    506506            memcpy( &addr->addr, &sock6->sin6_addr,
    507                     sizeof( struct sockaddr_in6 ) );
     507                    sizeof( struct in6_addr ) );
    508508            *port = sock6->sin6_port;
    509509        }
    510510        ++gFd->socketCount;
  • libtransmission/fdlimit.h

     
    8585/***********************************************************************
    8686 * Sockets
    8787 **********************************************************************/
    88 int      tr_fdSocketCreate( int type );
     88int      tr_fdSocketCreate( int domain, int type );
    8989
    9090int      tr_fdSocketAccept( int           b,
    9191                            tr_address  * addr,
  • libtransmission/resume.c

     
    3434#define KEY_MAX_PEERS       "max-peers"
    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"
    3940#define KEY_SPEEDLIMIT      "speed-limit"
     
    6162****
    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}
    7783
     
    94100            tr_peerMgrAddPex( tor->session->peerMgr,
    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 );
    98104        ret = TR_FR_PEERS;
    99105    }
     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 );
     119        ret = TR_FR_PEERS;
     120    }
    100121
    101122    return ret;
    102123}
  • libtransmission/net.c

     
    109109    return dst;
    110110}
    111111
     112tr_bool
     113tr_isV4Mapped( const tr_address * const addr )
     114{
     115    if( addr->addr.addr6.s6_addr[0] == 0 &&
     116        addr->addr.addr6.s6_addr[1] == 0 &&
     117        addr->addr.addr6.s6_addr[2] == 0 &&
     118        addr->addr.addr6.s6_addr[3] == 0 &&
     119        addr->addr.addr6.s6_addr[4] == 0 &&
     120        addr->addr.addr6.s6_addr[5] == 0 &&
     121        addr->addr.addr6.s6_addr[6] == 0 &&
     122        addr->addr.addr6.s6_addr[7] == 0 &&
     123        addr->addr.addr6.s6_addr[8] == 0 &&
     124        addr->addr.addr6.s6_addr[9] == 0 &&
     125        addr->addr.addr6.s6_addr[10] == 0xff &&
     126        addr->addr.addr6.s6_addr[11] == 0xff )
     127        return 1;
     128    return 0;
     129}
     130
     131void
     132tr_normalizeV4Mapped( tr_address * const addr )
     133{
     134    if( tr_isV4Mapped( addr ) )
     135    {
     136        addr->type = TR_AF_INET;
     137        memcpy( &addr->addr.addr4.s_addr, addr->addr.addr6.s6_addr + 12, 4 );
     138    }
     139}
     140
    112141/*
    113142 * Compare two tr_address structures.
    114143 * Returns:
     
    172201}
    173202
    174203static int
    175 createSocket( int type )
     204createSocket( int domain, int type )
    176205{
    177     return makeSocketNonBlocking( tr_fdSocketCreate( type ) );
     206    return makeSocketNonBlocking( tr_fdSocketCreate( domain, type ) );
    178207}
    179208
    180209static void
     
    191220#endif
    192221}
    193222
    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;
     223static void
     224setup_sockaddr( const tr_address        * addr,
     225                tr_port                   port,
     226                struct sockaddr_storage * sockaddr)
     227{
     228    struct sockaddr_in  sock4;
     229    struct sockaddr_in6 sock6;
     230    if( addr->type == TR_AF_INET )
     231    {
     232        memset( &sock4, 0, sizeof( sock4 ) );
     233        sock4.sin_family      = AF_INET;
     234        sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
     235        sock4.sin_port        = port;
     236        memcpy( sockaddr, &sock4, sizeof( sock4 ) );
     237    }
     238    else
     239    {
     240        memset( &sock6, 0, sizeof( sock6 ) );
     241        sock6.sin6_family = AF_INET6;
     242        sock6.sin6_port = port;
     243        sock6.sin6_flowinfo = 0;
     244        memcpy( &sock6.sin6_addr, &addr->addr, sizeof( struct in6_addr ) );
     245        memcpy( sockaddr, &sock6, sizeof( sock6 ) );
     246    }
     247}
    201248
    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;
     249int
     250tr_netOpenTCP( tr_session        * session,
     251               const tr_address  * addr,
     252               tr_port             port )
     253{
     254    int                     s;
     255    struct sockaddr_storage sock;
     256    const int               type = SOCK_STREAM;
     257    socklen_t               addrlen;
    228258
    229     if( ( s = createSocket( type ) ) < 0 )
     259    if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ),
     260                            type ) ) < 0 )
    230261        return -1;
    231262
    232263    setSndBuf( session, s );
    233264
    234265    setup_sockaddr( addr, port, &sock );
     266    if( addr->type == TR_AF_INET )
     267        addrlen = sizeof( struct sockaddr_in );
     268    else
     269        addrlen = sizeof( struct sockaddr_in6 );
    235270
    236271    if( ( connect( s, (struct sockaddr *) &sock,
    237                   sizeof( struct sockaddr ) ) < 0 )
     272                  addrlen ) < 0 )
    238273#ifdef WIN32
    239274      && ( sockerrno != WSAEWOULDBLOCK )
    240275#endif
     
    255290int
    256291tr_netBindTCP( const tr_address * addr, tr_port port )
    257292{
    258     int                      s;
    259     struct sockaddr_storage  sock;
    260     const int                type = SOCK_STREAM;
     293    int                     s;
     294    struct sockaddr_storage sock;
     295    const int               type = SOCK_STREAM;
     296    int                     addrlen;
    261297
    262298#if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT )
    263299    int                optval;
    264300#endif
    265301
    266     if( ( s = createSocket( type ) ) < 0 )
     302    if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ),
     303                            type ) ) < 0 )
    267304        return -1;
    268305
    269306#ifdef SO_REUSEADDR
     
    272309#endif
    273310
    274311    setup_sockaddr( addr, htons( port ), &sock );
     312    if( addr->type == TR_AF_INET )
     313        addrlen = sizeof( struct sockaddr_in );
     314    else
     315        addrlen = sizeof( struct sockaddr_in6 );
    275316
    276317    if( bind( s, (struct sockaddr *) &sock,
    277              sizeof( struct sockaddr ) ) )
     318             addrlen ) )
    278319    {
    279320        tr_err( _( "Couldn't bind port %d on %s: %s" ), port,
    280321               tr_ntop_non_ts( addr ), tr_strerror( sockerrno ) );
  • libtransmission/net.h

     
    5555
    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
    8260
     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 );
     80tr_bool tr_isV4Mapped( const tr_address * const addr );
     81void tr_normalizeV4Mapped( tr_address * const addr );
     82int tr_compareAddresses( const tr_address * a,
     83                         const tr_address * b);
     84
     85
    8386/***********************************************************************
    8487 * Sockets
    8588 **********************************************************************/
  • libtransmission/tracker.c

     
    240240        tr_publisherPublish( t->publisher, t, &event );
    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****
    245307***/
     
    276338    return retry;
    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 );
     351    array = tr_new( uint8_t, peerCount * ( sizeof( tr_address ) + 2 ) );
    292352
    293     for( i = 0, walk = compact; i < peerCount; ++i )
     353    for( i = 0, walk = array; i < peerCount; ++i )
    294354    {
    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;
     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];
    311360
     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;
     372        memcpy( walk + sizeof( tr_address ), &port, 2 );
     373        walk += sizeof( tr_address ) + 2;
    319374    }
    320375
    321     *byteCount = peerCount * 6;
    322     return compact;
     376    *byteCount = peerCount * sizeof( tr_address ) + 2;
     377    return array;
    323378}
    324379
    325380static void
     
    432487
    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 );
    444499                }
    445500            }
     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 );
     510                }
     511            }
    446512        }
    447513
    448514        if( bencLoaded )
  • libtransmission/torrent.c

     
    227227        case TR_TRACKER_PEERS:
    228228        {
    229229            size_t   i, n;
    230             tr_pex * pex = tr_peerMgrCompactToPex( event->compact,
    231                                                    event->compactLen,
    232                                                    NULL, 0, &n );
    233             if( event->allAreSeeds )
     230            tr_pex * pex = tr_peerMgrArrayToPex( event->compact,
     231                                                 event->compactLen, &n );
     232             if( event->allAreSeeds )
    234233                tr_tordbg( tor, "Got %d seeds from tracker", (int)n );
    235234            else
    236235                tr_torinf( tor, _( "Got %d peers from tracker" ), (int)n );