Ticket #776: ticket-776-bind-local-port.patch

File ticket-776-bind-local-port.patch, 4.9 KB (added by wereHamster, 12 years ago)
  • libtransmission/net.c

    diff --git a/libtransmission/net.c b/libtransmission/net.c
    index 678c622..778d97b 100644
    a b tr_netOpenPeerSocket( tr_session * session, 
    253253    const tr_address      * source_addr;
    254254    socklen_t               sourcelen;
    255255    struct sockaddr_storage source_sock;
     256    tr_port                 source_port = 0, source_port_max;
    256257
    257258    assert( tr_isAddress( addr ) );
    258259
    tr_netOpenPeerSocket( tr_session * session, 
    275276        return -1;
    276277    }
    277278
     279    if( tr_sessionShouldBindLocalPort( session ) )
     280    {
     281        int optval = 1;
     282        setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) );
     283        source_port = tr_sessionGetPeerPort( session );
     284        source_port_max = MIN( (int)source_port + 50, UINT16_MAX );
     285    }
     286   
    278287    addrlen = setup_sockaddr( addr, port, &sock );
    279288
    280289    /* set source address */
    281290    source_addr = tr_sessionGetPublicAddress( session, addr->type );
    282291    assert( source_addr );
    283     sourcelen = setup_sockaddr( source_addr, 0, &source_sock );
     292
     293try_again:
     294    sourcelen = setup_sockaddr( source_addr, htons( source_port ), &source_sock );
    284295    if( bind( s, ( struct sockaddr * ) &source_sock, sourcelen ) )
    285296    {
     297        if( tr_sessionShouldBindLocalPort( session ) && errno == EADDRINUSE )
     298        {
     299            if( source_port++ < source_port_max )
     300                goto try_again;
     301        }
     302
    286303        tr_err( _( "Couldn't set source address %s on %d: %s" ),
    287304                tr_ntop_non_ts( source_addr ), s, tr_strerror( errno ) );
    288305        return -errno;
  • libtransmission/session.c

    diff --git a/libtransmission/session.c b/libtransmission/session.c
    index b61dd6e..650246d 100644
    a b tr_sessionGetPublicAddress( const tr_session * session, int tr_af_type ) 
    222222    }
    223223}
    224224
     225tr_bool
     226tr_sessionShouldBindLocalPort( const tr_session * session )
     227{
     228    assert( tr_isSession( session ) );
     229
     230    return session->bindLocalPort;
     231}
     232
    225233/***
    226234****
    227235***/
    tr_sessionGetDefaultSettings( const char * configDir, tr_benc * d ) 
    296304    tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 );
    297305    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,        TR_DEFAULT_BIND_ADDRESS_IPV4 );
    298306    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,        TR_DEFAULT_BIND_ADDRESS_IPV6 );
     307    tr_bencDictAddBool( d, TR_PREFS_KEY_BIND_LOCAL_PORT,          FALSE );
    299308
    300309    tr_free( incompleteDir );
    301310}
    tr_sessionGetSettings( tr_session * s, struct tr_benc * d ) 
    358367    tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent );
    359368    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,        tr_ntop_non_ts( &s->public_ipv4->addr ) );
    360369    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,        tr_ntop_non_ts( &s->public_ipv6->addr ) );
     370    tr_bencDictAddBool( d, TR_PREFS_KEY_BIND_LOCAL_PORT,          s->bindLocalPort );
    361371}
    362372
    363373tr_bool
    sessionSetImpl( void * vdata ) 
    735745    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PORT_FORWARDING, &boolVal ) )
    736746        tr_sessionSetPortForwardingEnabled( session, boolVal );
    737747
     748    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_BIND_LOCAL_PORT, &boolVal ) )
     749        session->bindLocalPort = boolVal;
     750
    738751    /* file and peer socket limits */
    739752    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &i ) )
    740753        tr_fdSetPeerLimit( session, i );
  • libtransmission/session.h

    diff --git a/libtransmission/session.h b/libtransmission/session.h
    index cb3d2c6..0e86663 100644
    a b struct tr_session 
    189189    /* a page-aligned buffer for use by the libtransmission thread.
    190190     * @see SESSION_BUFFER_SIZE */
    191191    void * buffer;
    192 
    193192    tr_bool bufferInUse;
     193   
     194    tr_bool                      bindLocalPort;
    194195};
    195196
    196197tr_bool      tr_sessionAllowsDHT( const tr_session * session );
    const struct tr_address* tr_sessionGetPublicAddress( const tr_session *, int tr 
    215216
    216217struct tr_bindsockets * tr_sessionGetBindSockets( tr_session * );
    217218
     219tr_bool tr_sessionShouldBindLocalPort( const tr_session * session );
     220
    218221enum
    219222{
    220223    SESSION_MAGIC_NUMBER = 3845,
  • libtransmission/transmission.h

    diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h
    index 992e295..8dc154c 100644
    a b const char* tr_getDefaultDownloadDir( void ); 
    162162#define TR_PREFS_KEY_ALT_SPEED_TIME_DAY         "alt-speed-time-day"
    163163#define TR_PREFS_KEY_BIND_ADDRESS_IPV4          "bind-address-ipv4"
    164164#define TR_PREFS_KEY_BIND_ADDRESS_IPV6          "bind-address-ipv6"
     165#define TR_PREFS_KEY_BIND_LOCAL_PORT            "bind-local-port"
    165166#define TR_PREFS_KEY_BLOCKLIST_ENABLED          "blocklist-enabled"
    166167#define TR_PREFS_KEY_DHT_ENABLED                "dht-enabled"
    167168#define TR_PREFS_KEY_DOWNLOAD_DIR               "download-dir"