Changeset 920 for trunk/libtransmission


Ignore:
Timestamp:
Sep 25, 2006, 6:37:45 PM (15 years ago)
Author:
joshe
Message:

Merge nat-traversal branch to trunk.

Location:
trunk/libtransmission
Files:
17 edited
8 copied

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bencode.c

    r543 r920  
    2626
    2727#define LIST_SIZE   20
    28 #define OUTBUF_SIZE 100
    29 
    30 static int tr_bencSprintf( char ** buf, size_t * used, size_t * max,
    31                            char * format, ... )
    32 #ifdef __GNUC__
    33     __attribute__ ((format (printf, 4, 5)))
    34 #endif
    35     ;
    36 
    37 int _tr_bencLoad( char * buf, size_t len, benc_val_t * val, char ** end )
     28
     29int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
    3830{
    3931    char * p, * e, * foo;
     
    9082        cur              = &buf[1];
    9183        str_expected     = 1;
    92         while( (size_t)(cur - buf) < len && cur[0] != 'e' )
     84        while( cur - buf < len && cur[0] != 'e' )
    9385        {
    9486            if( val->val.l.count == val->val.l.alloc )
     
    140132
    141133        if( p != e || 0 > val->val.s.i ||
    142             (size_t)(val->val.s.i) > len - ((p + 1) - buf) )
     134            val->val.s.i > len - ((p + 1) - buf) )
    143135        {
    144136            return 1;
     
    241233}
    242234
    243 char * tr_bencSaveMalloc( benc_val_t * val, size_t * len )
     235char * tr_bencSaveMalloc( benc_val_t * val, int * len )
    244236{
    245237    char * buf   = NULL;
    246     size_t alloc = 0;
     238    int alloc = 0;
    247239
    248240    *len = 0;
     
    260252}
    261253
    262 int tr_bencSave( benc_val_t * val, char ** buf, size_t * used, size_t * max )
     254int tr_bencSave( benc_val_t * val, char ** buf, int * used, int * max )
    263255{
    264256    int ii;   
     
    267259    {
    268260        case TYPE_INT:
    269             if( tr_bencSprintf( buf, used, max, "i%"PRIu64"e", val->val.i ) )
     261            if( tr_sprintf( buf, used, max, "i%"PRIu64"e", val->val.i ) )
    270262            {
    271263                return 1;
     
    278270                return 1;
    279271            }
    280             if( tr_bencSprintf( buf, used, max, "%i:%s",
    281                                 val->val.s.i, val->val.s.s ) )
     272            if( tr_sprintf( buf, used, max, "%i:%s",
     273                            val->val.s.i, val->val.s.s ) )
    282274            {
    283275                return 1;
     
    287279        case TYPE_LIST:
    288280        case TYPE_DICT:
    289             if( tr_bencSprintf( buf, used, max,
    290                                 (TYPE_LIST == val->type ? "l" : "d") ) )
     281            if( tr_sprintf( buf, used, max,
     282                            (TYPE_LIST == val->type ? "l" : "d") ) )
    291283            {
    292284                return 1;
     
    299291                }
    300292            }
    301             if( tr_bencSprintf( buf, used, max, "e" ) )
     293            if( tr_sprintf( buf, used, max, "e" ) )
    302294            {
    303295                return 1;
     
    308300    return 0;
    309301}
    310 
    311 static int tr_bencSprintf( char ** buf, size_t * used, size_t * max,
    312                            char * format, ... )
    313 {
    314     va_list ap;
    315     int     want;
    316     char  * newbuf;
    317 
    318     va_start( ap, format );
    319     want = vsnprintf( NULL, 0, format, ap );
    320     va_end(ap);
    321 
    322     while( *used + want + 1 > *max )
    323     {
    324         *max += OUTBUF_SIZE;
    325         newbuf = realloc( *buf, *max );
    326         if( NULL == newbuf )
    327         {
    328             return 1;
    329         }
    330         *buf = newbuf;
    331     }
    332 
    333     va_start( ap, format );
    334     *used += vsnprintf( *buf + *used, *max - *used, format, ap );
    335     va_end( ap );
    336 
    337     return 0;
    338 }
  • trunk/libtransmission/bencode.h

    r261 r920  
    5353
    5454#define tr_bencLoad(b,l,v,e) _tr_bencLoad((char*)(b),(l),(v),(char**)(e))
    55 int          _tr_bencLoad( char * buf, size_t len, benc_val_t * val,
     55int          _tr_bencLoad( char * buf, int len, benc_val_t * val,
    5656                           char ** end );
    5757void         tr_bencPrint( benc_val_t * val );
    5858void         tr_bencFree( benc_val_t * val );
    5959benc_val_t * tr_bencDictFind( benc_val_t * val, char * key );
    60 char *       tr_bencSaveMalloc( benc_val_t * val, size_t * len );
     60char *       tr_bencSaveMalloc( benc_val_t * val, int * len );
    6161int          tr_bencSave( benc_val_t * val, char ** buf,
    62                           size_t * used, size_t * max );
     62                          int * used, int * max );
    6363
    6464#endif
  • trunk/libtransmission/fastresume.h

    r326 r920  
    249249    {
    250250        tr_inf( "Wrong size for resume file (%d bytes, %d expected)",
    251                 ftell( file ), size );
     251                (int)ftell( file ), size );
    252252        fclose( file );
    253253        return 1;
  • trunk/libtransmission/inout.c

    r723 r920  
    417417    {
    418418        /* Should not happen */
    419         tr_err( "readOrWriteBytes: offset out of range (%lld, %d, %d)",
     419        tr_err( "readOrWriteBytes: offset out of range (%"PRIu64", %d, %d)",
    420420                offset, size, isWrite );
    421421        goto fail;
  • trunk/libtransmission/internal.h

    r788 r920  
    2929   That is probably ugly to put them all here, but it is sooo
    3030   convenient */
     31#if ( defined( __unix__ ) || defined( unix ) ) && !defined( USG )
     32#include <sys/param.h>
     33#endif
    3134#include <stdio.h>
    3235#include <stdarg.h>
     
    5154#ifdef BEOS_NETSERVER
    5255#  define in_port_t uint16_t
     56#  define socklen_t uint32_t
    5357#else
    5458#  include <arpa/inet.h>
    5559#endif
    5660
     61#ifndef INADDR_NONE
     62#define INADDR_NONE             0xffffffff
     63#endif
     64
    5765#ifdef __GNUC__
    5866#  define UNUSED __attribute__((unused))
     67#  define PRINTF( fmt, args ) __attribute__((format (printf, fmt, args)))
    5968#else
    6069#  define UNUSED
     70#  define PRINTF( fmt, args )
    6171#endif
    6272
     
    108118typedef struct tr_completion_s tr_completion_t;
    109119
     120typedef enum { TR_OK, TR_ERROR, TR_WAIT } tr_tristate_t;
     121
    110122#include "platform.h"
    111123#include "bencode.h"
     
    119131#include "clients.h"
    120132#include "choking.h"
     133#include "natpmp.h"
     134#include "upnp.h"
     135#include "http.h"
     136#include "xml.h"
    121137
    122138struct tr_torrent_s
     
    188204    tr_fd_t      * fdlimit;
    189205    tr_choking_t * choking;
     206    tr_natpmp_t  * natpmp;
     207    tr_upnp_t    * upnp;
    190208
    191209    int            bindPort;
  • trunk/libtransmission/metainfo.c

    r786 r920  
    7070    if( sb.st_size > TORRENT_MAX_SIZE )
    7171    {
    72         tr_err( "Torrent file is too big (%d bytes)", sb.st_size );
     72        tr_err( "Torrent file is too big (%d bytes)", (int)sb.st_size );
    7373        return 1;
    7474    }
  • trunk/libtransmission/net.c

    r791 r920  
    3636 * Returns a non-zero value if an error occurs.
    3737 **********************************************************************/
    38 int tr_netResolve( char * address, struct in_addr * addr )
     38int tr_netResolve( const char * address, struct in_addr * addr )
    3939{
    4040    addr->s_addr = inet_addr( address );
     
    5353struct tr_resolve_s
    5454{
    55     int            status;
     55    tr_tristate_t  status;
    5656    char           * address;
    5757    struct in_addr addr;
     
    9595 * Adds an address to the resolution queue.
    9696 **********************************************************************/
    97 tr_resolve_t * tr_netResolveInit( char * address )
     97tr_resolve_t * tr_netResolveInit( const char * address )
    9898{
    9999    tr_resolve_t * r;
    100100
    101101    r           = malloc( sizeof( tr_resolve_t ) );
    102     r->status   = TR_RESOLVE_WAIT;
     102    r->status   = TR_WAIT;
    103103    r->address  = strdup( address );
    104104    r->refcount = 2;
     
    126126 * Checks the current status of a resolution.
    127127 **********************************************************************/
    128 int tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
    129 {
    130     int ret;
     128tr_tristate_t tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
     129{
     130    tr_tristate_t ret;
    131131
    132132    tr_lockLock( &resolveLock );
    133133    ret = r->status;
    134     if( ret == TR_RESOLVE_OK )
     134    if( ret == TR_OK )
    135135    {
    136136        *addr = r->addr;
     
    202202        {
    203203            memcpy( &r->addr, host->h_addr, host->h_length );
    204             r->status = TR_RESOLVE_OK;
     204            r->status = TR_OK;
    205205        }
    206206        else
    207207        {
    208             r->status = TR_RESOLVE_ERROR;
     208            r->status = TR_ERROR;
    209209        }
    210210       
     
    252252}
    253253
    254 static int createSocket()
     254static int createSocket( int type )
    255255{
    256256    int s;
    257257
    258     s = socket( AF_INET, SOCK_STREAM, 0 );
     258    s = socket( AF_INET, type, 0 );
    259259    if( s < 0 )
    260260    {
     
    266266}
    267267
    268 int tr_netOpen( struct in_addr addr, in_port_t port )
     268int tr_netOpen( struct in_addr addr, in_port_t port, int type )
    269269{
    270270    int s;
    271271    struct sockaddr_in sock;
    272272
    273     s = createSocket();
     273    s = createSocket( type );
    274274    if( s < 0 )
    275275    {
     
    294294}
    295295
    296 int tr_netBind( int port )
     296#ifdef IP_ADD_MEMBERSHIP
     297int tr_netMcastOpen( int port, struct in_addr addr )
     298{
     299    int fd;
     300    struct ip_mreq req;
     301
     302    fd = tr_netBindUDP( port );
     303    if( 0 > fd )
     304    {
     305        return -1;
     306    }
     307
     308    memset( &req, 0, sizeof( req ) );
     309    req.imr_multiaddr.s_addr = addr.s_addr;
     310    req.imr_interface.s_addr = htonl( INADDR_ANY );
     311    if( setsockopt( fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof ( req ) ) )
     312    {
     313        tr_err( "Could not join multicast group (%s)", strerror( errno ) );
     314        tr_netClose( fd );
     315        return -1;
     316    }
     317
     318    return fd;
     319}
     320#else /* IP_ADD_MEMBERSHIP */
     321int tr_netMcastOpen( int port UNUSED, struct in_addr addr UNUSED )
     322{
     323    return -1;
     324}
     325#endif /* IP_ADD_MEMBERSHIP */
     326
     327int tr_netBind( int port, int type )
    297328{
    298329    int s;
    299330    struct sockaddr_in sock;
    300 #ifdef SO_REUSEADDR
     331#if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT )
    301332    int optval;
    302333#endif
    303334
    304     s = createSocket();
     335    s = createSocket( type );
    305336    if( s < 0 )
    306337    {
     
    313344#endif
    314345
     346#ifdef SO_REUSEPORT
     347    if( SOCK_DGRAM == type )
     348    {
     349        optval = 1;
     350        setsockopt( s, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof( optval ) );
     351    }
     352#endif
     353
    315354    memset( &sock, 0, sizeof( sock ) );
    316355    sock.sin_family      = AF_INET;
     
    325364        return -1;
    326365    }
    327    
    328     tr_inf( "Binded port %d", port );
    329     listen( s, 5 );
    330366
    331367    return s;
     
    372408}
    373409
    374 int tr_netRecv( int s, uint8_t * buf, int size )
    375 {
    376     int ret;
    377 
    378     ret = recv( s, buf, size, 0 );
     410int tr_netRecvFrom( int s, uint8_t * buf, int size, struct sockaddr_in * addr )
     411{
     412    socklen_t len;
     413    int       ret;
     414
     415    len = ( NULL == addr ? 0 : sizeof( *addr ) );
     416    ret = recvfrom( s, buf, size, 0, ( struct sockaddr * ) addr, &len );
    379417    if( ret < 0 )
    380418    {
  • trunk/libtransmission/net.h

    r791 r920  
    2727 * DNS resolution
    2828 **********************************************************************/
    29 int tr_netResolve( char *, struct in_addr * );
     29int tr_netResolve( const char *, struct in_addr * );
    3030
    31 #define TR_RESOLVE_WAIT  0
    32 #define TR_RESOLVE_ERROR 1
    33 #define TR_RESOLVE_OK    2
    3431typedef struct tr_resolve_s tr_resolve_t;
    3532void           tr_netResolveThreadInit();
    3633void           tr_netResolveThreadClose();
    37 tr_resolve_t * tr_netResolveInit( char * );
    38 int            tr_netResolvePulse( tr_resolve_t *, struct in_addr * );
     34tr_resolve_t * tr_netResolveInit( const char * );
     35tr_tristate_t  tr_netResolvePulse( tr_resolve_t *, struct in_addr * );
    3936void           tr_netResolveClose( tr_resolve_t * );
    4037
     
    4340 * TCP sockets
    4441 **********************************************************************/
    45 int  tr_netOpen    ( struct in_addr addr, in_port_t port );
    46 int  tr_netBind    ( int );
     42#define tr_netOpenTCP( addr, port ) tr_netOpen( (addr), (port), SOCK_STREAM )
     43#define tr_netOpenUDP( addr, port ) tr_netOpen( (addr), (port), SOCK_DGRAM )
     44int  tr_netOpen    ( struct in_addr addr, in_port_t port, int type );
     45int  tr_netMcastOpen( int port, struct in_addr addr );
     46#define tr_netBindTCP( port ) tr_netBind( (port), SOCK_STREAM )
     47#define tr_netBindUDP( port ) tr_netBind( (port), SOCK_DGRAM )
     48int  tr_netBind    ( int port, int type );
    4749int  tr_netAccept  ( int s, struct in_addr *, in_port_t * );
    4850void tr_netClose   ( int s );
     
    5153#define TR_NET_CLOSE 0x40000000
    5254int  tr_netSend    ( int s, uint8_t * buf, int size );
    53 int  tr_netRecv    ( int s, uint8_t * buf, int size );
     55#define tr_netRecv( s, buf, size ) tr_netRecvFrom( (s), (buf), (size), NULL )
     56int  tr_netRecvFrom( int s, uint8_t * buf, int size, struct sockaddr_in * );
    5457
    5558void tr_netNtop( const struct in_addr * addr, char * buf, int len );
  • trunk/libtransmission/peer.c

    r774 r920  
    101101
    102102#define peer_dbg( a... ) __peer_dbg( peer, ## a )
     103static void __peer_dbg( tr_peer_t * peer, char * msg, ... ) PRINTF( 2, 3 );
     104
    103105static void __peer_dbg( tr_peer_t * peer, char * msg, ... )
    104106{
  • trunk/libtransmission/peerutils.h

    r261 r920  
    152152        !tr_fdSocketWillCreate( tor->fdlimit, 0 ) )
    153153    {
    154         peer->socket = tr_netOpen( peer->addr, peer->port );
     154        peer->socket = tr_netOpenTCP( peer->addr, peer->port );
    155155        if( peer->socket < 0 )
    156156        {
  • trunk/libtransmission/platform.c

    r679 r920  
    197197}
    198198
     199#if defined( BSD )
     200
     201#include <sys/sysctl.h>
     202#include <net/route.h>
     203
     204static uint8_t *
     205getroute( int * buflen );
     206static int
     207parseroutes( uint8_t * buf, int len, struct in_addr * addr );
     208
     209int
     210tr_getDefaultRoute( struct in_addr * addr )
     211{
     212    uint8_t * buf;
     213    int len;
     214
     215    buf = getroute( &len );
     216    if( NULL == buf )
     217    {
     218        tr_err( "failed to get default route (BSD)" );
     219        return 1;
     220    }
     221
     222    len = parseroutes( buf, len, addr );
     223    free( buf );
     224
     225    return len;
     226}
     227
     228#ifndef SA_SIZE
     229#define ROUNDUP( a, size ) \
     230    ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) )
     231#define SA_SIZE( sap ) \
     232    ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \
     233                    sizeof( u_long ) )
     234#endif /* !SA_SIZE */
     235#define NEXT_SA( sap ) \
     236    (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) )
     237
     238static uint8_t *
     239getroute( int * buflen )
     240{
     241    int     mib[6];
     242    size_t  len;
     243    uint8_t * buf;
     244
     245    mib[0] = CTL_NET;
     246    mib[1] = PF_ROUTE;
     247    mib[2] = 0;
     248    mib[3] = AF_INET;
     249    mib[4] = NET_RT_FLAGS;
     250    mib[5] = RTF_GATEWAY;
     251
     252    if( sysctl( mib, 6, NULL, &len, NULL, 0 ) )
     253    {
     254        if( ENOENT != errno )
     255        {
     256            tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
     257                    strerror( errno ) );
     258        }
     259        *buflen = 0;
     260        return NULL;
     261    }
     262
     263    buf = malloc( len );
     264    if( NULL == buf )
     265    {
     266        *buflen = 0;
     267        return NULL;
     268    }
     269
     270    if( sysctl( mib, 6, buf, &len, NULL, 0 ) )
     271    {
     272        tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
     273                strerror( errno ) );
     274        free( buf );
     275        *buflen = 0;
     276        return NULL;
     277    }
     278
     279    *buflen = len;
     280
     281    return buf;
     282}
     283
     284static int
     285parseroutes( uint8_t * buf, int len, struct in_addr * addr )
     286{
     287    uint8_t            * end;
     288    struct rt_msghdr   * rtm;
     289    struct sockaddr    * sa;
     290    struct sockaddr_in * sin;
     291    int                  ii;
     292    struct in_addr       dest, gw;
     293
     294    end = buf + len;
     295    while( end > buf + sizeof( *rtm ) )
     296    {
     297        rtm = (struct rt_msghdr *) buf;
     298        buf += rtm->rtm_msglen;
     299        if( end >= buf )
     300        {
     301            dest.s_addr = INADDR_NONE;
     302            gw.s_addr   = INADDR_NONE;
     303            sa = (struct sockaddr *) ( rtm + 1 );
     304
     305            for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ )
     306            {
     307                if( buf < (uint8_t *) NEXT_SA( sa ) )
     308                {
     309                    break;
     310                }
     311
     312                if( rtm->rtm_addrs & ( 1 << ii ) )
     313                {
     314                    if( AF_INET == sa->sa_family )
     315                    {
     316                        sin = (struct sockaddr_in *) sa;
     317                        switch( ii )
     318                        {
     319                            case RTAX_DST:
     320                                dest = sin->sin_addr;
     321                                break;
     322                            case RTAX_GATEWAY:
     323                                gw = sin->sin_addr;
     324                                break;
     325                        }
     326                    }
     327                    sa = NEXT_SA( sa );
     328                }
     329            }
     330
     331            if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr )
     332            {
     333                *addr = gw;
     334                return 0;
     335            }
     336        }
     337    }
     338
     339    return 1;
     340}
     341
     342#elif defined( linux ) || defined( __linux ) || defined( __linux__ )
     343
     344#include <linux/types.h>
     345#include <linux/netlink.h>
     346#include <linux/rtnetlink.h>
     347
     348#define SEQNUM 195909
     349
     350static int
     351getsock( void );
     352static uint8_t *
     353getroute( int fd, unsigned int * buflen );
     354static int
     355parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );
     356
     357int
     358tr_getDefaultRoute( struct in_addr * addr )
     359{
     360    int fd, ret;
     361    unsigned int len;
     362    uint8_t * buf;
     363
     364    ret = 1;
     365    fd = getsock();
     366    if( 0 <= fd )
     367    {
     368        while( ret )
     369        {
     370            buf = getroute( fd, &len );
     371            if( NULL == buf )
     372            {
     373                break;
     374            }
     375            ret = parseroutes( buf, len, addr );
     376            free( buf );
     377        }
     378        close( fd );
     379    }
     380
     381    if( ret )
     382    {
     383        tr_err( "failed to get default route (Linux)" );
     384    }
     385
     386    return ret;
     387}
     388
     389static int
     390getsock( void )
     391{
     392    int fd, flags;
     393    struct
     394    {
     395        struct nlmsghdr nlh;
     396        struct rtgenmsg rtg;
     397    } req;
     398    struct sockaddr_nl snl;
     399
     400    fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE );
     401    if( 0 > fd )
     402    {
     403        tr_err( "failed to create routing socket (%s)", strerror( errno ) );
     404        return -1;
     405    }
     406
     407    flags = fcntl( fd, F_GETFL );
     408    if( 0 > flags || 0 > fcntl( fd, F_SETFL, O_NONBLOCK | flags ) )
     409    {
     410        tr_err( "failed to set socket nonblocking (%s)", strerror( errno ) );
     411        close( fd );
     412        return -1;
     413    }
     414
     415    bzero( &snl, sizeof( snl ) );
     416    snl.nl_family = AF_NETLINK;
     417
     418    bzero( &req, sizeof( req ) );
     419    req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) );
     420    req.nlh.nlmsg_type = RTM_GETROUTE;
     421    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
     422    req.nlh.nlmsg_seq = SEQNUM;
     423    req.nlh.nlmsg_pid = 0;
     424    req.rtg.rtgen_family = AF_INET;
     425
     426    if( 0 > sendto( fd, &req, sizeof( req ), 0,
     427                    (struct sockaddr *) &snl, sizeof( snl ) ) )
     428    {
     429        tr_err( "failed to write to routing socket (%s)", strerror( errno ) );
     430        close( fd );
     431        return -1;
     432    }
     433
     434    return fd;
     435}
     436
     437static uint8_t *
     438getroute( int fd, unsigned int * buflen )
     439{
     440    void             * buf;
     441    unsigned int       len;
     442    ssize_t            res;
     443    struct sockaddr_nl snl;
     444    socklen_t          slen;
     445
     446    len = 8192;
     447    buf = calloc( 1, len );
     448    if( NULL == buf )
     449    {
     450        *buflen = 0;
     451        return NULL;
     452    }
     453
     454    for( ;; )
     455    {
     456        bzero( &snl, sizeof( snl ) );
     457        slen = sizeof( snl );
     458        res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen );
     459        if( 0 > res )
     460        {
     461            if( EAGAIN != errno )
     462            {
     463                tr_err( "failed to read from routing socket (%s)",
     464                        strerror( errno ) );
     465            }
     466            free( buf );
     467            *buflen = 0;
     468            return NULL;
     469        }
     470        if( slen < sizeof( snl ) || AF_NETLINK != snl.nl_family )
     471        {
     472            tr_err( "bad address" );
     473            free( buf );
     474            *buflen = 0;
     475            return NULL;
     476        }
     477
     478        if( 0 == snl.nl_pid )
     479        {
     480            break;
     481        }
     482    }
     483
     484    *buflen = res;
     485
     486    return buf;
     487}
     488
     489static int
     490parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr )
     491{
     492    struct nlmsghdr * nlm;
     493    struct nlmsgerr * nle;
     494    struct rtmsg    * rtm;
     495    struct rtattr   * rta;
     496    int               rtalen;
     497    struct in_addr    gw, dst;
     498
     499    nlm = ( struct nlmsghdr * ) buf;
     500    while( NLMSG_OK( nlm, len ) )
     501    {
     502        gw.s_addr = INADDR_ANY;
     503        dst.s_addr = INADDR_ANY;
     504        if( NLMSG_ERROR == nlm->nlmsg_type )
     505        {
     506            nle = (struct nlmsgerr *) NLMSG_DATA( nlm );
     507            if( NLMSG_LENGTH( NLMSG_ALIGN( sizeof( struct nlmsgerr ) ) ) >
     508                nlm->nlmsg_len )
     509            {
     510                tr_err( "truncated netlink error" );
     511            }
     512            else
     513            {
     514                tr_err( "netlink error (%s)", strerror( nle->error ) );
     515            }
     516            return 1;
     517        }
     518        else if( RTM_NEWROUTE == nlm->nlmsg_type && SEQNUM == nlm->nlmsg_seq &&
     519                 getpid() == (pid_t) nlm->nlmsg_pid &&
     520                 NLMSG_LENGTH( sizeof( struct rtmsg ) ) <= nlm->nlmsg_len )
     521        {
     522            rtm = NLMSG_DATA( nlm );
     523            rta = RTM_RTA( rtm );
     524            rtalen = RTM_PAYLOAD( nlm );
     525
     526            while( RTA_OK( rta, rtalen ) )
     527            {
     528                if( sizeof( struct in_addr ) <= RTA_PAYLOAD( rta ) )
     529                {
     530                    switch( rta->rta_type )
     531                    {
     532                        case RTA_GATEWAY:
     533                            memcpy( &gw, RTA_DATA( rta ), sizeof( gw ) );
     534                            break;
     535                        case RTA_DST:
     536                            memcpy( &dst, RTA_DATA( rta ), sizeof( dst ) );
     537                            break;
     538                    }
     539                }
     540                rta = RTA_NEXT( rta, rtalen );
     541            }
     542        }
     543
     544        if( INADDR_NONE != gw.s_addr && INADDR_ANY != gw.s_addr &&
     545            INADDR_ANY == dst.s_addr )
     546        {
     547            *addr = gw;
     548            return 0;
     549        }
     550
     551        nlm = NLMSG_NEXT( nlm, len );
     552    }
     553
     554    return 1;
     555}
     556
     557#else /* not BSD or Linux */
     558
     559int
     560tr_getDefaultRoute( struct in_addr * addr UNUSED )
     561{
     562    tr_inf( "don't know how to get default route on this platform" );
     563    return 1;
     564}
     565
     566#endif
  • trunk/libtransmission/platform.h

    r310 r920  
    6161}
    6262
     63int
     64tr_getDefaultRoute( struct in_addr * addr );
     65
    6366#endif
  • trunk/libtransmission/tracker.c

    r854 r920  
    4343    uint64_t       dateOk;
    4444
    45 #define TC_STATUS_IDLE    1
    46 #define TC_STATUS_RESOLVE 2
    47 #define TC_STATUS_CONNECT 4
    48 #define TC_STATUS_RECV    8
    49     char           status;
    50 
    5145#define TC_ATTEMPT_NOREACH 1
    5246#define TC_ATTEMPT_ERROR   2
     
    5448    char           lastAttempt;
    5549
    56     tr_resolve_t * resolve;
    57     int            socket;
    58     uint8_t      * buf;
    59     int            size;
    60     int            pos;
     50    tr_http_t    * http;
    6151
    6252    int            bindPort;
     
    6757};
    6858
    69 static void sendQuery  ( tr_tracker_t * tc );
    70 static void recvAnswer ( tr_tracker_t * tc );
     59static tr_http_t * getQuery   ( tr_tracker_t * tc );
     60static void        readAnswer ( tr_tracker_t * tc, const char *, int );
    7161
    7262tr_tracker_t * tr_trackerInit( tr_torrent_t * tor )
     
    8474    tc->leechers = -1;
    8575
    86     tc->status   = TC_STATUS_IDLE;
    8776    tc->lastAttempt = TC_ATTEMPT_NOREACH;
    88     tc->size     = 1024;
    89     tc->buf      = malloc( tc->size );
    9077
    9178    tc->bindPort = *(tor->bindPort);
     
    160147    tr_torrent_t * tor = tc->tor;
    161148    tr_info_t    * inf = &tor->info;
    162     uint64_t       now = tr_date();
    163 
    164     if( ( tc->status & TC_STATUS_IDLE ) && shouldConnect( tc ) )
    165     {
    166         tc->resolve = tr_netResolveInit( inf->trackerAddress );
     149    const char   * data;
     150    int            len;
     151
     152    if( ( NULL == tc->http ) && shouldConnect( tc ) )
     153    {
     154        if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) )
     155        {
     156            return 0;
     157        }
     158        tc->dateTry = tr_date();
     159        tc->http = getQuery( tc );
    167160
    168161        tr_inf( "Tracker: connecting to %s:%d (%s)",
     
    173166                    ( 0 < tc->newPort ? "sending 'stopped' to change port" :
    174167                      "getting peers" ) ) ) );
    175 
    176         tc->status  = TC_STATUS_RESOLVE;
    177         tc->dateTry = tr_date();
    178     }
    179 
    180     if( tc->status & TC_STATUS_RESOLVE )
    181     {
    182         int ret;
    183         struct in_addr addr;
    184 
    185         ret = tr_netResolvePulse( tc->resolve, &addr );
    186         if( ret == TR_RESOLVE_WAIT )
    187         {
    188             return 0;
    189         }
    190         else
    191         {
    192             tr_netResolveClose( tc->resolve );
    193         }
    194        
    195         if( ret == TR_RESOLVE_ERROR )
    196         {
    197             tc->status = TC_STATUS_IDLE;
    198             return 0;
    199         }
    200 
    201         if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) )
    202         {
    203             tc->status = TC_STATUS_IDLE;
    204             return 0;
    205         }
    206 
    207         tc->socket = tr_netOpen( addr, htons( inf->trackerPort ) );
    208         if( tc->socket < 0 )
    209         {
    210             tr_fdSocketClosed( tor->fdlimit, 1 );
    211             tc->status = TC_STATUS_IDLE;
    212             return 0;
    213         }
    214 
    215         tc->status = TC_STATUS_CONNECT;
    216     }
    217 
    218     if( tc->status & TC_STATUS_CONNECT )
    219     {
    220         /* We are connecting to the tracker. Try to send the query */
    221         sendQuery( tc );
    222     }
    223 
    224     if( tc->status & TC_STATUS_RECV )
    225     {
    226         /* Try to get something */
    227         recvAnswer( tc );
    228     }
    229 
    230     if( tc->status > TC_STATUS_IDLE && now > tc->dateTry + 60000 )
    231     {
    232         /* Give up if the request wasn't successful within 60 seconds */
    233         tr_inf( "Tracker: timeout reached (60 s)" );
    234 
    235         tr_netClose( tc->socket );
    236         tr_fdSocketClosed( tor->fdlimit, 1 );
    237 
    238         tc->status  = TC_STATUS_IDLE;
    239         tc->dateTry = tr_date();
     168    }
     169
     170    if( NULL != tc->http )
     171    {
     172        switch( tr_httpPulse( tc->http, &data, &len ) )
     173        {
     174            case TR_WAIT:
     175                return 0;
     176
     177            case TR_ERROR:
     178                tr_httpClose( tc->http );
     179                tr_fdSocketClosed( tor->fdlimit, 1 );
     180                tc->http    = NULL;
     181                tc->dateTry = tr_date();
     182                return 0;
     183
     184            case TR_OK:
     185                readAnswer( tc, data, len );
     186                tr_httpClose( tc->http );
     187                tc->http = NULL;
     188                tr_fdSocketClosed( tor->fdlimit, 1 );
     189                break;
     190        }
    240191    }
    241192
     
    254205    tr_torrent_t * tor = tc->tor;
    255206
    256     if( tc->status > TC_STATUS_CONNECT )
     207    if( NULL != tc->http )
    257208    {
    258209        /* If we are already sendy a query at the moment, we need to
    259210           reconnect */
    260         tr_netClose( tc->socket );
     211        tr_httpClose( tc->http );
     212        tc->http = NULL;
    261213        tr_fdSocketClosed( tor->fdlimit, 1 );
    262         tc->status = TC_STATUS_IDLE;
    263214    }
    264215
     
    268219
    269220    /* Even if we have connected recently, reconnect right now */
    270     if( tc->status & TC_STATUS_IDLE )
    271     {
    272         tc->dateTry = 0;
    273     }
     221    tc->dateTry = 0;
    274222}
    275223
     
    278226    tr_torrent_t * tor = tc->tor;
    279227
    280     if( tc->status == TC_STATUS_RESOLVE )
    281     {
    282         tr_netResolveClose( tc->resolve );
    283     }
    284     else if( tc->status > TC_STATUS_RESOLVE )
    285     {
    286         tr_netClose( tc->socket );
     228    if( NULL != tc->http )
     229    {
     230        tr_httpClose( tc->http );
    287231        tr_fdSocketClosed( tor->fdlimit, 1 );
    288232    }
    289     free( tc->buf );
    290233    free( tc );
    291234}
    292235
    293 static void sendQuery( tr_tracker_t * tc )
     236static tr_http_t * getQuery( tr_tracker_t * tc )
    294237{
    295238    tr_torrent_t * tor = tc->tor;
    296239    tr_info_t    * inf = &tor->info;
    297240
    298     char     * event;
    299     uint64_t   left;
    300     int        ret;
    301     uint64_t   down;
    302     uint64_t   up;
     241    char         * event;
     242    uint64_t       left;
     243    uint64_t       down;
     244    uint64_t       up;
    303245
    304246    assert( tor->downloaded >= tc->download && tor->uploaded >= tc->upload );
     
    331273    left = tr_cpLeftBytes( tor->completion );
    332274
    333     ret = snprintf( (char *) tc->buf, tc->size,
    334             "GET %s?"
    335             "info_hash=%s&"
    336             "peer_id=%s&"
    337             "port=%d&"
    338             "uploaded=%"PRIu64"&"
    339             "downloaded=%"PRIu64"&"
    340             "left=%"PRIu64"&"
    341             "compact=1&"
    342             "numwant=50&"
    343             "key=%s"
    344             "%s "
    345             "HTTP/1.1\r\n"
    346             "Host: %s\r\n"
    347             "User-Agent: Transmission/%d.%d\r\n"
    348             "Connection: close\r\n\r\n",
    349             inf->trackerAnnounce, tor->hashString, tc->id,
    350             tc->bindPort, up, down,
    351             left, tor->key, event, inf->trackerAddress,
    352             VERSION_MAJOR, VERSION_MINOR );
    353 
    354     ret = tr_netSend( tc->socket, tc->buf, ret );
    355     if( ret & TR_NET_CLOSE )
    356     {
    357         tr_inf( "Tracker: connection failed" );
    358         tr_netClose( tc->socket );
    359         tr_fdSocketClosed( tor->fdlimit, 1 );
    360         tc->status  = TC_STATUS_IDLE;
    361         tc->dateTry = tr_date();
    362     }
    363     else if( !( ret & TR_NET_BLOCK ) )
    364     {
    365         // printf( "Tracker: sent %s", tc->buf );
    366         tc->status = TC_STATUS_RECV;
    367         tc->pos    = 0;
    368     }
    369 }
    370 
    371 static void recvAnswer( tr_tracker_t * tc )
     275    return tr_httpClient( TR_HTTP_GET, inf->trackerAddress,
     276                          inf->trackerPort,
     277                          "%s?"
     278                          "info_hash=%s&"
     279                          "peer_id=%s&"
     280                          "port=%d&"
     281                          "uploaded=%"PRIu64"&"
     282                          "downloaded=%"PRIu64"&"
     283                          "left=%"PRIu64"&"
     284                          "compact=1&"
     285                          "numwant=50&"
     286                          "key=%s"
     287                          "%s ",
     288                          inf->trackerAnnounce, tor->hashString, tc->id,
     289                          tc->bindPort, up, down, left, tor->key, event );
     290}
     291
     292static void readAnswer( tr_tracker_t * tc, const char * data, int len )
    372293{
    373294    tr_torrent_t * tor = tc->tor;
    374     int ret;
    375295    int i;
     296    int code;
    376297    benc_val_t   beAll;
    377298    benc_val_t * bePeers, * beFoo;
    378     uint8_t * body;
     299    const uint8_t * body;
    379300    int bodylen;
    380301    int shouldfree;
    381302
    382     if( tc->pos == tc->size )
    383     {
    384         tc->size *= 2;
    385         tc->buf   = realloc( tc->buf, tc->size );
    386     }
    387    
    388     ret = tr_netRecv( tc->socket, &tc->buf[tc->pos],
    389                     tc->size - tc->pos );
    390 
    391     if( ret & TR_NET_BLOCK )
    392     {
    393         return;
    394     }
    395     if( !( ret & TR_NET_CLOSE ) )
    396     {
    397         // printf( "got %d bytes\n", ret );
    398         tc->pos += ret;
    399         return;
    400     }
    401 
    402     tr_netClose( tc->socket );
    403     tr_fdSocketClosed( tor->fdlimit, 1 );
    404     // printf( "connection closed, got total %d bytes\n", tc->pos );
    405 
    406     tc->status  = TC_STATUS_IDLE;
    407303    tc->dateTry = tr_date();
    408 
    409     if( tc->pos < 12 || ( 0 != memcmp( tc->buf, "HTTP/1.0 ", 9 ) &&
    410                           0 != memcmp( tc->buf, "HTTP/1.1 ", 9 ) ) )
    411     {
    412         /* We don't have a complete HTTP status line */
    413         tr_inf( "Tracker: incomplete HTTP status line" );
     304    code = tr_httpResponseCode( data, len );
     305    if( 0 > code )
     306    {
     307        /* We don't have a valid HTTP status line */
     308        tr_inf( "Tracker: invalid HTTP status line" );
    414309        tc->lastAttempt = TC_ATTEMPT_NOREACH;
    415310        return;
    416311    }
    417312
    418     if( '2' != tc->buf[9] )
     313    if( !TR_HTTP_STATUS_OK( code ) )
    419314    {
    420315        /* we didn't get a 2xx status code */
    421         tr_err( "Tracker: invalid HTTP status code: %c%c%c",
    422                 tc->buf[9], tc->buf[10], tc->buf[11] );
     316        tr_err( "Tracker: invalid HTTP status code: %i", code );
    423317        tc->lastAttempt = TC_ATTEMPT_ERROR;
    424318        return;
     
    426320
    427321    /* find the end of the http headers */
    428     body = tr_memmem( tc->buf, tc->pos, "\015\012\015\012", 4 );
    429     if( NULL != body )
    430     {
    431         body += 4;
    432     }
    433     /* hooray for trackers that violate the HTTP spec */
    434     else if( NULL != ( body = tr_memmem( tc->buf, tc->pos, "\015\015", 2 ) ) ||
    435              NULL != ( body = tr_memmem( tc->buf, tc->pos, "\012\012", 2 ) ) )
    436     {
    437         body += 2;
    438     }
    439     else
     322    body = (uint8_t *) tr_httpParse( data, len, NULL );
     323    if( NULL == body )
    440324    {
    441325        tr_err( "Tracker: could not find end of HTTP headers" );
     
    443327        return;
    444328    }
    445     bodylen = tc->pos - (body - tc->buf);
     329    bodylen = len - (body - (const uint8_t*)data);
    446330
    447331    /* Find and load the dictionary */
     
    611495    tr_info_t * inf = &tor->info;
    612496
    613     int s, i, ret;
    614     uint8_t buf[1024];
    615     benc_val_t scrape, * val1, * val2;
    616     struct in_addr addr;
    617     uint64_t date;
    618     int pos, len;
    619     tr_resolve_t * resolve;
     497    tr_http_t  * http;
     498    const char * data, * body;
     499    int          datalen, bodylen;
     500    int          code, ii;
     501    benc_val_t   scrape, * val1, * val2;
    620502
    621503    if( !tor->scrape[0] )
     
    625507    }
    626508
    627     resolve = tr_netResolveInit( inf->trackerAddress );
    628     for( date = tr_date();; )
    629     {
    630         ret = tr_netResolvePulse( resolve, &addr );
    631         if( ret == TR_RESOLVE_OK )
    632         {
    633             tr_netResolveClose( resolve );
     509    http = tr_httpClient( TR_HTTP_GET, inf->trackerAddress, inf->trackerPort,
     510                          "%s?info_hash=%s", tor->scrape, tor->hashString );
     511
     512    data = NULL;
     513    while( NULL == data )
     514    {
     515        switch( tr_httpPulse( http, &data, &datalen ) )
     516        {
     517            case TR_WAIT:
     518                break;
     519
     520            case TR_ERROR:
     521                tr_httpClose( http );
     522                return 1;
     523
     524            case TR_OK:
     525                if( NULL == data || 0 >= datalen )
     526                {
     527                    tr_httpClose( http );
     528                    return 1;
     529                }
     530                break;
     531        }
     532        tr_wait( 10 );
     533    }
     534
     535    code = tr_httpResponseCode( data, datalen );
     536    if( !TR_HTTP_STATUS_OK( code ) )
     537    {
     538        tr_httpClose( http );
     539        return 1;
     540    }
     541
     542    body = tr_httpParse( data, datalen , NULL );
     543    if( NULL == body )
     544    {
     545        tr_httpClose( http );
     546        return 1;
     547    }
     548    bodylen = datalen - ( body - data );
     549
     550    for( ii = 0; ii < bodylen - 8; ii++ )
     551    {
     552        if( !memcmp( body + ii, "d5:files", 8 ) )
     553        {
    634554            break;
    635555        }
    636         if( ret == TR_RESOLVE_ERROR ||
    637             ( ret == TR_RESOLVE_WAIT && tr_date() > date + 10000 ) )
    638         {
    639             tr_err( "Could not resolve %s", inf->trackerAddress );
    640             tr_netResolveClose( resolve );
    641             return 1;
    642         }
    643         tr_wait( 10 );
    644     }
    645 
    646     s = tr_netOpen( addr, htons( inf->trackerPort ) );
    647     if( s < 0 )
    648     {
    649         return 1;
    650     }
    651 
    652     len = snprintf( (char *) buf, sizeof( buf ),
    653               "GET %s?info_hash=%s HTTP/1.1\r\n"
    654               "Host: %s\r\n"
    655               "Connection: close\r\n\r\n",
    656               tor->scrape, tor->hashString,
    657               inf->trackerAddress );
    658 
    659     for( date = tr_date();; )
    660     {
    661         ret = tr_netSend( s, buf, len );
    662         if( ret & TR_NET_CLOSE )
    663         {
    664             tr_err( "Could not connect to tracker" );
    665             tr_netClose( s );
    666             return 1;
    667         }
    668         else if( ret & TR_NET_BLOCK )
    669         {
    670             if( tr_date() > date + 10000 )
    671             {
    672                 tr_err( "Could not connect to tracker" );
    673                 tr_netClose( s );
    674                 return 1;
    675             }
    676         }
    677         else
    678         {
    679             break;
    680         }
    681         tr_wait( 10 );
    682     }
    683 
    684     pos = 0;
    685     for( date = tr_date();; )
    686     {
    687         ret = tr_netRecv( s, &buf[pos], sizeof( buf ) - pos );
    688         if( ret & TR_NET_CLOSE )
    689         {
    690             break;
    691         }
    692         else if( ret & TR_NET_BLOCK )
    693         {
    694             if( tr_date() > date + 10000 )
    695             {
    696                 tr_err( "Could not read from tracker" );
    697                 tr_netClose( s );
    698                 return 1;
    699             }
    700         }
    701         else
    702         {
    703             pos += ret;
    704         }
    705         tr_wait( 10 );
    706     }
    707 
    708     if( pos < 1 )
    709     {
    710         tr_err( "Could not read from tracker" );
    711         tr_netClose( s );
    712         return 1;
    713     }
    714 
    715     for( i = 0; i < pos - 8; i++ )
    716     {
    717         if( !memcmp( &buf[i], "d5:files", 8 ) )
    718         {
    719             break;
    720         }
    721     }
    722     if( i >= pos - 8 )
    723     {
    724         return 1;
    725     }
    726     if( tr_bencLoad( &buf[i], pos - i, &scrape, NULL ) )
    727     {
     556    }
     557    if( ii >= bodylen - 8 )
     558    {
     559        tr_httpClose( http );
     560        return 1;
     561    }
     562    if( tr_bencLoad( body + ii, bodylen - ii, &scrape, NULL ) )
     563    {
     564        tr_httpClose( http );
    728565        return 1;
    729566    }
     
    732569    if( !val1 )
    733570    {
     571        tr_bencFree( &scrape );
     572        tr_httpClose( http );
    734573        return 1;
    735574    }
     
    737576    if( !val1 )
    738577    {
     578        tr_bencFree( &scrape );
     579        tr_httpClose( http );
    739580        return 1;
    740581    }
     
    742583    if( !val2 )
    743584    {
     585        tr_bencFree( &scrape );
     586        tr_httpClose( http );
    744587        return 1;
    745588    }
     
    748591    if( !val2 )
    749592    {
     593        tr_bencFree( &scrape );
     594        tr_httpClose( http );
    750595        return 1;
    751596    }
    752597    *leechers = val2->val.i;
    753598    tr_bencFree( &scrape );
     599    tr_httpClose( http );
    754600
    755601    return 0;
  • trunk/libtransmission/transmission.c

    r815 r920  
    7575    h->fdlimit  = tr_fdInit();
    7676    h->choking  = tr_chokingInit( h );
     77    h->natpmp   = tr_natpmpInit( h->fdlimit );
     78    h->upnp     = tr_upnpInit( h->fdlimit );
    7779
    7880    h->bindPort = -1;
     
    105107    {
    106108        /* XXX should handle failure here in a better way */
    107         sock = tr_netBind( port );
     109        sock = tr_netBindTCP( port );
     110        if( 0 > sock)
     111        {
     112            tr_fdSocketClosed( h->fdlimit, 0 );
     113        }
     114        else
     115        {   
     116            tr_inf( "Bound listening port %d", port );
     117            listen( sock, 5 );
     118        }
    108119    }
    109120#else
     
    133144    h->bindSocket = sock;
    134145
     146    tr_natpmpForwardPort( h->natpmp, port );
     147    tr_upnpForwardPort( h->upnp, port );
     148
    135149    tr_lockUnlock( &h->acceptLock );
     150}
     151
     152void tr_natTraversalEnable( tr_handle_t * h )
     153{
     154    tr_natpmpStart( h->natpmp );
     155    tr_upnpStart( h->upnp );
     156}
     157
     158void tr_natTraversalDisable( tr_handle_t * h )
     159{
     160    tr_natpmpStop( h->natpmp );
     161    tr_upnpStop( h->upnp );
     162}
     163
     164int tr_natTraversalStatus( tr_handle_t * h )
     165{
     166    int statuses[] = {
     167        TR_NAT_TRAVERSAL_MAPPED,
     168        TR_NAT_TRAVERSAL_MAPPING,
     169        TR_NAT_TRAVERSAL_UNMAPPING,
     170        TR_NAT_TRAVERSAL_ERROR,
     171        TR_NAT_TRAVERSAL_NOTFOUND,
     172        TR_NAT_TRAVERSAL_DISABLED,
     173        -1,
     174    };
     175    int natpmp, upnp, ii;
     176
     177    natpmp = tr_natpmpStatus( h->natpmp );
     178    upnp = tr_upnpStatus( h->upnp );
     179
     180    for( ii = 0; 0 <= statuses[ii]; ii++ )
     181    {
     182        if( statuses[ii] == natpmp || statuses[ii] == upnp )
     183        {
     184            return statuses[ii];
     185        }
     186    }
     187
     188    assert( 0 );
     189
     190    return TR_NAT_TRAVERSAL_ERROR;
    136191}
    137192
     
    630685{
    631686    acceptStop( h );
     687    tr_natpmpClose( h->natpmp );
     688    tr_upnpClose( h->upnp );
    632689    tr_chokingClose( h->choking );
    633690    tr_fdClose( h->fdlimit );
     
    735792    {
    736793        date1 = tr_date();
     794
     795        /* do NAT-PMP and UPnP pulses here since there's nowhere better */
     796        tr_natpmpPulse( h->natpmp );
     797        tr_upnpPulse( h->upnp );
    737798
    738799        /* Check for incoming connections */
  • trunk/libtransmission/transmission.h

    r817 r920  
    100100 * tr_setBindPort
    101101 ***********************************************************************
    102  * Sets the port to listen for incoming peer connections
     102 * Sets the port to listen for incoming peer connections.
     103 * This can be safely called even with active torrents.
    103104 **********************************************************************/
    104105void tr_setBindPort( tr_handle_t *, int );
     106
     107/***********************************************************************
     108 * tr_natTraversalEnable
     109 * tr_natTraversalDisable
     110 ***********************************************************************
     111 * Enable or disable NAT traversal using NAT-PMP or UPnP IGD.
     112 **********************************************************************/
     113void tr_natTraversalEnable( tr_handle_t * );
     114void tr_natTraversalDisable( tr_handle_t * );
     115
     116/***********************************************************************
     117 * tr_natTraversalStatus
     118 ***********************************************************************
     119 * Return the status of NAT traversal
     120 **********************************************************************/
     121#define TR_NAT_TRAVERSAL_MAPPING        1
     122#define TR_NAT_TRAVERSAL_MAPPED         2
     123#define TR_NAT_TRAVERSAL_NOTFOUND       3
     124#define TR_NAT_TRAVERSAL_ERROR          4
     125#define TR_NAT_TRAVERSAL_UNMAPPING      5
     126#define TR_NAT_TRAVERSAL_DISABLED       6
     127#define TR_NAT_TRAVERSAL_IS_DISABLED( st ) \
     128  ( TR_NAT_TRAVERSAL_DISABLED == (st) || TR_NAT_TRAVERSAL_UNMAPPING == (st) )
     129int tr_natTraversalStatus( tr_handle_t * );
    105130
    106131/***********************************************************************
  • trunk/libtransmission/utils.c

    r837 r920  
    2525#include "transmission.h"
    2626
     27#define SPRINTF_BUFSIZE         100
     28
    2729static tr_lock_t      * messageLock = NULL;
    2830static int              messageLevel = 0;
     
    9799void tr_msg( int level, char * msg, ... )
    98100{
    99     va_list          args;
     101    va_list         args1, args2;
    100102    tr_msg_list_t * newmsg;
     103    int             len1, len2;
    101104
    102105    assert( NULL != messageLock );
     
    113116    if( messageLevel >= level )
    114117    {
    115         va_start( args, msg );
     118        va_start( args1, msg );
    116119        if( messageQueuing )
    117120        {
     
    121124                newmsg->level = level;
    122125                newmsg->when = time( NULL );
    123                 vasprintf( &newmsg->message, msg, args );
     126                len1 = len2 = 0;
     127                va_start( args2, msg );
     128                tr_vsprintf( &newmsg->message, &len1, &len2, msg,
     129                             args1, args2 );
     130                va_end( args2 );
    124131                if( NULL == newmsg->message )
    125132                {
     
    135142        else
    136143        {
    137             vfprintf( stderr, msg, args );
     144            vfprintf( stderr, msg, args1 );
    138145            fputc( '\n', stderr );
    139146        }
    140         va_end( args );
     147        va_end( args1 );
    141148    }
    142149
     
    235242    return 0;
    236243}
     244
     245#define UPPER( cc ) \
     246    ( 'a' <= (cc) && 'z' >= (cc) ? (cc) - ( 'a' - 'A' ) : (cc) )
     247
     248int tr_strncasecmp( const char * first, const char * second, int len )
     249{
     250    int ii;
     251    char firstchar, secondchar;
     252
     253    if( 0 > len )
     254    {
     255        len = strlen( first );
     256        ii = strlen( second );
     257        len = MIN( len, ii );
     258    }
     259
     260    for( ii = 0; ii < len; ii++ )
     261    {
     262        if( first[ii] != second[ii] )
     263        {
     264            firstchar = UPPER( first[ii] );
     265            secondchar = UPPER( second[ii] );
     266            if( firstchar > secondchar )
     267            {
     268                return 1;
     269            }
     270            else if( firstchar < secondchar )
     271            {
     272                return -1;
     273            }
     274        }
     275        if( '\0' == first[ii] )
     276        {
     277            /* if first[ii] is '\0' then second[ii] is too */
     278            return 0;
     279        }
     280    }
     281
     282    return 0;
     283}
     284
     285int tr_sprintf( char ** buf, int * used, int * max, const char * format, ... )
     286{
     287    va_list ap1, ap2;
     288    int     ret;
     289
     290    va_start( ap1, format );
     291    va_start( ap2, format );
     292    ret = tr_vsprintf( buf, used, max, format, ap1, ap2 );
     293    va_end( ap2 );
     294    va_end( ap1 );
     295
     296    return ret;
     297}
     298
     299int tr_vsprintf( char ** buf, int * used, int * max, const char * fmt,
     300                 va_list ap1, va_list ap2 )
     301{
     302    int     want;
     303    char  * newbuf;
     304
     305    want = vsnprintf( NULL, 0, fmt, ap1 );
     306
     307    while( *used + want + 1 > *max )
     308    {
     309        *max += SPRINTF_BUFSIZE;
     310        newbuf = realloc( *buf, *max );
     311        if( NULL == newbuf )
     312        {
     313            return 1;
     314        }
     315        *buf = newbuf;
     316    }
     317
     318    *used += vsnprintf( *buf + *used, *max - *used, fmt, ap2 );
     319
     320    return 0;
     321}
     322
     323char *
     324tr_dupstr( const char * base, int len )
     325{
     326    char * ret;
     327
     328    ret = malloc( len + 1 );
     329    if( NULL != ret )
     330    {
     331        memcpy( ret, base, len );
     332        ret[len] = '\0';
     333    }
     334
     335    return ret;
     336}
  • trunk/libtransmission/utils.h

    r815 r920  
    3131#define tr_inf( a... ) tr_msg( TR_MSG_INF, ## a )
    3232#define tr_dbg( a... ) tr_msg( TR_MSG_DBG, ## a )
    33 void tr_msg  ( int level, char * msg, ... );
     33void tr_msg  ( int level, char * msg, ... ) PRINTF( 2, 3 );
    3434
    3535int  tr_rand ( int );
     
    4444 **********************************************************************/
    4545int tr_mkdir( char * path );
     46
     47/***********************************************************************
     48 * tr_strcasecmp
     49 ***********************************************************************
     50 * A case-insensitive strncmp()
     51 **********************************************************************/
     52#define tr_strcasecmp( ff, ss ) ( tr_strncasecmp( (ff), (ss), -1 ) )
     53int tr_strncasecmp( const char * first, const char * second, int len );
     54
     55/***********************************************************************
     56 * tr_sprintf
     57 ***********************************************************************
     58 * Appends to the end of a buffer using printf formatting,
     59 * growing the buffer if needed
     60 **********************************************************************/
     61int tr_sprintf( char ** buf, int * used, int * max,
     62                const char * format, ... ) PRINTF( 4, 5 );
     63/* gee, it sure would be nice if BeOS had va_copy() */
     64int tr_vsprintf( char **, int *, int *, const char *, va_list, va_list );
     65
     66/***********************************************************************
     67 * tr_dupstr
     68 ***********************************************************************
     69 * Creates a nul-terminated string
     70 **********************************************************************/
     71char * tr_dupstr( const char * base, int len );
    4672
    4773/***********************************************************************
Note: See TracChangeset for help on using the changeset viewer.