Ignore:
Timestamp:
Dec 15, 2008, 12:17:08 AM (12 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 :)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 ) ) )
Note: See TracChangeset for help on using the changeset viewer.