Ignore:
Timestamp:
May 14, 2009, 1:42:29 PM (13 years ago)
Author:
charles
Message:

(trunk libT) #2035: Transmission causes wakeups by unnecessary polling.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/net.c

    r8391 r8398  
    3939 #include <fcntl.h>
    4040#endif
     41#include <unistd.h>
    4142
    4243#include <evutil.h>
     
    4849#include "peer-io.h"
    4950#include "platform.h"
     51#include "session.h"
    5052#include "utils.h"
    5153
     
    5557
    5658const tr_address tr_in6addr_any = { TR_AF_INET6, { IN6ADDR_ANY_INIT } };
    57 const tr_address tr_inaddr_any = { TR_AF_INET,
    58     { { { { INADDR_ANY, 0x00, 0x00, 0x00 } } } } };
     59const tr_address tr_inaddr_any = { TR_AF_INET, { { { { INADDR_ANY, 0x00, 0x00, 0x00 } } } } };
    5960
    6061#ifdef WIN32
    6162static const char *
    62 inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
     63inet_ntop( int af, const void *src, char *dst, socklen_t cnt )
    6364{
    6465    if (af == AF_INET)
    6566    {
    6667        struct sockaddr_in in;
    67         memset(&in, 0, sizeof(in));
     68        memset( &in, 0, sizeof( in ) );
    6869        in.sin_family = AF_INET;
    69         memcpy(&in.sin_addr, src, sizeof(struct in_addr));
    70         getnameinfo((struct sockaddr *)&in, sizeof(struct
    71             sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
     70        memcpy( &in.sin_addr, src, sizeof( struct in_addr ) );
     71        getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
     72                    dst, cnt, NULL, 0, NI_NUMERICHOST);
    7273        return dst;
    7374    }
     
    7576    {
    7677        struct sockaddr_in6 in;
    77         memset(&in, 0, sizeof(in));
     78        memset( &in, 0, sizeof( in ) );
    7879        in.sin6_family = AF_INET6;
    79         memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
    80         getnameinfo((struct sockaddr *)&in, sizeof(struct
    81             sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
     80        memcpy( &in.sin6_addr, src, sizeof( struct in_addr6 ) );
     81        getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
     82                    dst, cnt, NULL, 0, NI_NUMERICHOST);
    8283        return dst;
    8384    }
     
    197198tr_net_hasIPv6( tr_port port )
    198199{
     200    static tr_bool result = FALSE;
    199201    static tr_bool alreadyDone = FALSE;
    200     static tr_bool result      = FALSE;
    201     int s;
    202     if( alreadyDone )
    203         return result;
    204     s = tr_netBindTCP( &tr_in6addr_any, port, TRUE );
    205     if( s >= 0 || -s != EAFNOSUPPORT ) /* we support ipv6 */
    206     {
    207         result = TRUE;
    208         tr_netClose( s );
    209     }
    210     alreadyDone = TRUE;
     202
     203    if( !alreadyDone )
     204    {
     205        int fd = tr_netBindTCP( &tr_in6addr_any, port, TRUE );
     206        if( fd >= 0 || -fd != EAFNOSUPPORT ) /* we support ipv6 */
     207            result = TRUE;
     208        if( fd >= 0 )
     209            EVUTIL_CLOSESOCKET( fd );
     210        alreadyDone = TRUE;
     211    }
     212
    211213    return result;
    212 }
    213 
    214 /***********************************************************************
    215  * Socket list housekeeping
    216  **********************************************************************/
    217 struct tr_socketList
    218 {
    219     int             socket;
    220     tr_address      addr;
    221     tr_socketList * next;
    222 };
    223 
    224 tr_socketList *
    225 tr_socketListAppend( tr_socketList * const head,
    226                      const tr_address * const addr )
    227 {
    228     tr_socketList * tmp;
    229 
    230     assert( head );
    231     assert( tr_isAddress( addr ) );
    232 
    233     for( tmp = head; tmp->next; tmp = tmp->next );
    234     tmp->next = tr_socketListNew( addr );
    235     return tmp->next;
    236 }
    237 
    238 tr_socketList *
    239 tr_socketListNew( const tr_address * const addr )
    240 {
    241     tr_socketList * tmp;
    242 
    243     assert( tr_isAddress( addr ) );
    244 
    245     tmp = tr_new( tr_socketList, 1 );
    246     tmp->socket = -1;
    247     tmp->addr = *addr;
    248     tmp->next = NULL;
    249     return tmp;
    250 }
    251 
    252 void
    253 tr_socketListFree( tr_socketList * const head )
    254 {
    255     assert( head );
    256 
    257     if( head->next )
    258         tr_socketListFree( head->next );
    259     tr_free( head );
    260 }
    261 
    262 void
    263 tr_socketListRemove( tr_socketList * const head,
    264                      tr_socketList * const el)
    265 {
    266     tr_socketList * tmp;
    267 
    268     assert( head );
    269     assert( el );
    270 
    271     for( tmp = head; tmp->next && tmp->next != el; tmp = tmp->next );
    272     tmp->next = el->next;
    273     el->next = NULL;
    274     tr_socketListFree(el);
    275 }
    276 
    277 void
    278 tr_socketListTruncate( tr_socketList * const head,
    279                        tr_socketList * const start )
    280 {
    281     tr_socketList * tmp;
    282 
    283     assert( head );
    284     assert( start );
    285 
    286     for( tmp = head; tmp->next && tmp->next != start; tmp = tmp->next );
    287     tr_socketListFree( start );
    288     tmp->next = NULL;
    289 }
    290 
    291 #if 0
    292 int
    293 tr_socketListGetSocket( const tr_socketList * const el )
    294 {
    295     assert( el );
    296 
    297     return el->socket;
    298 }
    299 
    300 const tr_address *
    301 tr_socketListGetAddress( const tr_socketList * const el )
    302 {
    303     assert( el );
    304     return &el->addr;
    305 }
    306 #endif
    307 
    308 void
    309 tr_socketListForEach( tr_socketList * const head,
    310                       void ( * cb ) ( int * const,
    311                                       tr_address * const,
    312                                       void * const),
    313                       void * const userData )
    314 {
    315     tr_socketList * tmp;
    316     for( tmp = head; tmp; tmp = tmp->next )
    317         cb( &tmp->socket, &tmp->addr, userData );
    318 }
    319 
    320 const tr_address *
    321 tr_socketListGetType( const tr_socketList * const el, tr_address_type type )
    322 {
    323     const tr_socketList * tmp = el;
    324     while( tmp )
    325     {
    326         if( tmp->addr.type == type )
    327             return &tmp->addr;
    328         tmp = tmp->next;
    329     }
    330     return NULL;
    331214}
    332215
     
    345228}
    346229
    347 static int
    348 makeSocketNonBlocking( int fd )
    349 {
    350     if( fd >= 0 )
    351     {
    352         if( evutil_make_socket_nonblocking( fd ) )
    353         {
    354             int tmperrno;
    355             tr_err( _( "Couldn't create socket: %s" ),
    356                    tr_strerror( sockerrno ) );
    357             tmperrno = sockerrno;
    358             tr_netClose( fd );
    359             fd = -tmperrno;
    360         }
    361     }
    362 
    363     return fd;
    364 }
    365 
    366 static int
    367 createSocket( int domain, int type )
    368 {
    369     return makeSocketNonBlocking( tr_fdSocketCreate( domain, type ) );
    370 }
    371 
    372 static void
    373 setSndBuf( tr_session * session UNUSED, int fd UNUSED )
    374 {
    375 #if 0
    376     if( fd >= 0 )
    377     {
    378         const int sndbuf = session->so_sndbuf;
    379         const int rcvbuf = session->so_rcvbuf;
    380         setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof( sndbuf ) );
    381         setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof( rcvbuf ) );
    382     }
    383 #endif
    384 }
    385 
    386230static socklen_t
    387231setup_sockaddr( const tr_address        * addr,
     
    389233                struct sockaddr_storage * sockaddr)
    390234{
    391     struct sockaddr_in  sock4;
    392     struct sockaddr_in6 sock6;
    393 
    394235    assert( tr_isAddress( addr ) );
    395236
    396237    if( addr->type == TR_AF_INET )
    397238    {
     239        struct sockaddr_in  sock4;
    398240        memset( &sock4, 0, sizeof( sock4 ) );
    399241        sock4.sin_family      = AF_INET;
     
    405247    else
    406248    {
     249        struct sockaddr_in6 sock6;
    407250        memset( &sock6, 0, sizeof( sock6 ) );
    408         sock6.sin6_family = AF_INET6;
    409         sock6.sin6_port = port;
     251        sock6.sin6_family   = AF_INET6;
     252        sock6.sin6_port     = port;
    410253        sock6.sin6_flowinfo = 0;
    411         sock6.sin6_addr = addr->addr.addr6;
     254        sock6.sin6_addr     = addr->addr.addr6;
    412255        memcpy( sockaddr, &sock6, sizeof( sock6 ) );
    413256        return sizeof( struct sockaddr_in6 );
     
    461304}
    462305
    463 const tr_socketList * tr_getSessionBindSockets( const tr_session * session );
    464 
    465306int
    466307tr_netOpenTCP( tr_session        * session,
     
    468309               tr_port             port )
    469310{
     311    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
    470312    int                     s;
    471313    struct sockaddr_storage sock;
    472     const int               type = SOCK_STREAM;
    473314    socklen_t               addrlen;
    474315    const tr_address      * source_addr;
     
    481322        return -EINVAL;
    482323
    483     if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ), type ) ) < 0 )
    484         return s;
    485 
    486     setSndBuf( session, s );
     324    s = tr_fdSocketCreate( domains[addr->type], SOCK_STREAM );
     325    if( s < 0 )
     326        return -1;
     327
     328    if( evutil_make_socket_nonblocking( s ) < 0 ) {
     329        EVUTIL_CLOSESOCKET( s );
     330        return -1;
     331    }
    487332
    488333    addrlen = setup_sockaddr( addr, port, &sock );
    489334   
    490335    /* set source address */
    491     source_addr = tr_socketListGetType( tr_getSessionBindSockets( session ),
    492                                         addr->type );
     336    source_addr = tr_sessionGetPublicAddress( session, addr->type );
    493337    assert( source_addr );
    494338    sourcelen = setup_sockaddr( source_addr, 0, &source_sock );
     
    527371tr_netBindTCP( const tr_address * addr, tr_port port, tr_bool suppressMsgs )
    528372{
    529     int                     s;
     373    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
    530374    struct sockaddr_storage sock;
    531     const int               type = SOCK_STREAM;
    532     int                     addrlen;
    533 
    534 #if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT ) || defined( IPV6_V6ONLY )
    535     int                optval = 1;
    536 #endif
     375    int fd;
     376    int addrlen;
     377    int optval;
    537378
    538379    assert( tr_isAddress( addr ) );
    539380
    540     if( ( s = createSocket( ( addr->type == TR_AF_INET ? AF_INET : AF_INET6 ),
    541                             type ) ) < 0 )
    542         return s;
    543 
    544 #ifdef SO_REUSEADDR
    545     setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof( optval ) );
    546 #endif
     381    fd = socket( domains[addr->type], SOCK_STREAM, 0 );
     382    if( fd < 0 )
     383        return -1;
     384
     385    if( evutil_make_socket_nonblocking( fd ) < 0 ) {
     386        EVUTIL_CLOSESOCKET( fd );
     387        return -1;
     388    }
     389
     390    optval = 1;
     391    setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) );
     392    setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) );
    547393
    548394#ifdef IPV6_V6ONLY
    549     if( addr->type == TR_AF_INET6 &&
    550         setsockopt( s, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
    551                              sizeof( optval ) ) == -1 ) {
    552         /* the kernel may not support this. if not, ignore it */
    553         if( errno != ENOPROTOOPT )
    554             return -errno;
    555     }
     395    if( addr->type == TR_AF_INET6 )
     396        if( setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof( optval ) ) == -1 )
     397            if( EVUTIL_SOCKET_ERROR( ) != ENOPROTOOPT ) /* if the kernel doesn't support it, ignore it */
     398                return -EVUTIL_SOCKET_ERROR( );
    556399#endif
    557400
    558401    addrlen = setup_sockaddr( addr, htons( port ), &sock );
    559 
    560     if( bind( s, (struct sockaddr *) &sock,
    561              addrlen ) )
    562     {
    563         int tmperrno;
     402    if( bind( fd, (struct sockaddr *) &sock, addrlen ) ) {
     403        const int err = EVUTIL_SOCKET_ERROR( );
    564404        if( !suppressMsgs )
    565             tr_err( _( "Couldn't bind port %d on %s: %s" ), port,
    566                     tr_ntop_non_ts( addr ), tr_strerror( sockerrno ) );
    567         tmperrno = sockerrno;
    568         tr_netClose( s );
    569         return -tmperrno;
    570     }
     405            tr_err( _( "Couldn't bind port %d on %s: %s" ),
     406                    port, tr_ntop_non_ts( addr ), tr_strerror( err ) );
     407        tr_netClose( fd );
     408        return -err;
     409    }
     410
    571411    if( !suppressMsgs )
    572         tr_dbg(  "Bound socket %d to port %d on %s",
    573                  s, port, tr_ntop_non_ts( addr ) );
    574     return s;
     412        tr_dbg( "Bound socket %d to port %d on %s", fd, port, tr_ntop_non_ts( addr ) );
     413
     414    if( listen( fd, 128 ) == -1 ) {
     415        EVUTIL_CLOSESOCKET( fd );
     416        return -EVUTIL_SOCKET_ERROR( );
     417    }
     418
     419    return fd;
    575420}
    576421
    577422int
    578 tr_netAccept( tr_session  * session,
     423tr_netAccept( tr_session  * session UNUSED,
    579424              int           b,
    580425              tr_address  * addr,
    581426              tr_port     * port )
    582427{
    583     int fd;
    584 
    585     fd = makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) );
    586     setSndBuf( session, fd );
     428    int fd = tr_fdSocketAccept( b, addr, port );
     429
     430    if( fd>=0 && evutil_make_socket_nonblocking(fd)<0 ) {
     431        EVUTIL_CLOSESOCKET( fd );
     432        fd = -1;
     433    }
     434
    587435    return fd;
    588436}
Note: See TracChangeset for help on using the changeset viewer.