Changeset 11654


Ignore:
Timestamp:
Jan 9, 2011, 9:48:36 PM (11 years ago)
Author:
jch
Message:

Move creation of the UDP sockets to tr-udp.c.

Location:
trunk/libtransmission
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/session.c

    r11653 r11654  
    524524    /* initialize the bare skeleton of the session object */
    525525    session = tr_new0( tr_session, 1 );
     526    session->udp_socket = -1;
     527    session->udp6_socket = -1;
    526528    session->bandwidth = tr_bandwidthNew( session, NULL );
    527529    session->lock = tr_lockNew( );
  • trunk/libtransmission/session.h

    r11610 r11654  
    126126    int                          uploadSlotsPerTorrent;
    127127
     128    /* The UDP sockets used for the DHT and uTP. */
     129    tr_port                      udp_port;
     130    int                          udp_socket;
     131    int                          udp6_socket;
     132    unsigned char *              udp6_bound;
     133
    128134    /* The open port on the local machine for incoming peer requests */
    129135    tr_port                      private_peer_port;
  • trunk/libtransmission/tr-dht.c

    r11645 r11654  
    6060#include "utils.h"
    6161
    62 static int dht_socket = -1, dht6_socket = -1;
    63 static struct event * dht_event = NULL;
    64 static struct event * dht6_event = NULL;
    65 static tr_port dht_port;
     62static struct event dht_event, dht6_event;
    6663static unsigned char myid[20];
    6764static tr_session *session = NULL;
     
    253250}
    254251
    255 /* BEP-32 has a rather nice explanation of why we need to bind to one
    256    IPv6 address, if I may say so myself. */
    257 
    258 static int
    259 rebind_ipv6(tr_bool force)
    260 {
    261     struct sockaddr_in6 sin6;
    262     const unsigned char *ipv6 = tr_globalIPv6();
    263     static unsigned char *last_bound = NULL;
    264     int s, rc;
    265     int one = 1;
    266 
    267     /* We currently have no way to enable or disable IPv6 once the DHT has
    268        been initialised. Oh, well. */
    269     if(ipv6 == NULL || (!force && dht6_socket < 0)) {
    270         if(last_bound) {
    271             free(last_bound);
    272             last_bound = NULL;
    273         }
    274         return 0;
    275     }
    276 
    277     if(last_bound != NULL && memcmp(ipv6, last_bound, 16) == 0)
    278         return 0;
    279 
    280     s = socket(PF_INET6, SOCK_DGRAM, 0);
    281     if(s < 0) {
    282         tr_ndbg( "DHT", "dht6_socket: %s", tr_strerror( errno ) );
    283         return -1;
    284     }
    285 
    286 #ifdef IPV6_V6ONLY
    287         /* Since we always open an IPv4 socket on the same port, this
    288            shouldn't matter. But I'm superstitious. */
    289         setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
    290 #endif
    291 
    292     memset(&sin6, 0, sizeof(sin6));
    293     sin6.sin6_family = AF_INET6;
    294     if(ipv6)
    295         memcpy(&sin6.sin6_addr, ipv6, 16);
    296     sin6.sin6_port = htons(dht_port);
    297     rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
    298 
    299     if(rc < 0) {
    300         tr_nerr( "DHT", "bind(dht6_socket): %s", tr_strerror( errno ) );
    301         close(s);
    302         return -1;
    303     }
    304 
    305     if(dht6_socket < 0) {
    306         dht6_socket = s;
    307     } else {
    308         rc = dup2(s, dht6_socket);
    309         close(s);
    310         if(rc < 0)
    311             return -1;
    312     }
    313 
    314     if(last_bound == NULL)
    315         last_bound = malloc(16);
    316     if(last_bound)
    317         memcpy(last_bound, ipv6, 16);
    318 
    319     return 1;
    320 }
    321 
    322252int
    323 tr_dhtInit(tr_session *ss, const tr_address * tr_addr)
    324 {
    325     struct sockaddr_in sin;
     253tr_dhtInit(tr_session *ss)
     254{
    326255    tr_benc benc;
    327256    int rc;
     
    334263
    335264    if( session ) /* already initialized */
    336         return -1;
    337 
    338     dht_port = tr_sessionGetPeerPort(ss);
    339     if(dht_port <= 0)
    340         return -1;
     265        return -1;   
    341266
    342267    tr_ndbg( "DHT", "Initializing DHT" );
    343 
    344     dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
    345     if(dht_socket < 0)
    346         goto fail;
    347 
    348     memset(&sin, 0, sizeof(sin));
    349     sin.sin_family = AF_INET;
    350     memcpy(&sin.sin_addr, &tr_addr->addr.addr4, sizeof (struct in_addr));
    351     sin.sin_port = htons(dht_port);
    352     rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
    353     if(rc < 0)
    354         goto fail;
    355 
    356     if(tr_globalIPv6())
    357         rebind_ipv6(TRUE);
    358268
    359269    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
     
    367277        if( have_id && len==20 )
    368278            memcpy( myid, raw, len );
    369         if( dht_socket >= 0 &&
     279        if( ss->udp_socket >= 0 &&
    370280            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
    371281                nodes = tr_memdup( raw, len );
    372282        }
    373         if( dht6_socket > 0 &&
     283        if( ss->udp6_socket > 0 &&
    374284            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
    375285            nodes6 = tr_memdup( raw, len6 );
     
    392302    }
    393303
    394     rc = dht_init( dht_socket, dht6_socket, myid, NULL );
     304    rc = dht_init( ss->udp_socket, ss->udp6_socket, myid, NULL );
    395305    if( rc < 0 )
    396306        goto fail;
     
    406316    tr_threadNew( dht_bootstrap, cl );
    407317
    408     dht_event = event_new( session->event_base, dht_socket, EV_READ, event_callback, NULL );
    409     tr_timerAdd( dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
    410 
    411     if( dht6_socket >= 0 )
     318    event_set( &dht_event, ss->udp_socket, EV_READ, event_callback, NULL );
     319    tr_timerAdd( &dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
     320
     321    if( ss->udp6_socket >= 0 )
    412322    {
    413         dht6_event = event_new( session->event_base, dht6_socket, EV_READ, event_callback, NULL );
    414         tr_timerAdd( dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
     323        event_set( &dht6_event, ss->udp6_socket, EV_READ, event_callback, NULL );
     324        tr_timerAdd( &dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
    415325    }
    416326
     
    419329    return 1;
    420330
    421     fail:
    422     {
    423         const int save = errno;
    424         close(dht_socket);
    425         if( dht6_socket >= 0 )
    426             close(dht6_socket);
    427         dht_socket = dht6_socket = -1;
    428         session = NULL;
    429         tr_ndbg( "DHT", "DHT initialization failed: %s", tr_strerror( save ) );
    430         errno = save;
    431     }
    432 
     331 fail:
     332    tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", errno );
     333    session = NULL;
    433334    return -1;
    434335}
     
    445346    dht_event = NULL;
    446347
    447     if( dht6_event ) {
    448         event_free( dht6_event );
    449         dht6_event = NULL;
    450     }
     348    if( ss->udp6_socket >= 0 )
     349        event_del( &dht6_event );
    451350
    452351    /* Since we only save known good nodes, avoid erasing older data if we
     
    490389
    491390    dht_uninit( 1 );
    492     tr_netCloseSocket( dht_socket );
    493     dht_socket = -1;
    494     if(dht6_socket > 0) {
    495         tr_netCloseSocket( dht6_socket );
    496         dht6_socket = -1;
    497     }
    498 
    499391    tr_ndbg("DHT", "Done uninitializing DHT");
    500392
     
    541433
    542434    if( !tr_dhtEnabled( session ) ||
    543         (af == AF_INET && dht_socket < 0) ||
    544         (af == AF_INET6 && dht6_socket < 0) ) {
     435        (af == AF_INET && session->udp_socket < 0) ||
     436        (af == AF_INET6 && session->udp6_socket < 0) ) {
    545437        if( nodes_return )
    546438            *nodes_return = 0;
     
    561453tr_dhtPort( tr_session *ss )
    562454{
    563     return tr_dhtEnabled( ss ) ? dht_port : 0;
     455    return tr_dhtEnabled( ss ) ? ss->udp_port : 0;
    564456}
    565457
     
    702594event_callback(int s, short type, void *ignore UNUSED )
    703595{
    704     struct event *event = (s == dht_socket) ? dht_event : dht6_event;
     596    struct event *event;
    705597    time_t tosleep;
    706     static int count = 0;
     598
     599    if (s == session->udp_socket)
     600        event =  &dht_event;
     601    else if(s == session->udp6_socket)
     602        event = &dht6_event;
     603    else {
     604        tr_nerr("DHT", "Event on unexpected socket");
     605        event = NULL;
     606    }
    707607
    708608    if( dht_periodic( type == EV_READ, &tosleep, callback, NULL) < 0 ) {
     
    717617    }
    718618
    719     /* Only do this once in a while. Counting rather than measuring time
     619#ifdef NOTYET
     620    /* Only do this once in a while.  Counting rather than measuring time
    720621       avoids a system call. */
    721622    count++;
     
    724625        count = 0;
    725626    }
    726 
    727     /* Being slightly late is fine,
    728        and has the added benefit of adding some jitter. */
    729     tr_timerAdd( event, tosleep, tr_cryptoWeakRandInt( 1000000 ) );
     627#endif
     628
     629    if(event) {
     630        /* Being slightly late is fine,
     631           and has the added benefit of adding some jitter. */
     632        tr_timerAdd( event, tosleep, tr_cryptoWeakRandInt( 1000000 ) );
     633    }
    730634}
    731635
  • trunk/libtransmission/tr-dht.h

    r11652 r11654  
    3737};
    3838
    39 int  tr_dhtInit( tr_session *, const tr_address * );
     39int  tr_dhtInit( tr_session * );
    4040void tr_dhtUninit( tr_session * );
    4141tr_bool tr_dhtEnabled( const tr_session * );
  • trunk/libtransmission/tr-udp.c

    r11653 r11654  
    2222*/
    2323
     24#include <unistd.h>
     25#include <assert.h>
     26
    2427#include "transmission.h"
    2528#include "net.h"
     
    2831#include "tr-udp.h"
    2932
     33/* BEP-32 has a rather nice explanation of why we need to bind to one
     34   IPv6 address, if I may say so myself. */
     35
     36static void
     37rebind_ipv6(tr_session *ss, tr_bool force)
     38{
     39    struct sockaddr_in6 sin6;
     40    const unsigned char *ipv6 = tr_globalIPv6();
     41    int s = -1, rc;
     42    int one = 1;
     43
     44    /* We currently have no way to enable or disable IPv6 after initialisation.
     45       No way to fix that without some surgery to the DHT code itself. */
     46    if(ipv6 == NULL || (!force && ss->udp6_socket < 0)) {
     47        if(ss->udp6_bound) {
     48            free(ss->udp6_bound);
     49            ss->udp6_bound = NULL;
     50        }
     51        return;
     52    }
     53
     54    if(ss->udp6_bound != NULL && memcmp(ipv6, ss->udp6_bound, 16) == 0)
     55        return;
     56
     57    s = socket(PF_INET6, SOCK_DGRAM, 0);
     58    if(s < 0)
     59        goto fail;
     60
     61#ifdef IPV6_V6ONLY
     62        /* Since we always open an IPv4 socket on the same port, this
     63           shouldn't matter.  But I'm superstitious. */
     64        setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
     65#endif
     66
     67    memset(&sin6, 0, sizeof(sin6));
     68    sin6.sin6_family = AF_INET6;
     69    if(ipv6)
     70        memcpy(&sin6.sin6_addr, ipv6, 16);
     71    sin6.sin6_port = htons(ss->udp_port);
     72    rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
     73    if(rc < 0)
     74        goto fail;
     75
     76    if(ss->udp6_socket < 0) {
     77        ss->udp6_socket = s;
     78        s = -1;
     79    } else {
     80        rc = dup2(s, ss->udp6_socket);
     81        if(rc < 0)
     82            goto fail;
     83        close(s);
     84        s = -1;
     85    }
     86
     87    if(ss->udp6_bound == NULL)
     88        ss->udp6_bound = malloc(16);
     89    if(ss->udp6_bound)
     90        memcpy(ss->udp6_bound, ipv6, 16);
     91
     92    return;
     93
     94 fail:
     95    /* Something went wrong.  It's difficult to recover, so let's simply
     96       set things up so that we try again next time. */
     97    tr_nerr("UDP", "Couldn't rebind IPv6 socket");
     98    if(s >= 0)
     99        close(s);
     100    if(ss->udp6_bound) {
     101        free(ss->udp6_bound);
     102        ss->udp6_bound = NULL;
     103    }
     104}
    30105
    31106void
    32107tr_udpInit(tr_session *ss, const tr_address * addr)
    33108{
    34     if( ss->isDHTEnabled )
    35         tr_dhtInit(ss, addr);
     109    struct sockaddr_in sin;
     110    int rc;
     111
     112    assert(ss->udp_socket < 0);
     113    assert(ss->udp6_socket < 0);
     114
     115    ss->udp_port = tr_sessionGetPeerPort(ss);
     116    if(ss->udp_port <= 0)
     117        return;
     118
     119    ss->udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
     120    if(ss->udp_socket < 0) {
     121        tr_nerr("UDP", "Couldn't create IPv4 socket");
     122        goto ipv6;
     123    }
     124
     125    memset(&sin, 0, sizeof(sin));
     126    sin.sin_family = AF_INET;
     127    memcpy(&sin.sin_addr, &addr->addr.addr4, sizeof (struct in_addr));
     128    sin.sin_port = htons(ss->udp_port);
     129    rc = bind(ss->udp_socket, (struct sockaddr*)&sin, sizeof(sin));
     130    if(rc < 0) {
     131        tr_nerr("UDP", "Couldn't bind IPv4 socket");
     132        close(ss->udp_socket);
     133        ss->udp_socket = -1;
     134        goto ipv6;
     135    }
     136
     137 ipv6:
     138    if(tr_globalIPv6())
     139        rebind_ipv6(ss, TRUE);
     140
     141    if(ss->isDHTEnabled)
     142        tr_dhtInit(ss);
    36143}
    37144
     
    39146tr_udpUninit(tr_session *ss)
    40147{
    41     return tr_dhtUninit(ss);
     148    tr_dhtUninit(ss);
     149
     150    if(ss->udp_socket >= 0) {
     151        tr_netCloseSocket( ss->udp_socket );
     152        ss->udp_socket = -1;
     153    }
     154
     155    if(ss->udp6_socket >= 0) {
     156        tr_netCloseSocket( ss->udp6_socket );
     157        ss->udp6_socket = -1;
     158    }
     159
     160    if(ss->udp6_bound) {
     161        free(ss->udp6_bound);
     162        ss->udp6_bound = NULL;
     163    }
    42164}
Note: See TracChangeset for help on using the changeset viewer.