Changeset 1540


Ignore:
Timestamp:
Mar 8, 2007, 4:06:58 AM (15 years ago)
Author:
joshe
Message:

Implement Azureus peer protocol, including PEX message.
Implement extended messages, including uTorrent PEX.

Location:
branches/pex
Files:
6 added
19 edited

Legend:

Unmodified
Added
Removed
  • branches/pex/libtransmission/bencode.c

    r1524 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    2727#define LIST_SIZE   20
    2828
     29static int makeroom( benc_val_t * val, int count )
     30{
     31    int len;
     32    void * new;
     33
     34    assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
     35
     36    len = val->val.l.alloc;
     37    while( val->val.l.count + count >= len )
     38    {
     39        len += LIST_SIZE;
     40    }
     41
     42    if( len > val->val.l.alloc )
     43    {
     44        /* We need a bigger boat */
     45        new = realloc( val->val.l.vals, len * sizeof( benc_val_t ) );
     46        if( NULL == new )
     47        {
     48            return 1;
     49        }
     50        val->val.l.alloc = len;
     51        val->val.l.vals = new;
     52    }
     53
     54    return 0;
     55}
     56
    2957int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
    3058{
    3159    char * p, * e, * foo;
    3260
    33     if( 1 >= len )
     61    if( NULL == buf || 1 >= len )
    3462    {
    3563        return 1;
     
    84112        while( cur - buf < len && cur[0] != 'e' )
    85113        {
    86             if( val->val.l.count == val->val.l.alloc )
    87             {
    88                 /* We need a bigger boat */
    89                 val->val.l.alloc += LIST_SIZE;
    90                 val->val.l.vals   =  realloc( val->val.l.vals,
    91                         val->val.l.alloc  * sizeof( benc_val_t ) );
    92             }
    93             if( tr_bencLoad( cur, len - (cur - buf),
     114            if( makeroom( val, 1 ) ||
     115                tr_bencLoad( cur, len - (cur - buf),
    94116                             &val->val.l.vals[val->val.l.count], &p ) )
    95117            {
     
    198220
    199221        case TYPE_STR:
    200             if( val->val.s.s )
     222            if( !val->val.s.nofree )
    201223            {
    202224                free( val->val.s.s );
     
    249271        }
    250272    }
     273    va_end( ap );
     274
     275    return ret;
     276}
     277
     278char * tr_bencStealStr( benc_val_t * val )
     279{
     280    assert( TYPE_STR == val->type );
     281    val->val.s.nofree = 1;
     282    return val->val.s.s;
     283}
     284
     285void tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree )
     286{
     287    tr_bencInit( val, TYPE_STR );
     288    val->val.s.s      = str;
     289    val->val.s.nofree = nofree;
     290    if( 0 >= len )
     291    {
     292        len = ( NULL == str ? 0 : strlen( str ) );
     293    }
     294    val->val.s.i = len;
     295}
     296
     297int tr_bencInitStrDup( benc_val_t * val, const char * str )
     298{
     299    char * new = NULL;
     300
     301    if( NULL != str )
     302    {
     303        new = strdup( str );
     304        if( NULL == new )
     305        {
     306            return 1;
     307        }
     308    }
     309
     310    tr_bencInitStr( val, new, 0, 0 );
     311
     312    return 0;
     313}
     314
     315void tr_bencInitInt( benc_val_t * val, int64_t num )
     316{
     317    tr_bencInit( val, TYPE_INT );
     318    val->val.i = num;
     319}
     320
     321int tr_bencListAppend( benc_val_t * val, ... )
     322{
     323    va_list ap;
     324    int len;
     325    benc_val_t ** ptr;
     326
     327    assert( TYPE_LIST == val->type );
     328
     329    len = 0;
     330    va_start( ap, val );
     331    while( NULL != va_arg( ap, benc_val_t ** ) )
     332    {
     333        len++;
     334    }
     335    va_end( ap );
     336
     337    if( makeroom( val, len ) )
     338    {
     339        return 1;
     340    }
     341
     342    va_start( ap, val );
     343    while( NULL != ( ptr = va_arg( ap, benc_val_t ** ) ) )
     344    {
     345        *ptr = &val->val.l.vals[val->val.l.count];
     346        tr_bencInit( *ptr, TYPE_INT );
     347        val->val.l.count++;
     348    }
     349    va_end( ap );
     350
     351    return 0;
     352}
     353
     354int tr_bencListExtend( benc_val_t * val, int count )
     355{
     356    assert( TYPE_LIST == val->type );
     357
     358    if( makeroom( val, count ) )
     359    {
     360        return 1;
     361    }
     362
     363    return 0;
     364}
     365
     366static inline int _tr_bencDictAppend( benc_val_t * val, va_list ap,
     367                                      va_list ap2, int nofree )
     368{
     369    int len;
     370    char * key;
     371    benc_val_t ** ptr;
     372
     373    assert( TYPE_DICT == val->type );
     374
     375    len = 0;
     376    while( NULL != va_arg( ap, char * ) )
     377    {
     378        ptr = va_arg( ap, benc_val_t ** );
     379        assert( NULL != ptr );
     380        len += 2;
     381    }
     382
     383    if( makeroom( val, len ) )
     384    {
     385        return 1;
     386    }
     387
     388    while( NULL != ( key = va_arg( ap2, char * ) ) )
     389    {
     390        if( !nofree )
     391        {
     392            key = strdup( key );
     393            if( NULL == key )
     394            {
     395                return 1;
     396            }
     397        }
     398        ptr = va_arg( ap2, benc_val_t ** );
     399        tr_bencInitStr( &val->val.l.vals[val->val.l.count], key, 0, nofree );
     400        val->val.l.count++;
     401        *ptr = &val->val.l.vals[val->val.l.count];
     402        tr_bencInit( *ptr, TYPE_INT );
     403        val->val.l.count++;
     404    }
     405
     406    return 0;
     407}
     408
     409int tr_bencDictAppend( benc_val_t * val, ... )
     410{
     411    va_list ap, ap2;
     412    int     ret;
     413
     414    va_start( ap, val );
     415    va_start( ap2, val );
     416    ret = _tr_bencDictAppend( val, ap, ap2, 0 );
     417    va_end( ap2 );
     418    va_end( ap );
     419
     420    return ret;
     421}
     422
     423int tr_bencDictAppendNofree( benc_val_t * val, ... )
     424{
     425    va_list ap, ap2;
     426    int     ret;
     427
     428    va_start( ap, val );
     429    va_start( ap2, val );
     430    ret = _tr_bencDictAppend( val, ap, ap2, 1 );
     431    va_end( ap2 );
    251432    va_end( ap );
    252433
  • branches/pex/libtransmission/bencode.h

    r1524 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    4242            int    i;
    4343            char * s;
     44            int    nofree;
    4445        } s;
    4546        struct
     
    5960benc_val_t * tr_bencDictFind( benc_val_t * val, const char * key );
    6061benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... );
    61 char *       tr_bencSaveMalloc( benc_val_t * val, int * len );
    62 int          tr_bencSave( benc_val_t * val, char ** buf,
     62
     63/* marks a string as 'do not free' and returns it */
     64char *       tr_bencStealStr( benc_val_t * val );
     65
     66/* convenience functions for building benc_val_t structures */
     67
     68static inline void tr_bencInit( benc_val_t * val, int type )
     69{
     70    memset( val, 0, sizeof( *val ) );
     71    val->type = type;
     72}
     73
     74void   tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree );
     75int    tr_bencInitStrDup( benc_val_t * val, const char * str );
     76void   tr_bencInitInt( benc_val_t * val, int64_t num );
     77/* args are a NULL terminated list of benc_val_t** */
     78int    tr_bencListAppend( benc_val_t * val, ... );
     79/* args are a NULL terminated list of pairs of char * key, benc_val_t ** val */
     80int    tr_bencDictAppend( benc_val_t * val, ... );
     81/* like tr_bencDictAppend but char * key args are marked nofree */
     82int    tr_bencDictAppendNofree( benc_val_t * val, ... );
     83
     84/* insure val has room for at least count more items */
     85int tr_bencListExtend( benc_val_t * val, int count );
     86
     87char * tr_bencSaveMalloc( benc_val_t * val, int * len );
     88int    tr_bencSave( benc_val_t * val, char ** buf,
    6389                          int * used, int * max );
    6490
  • branches/pex/libtransmission/fastresume.h

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    381381                    return 1;
    382382                }
    383                 tr_torrentAddCompact( tor, buf, len / 6 );
     383                tr_torrentAddCompact( tor, TR_PEER_FROM_CACHE, buf, len / 6 );
    384384                free( buf );
    385385                continue;
  • branches/pex/libtransmission/http.c

    r1436 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2006 Transmission authors and contributors
     4 * Copyright (c) 2006-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    450450    if( tr_sprintf( EXPANDBUF( http->header ), " HTTP/1.1" CR LF
    451451                    "Host: %s" CR LF
    452                     "User-Agent: Transmission/%d.%d" CR LF
     452                    "User-Agent: %s/%d.%d" CR LF
    453453                    "Connection: close" CR LF,
    454                     http->host, VERSION_MAJOR, VERSION_MINOR ) )
     454                    http->host, TR_NAME, VERSION_MAJOR, VERSION_MINOR ) )
    455455    {
    456456        goto err;
  • branches/pex/libtransmission/internal.h

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    6565#  include <arpa/inet.h>
    6666#endif
     67
     68#define TR_NAME                 "Transmission"
    6769
    6870#ifndef INADDR_NONE
     
    145147#include "xml.h"
    146148
    147 void tr_torrentAddCompact( tr_torrent_t * tor, uint8_t * buf, int count );
     149void tr_torrentAddCompact( tr_torrent_t * tor, int from,
     150                           uint8_t * buf, int count );
    148151void tr_torrentAttachPeer( tr_torrent_t * tor, tr_peer_t * peer );
    149152
     
    166169    char            * id;
    167170    char            * key;
     171    uint8_t         * azId;
    168172    int               publicPort;
    169173
     
    223227    tr_handle_status_t stats[2];
    224228    int                statCur;
     229#define TR_AZ_ID_LEN            20
     230    uint8_t        azId[TR_AZ_ID_LEN];
    225231};
    226232
  • branches/pex/libtransmission/metainfo.c

    r1538 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    203203    }
    204204    inf->pieceCount = val->val.s.i / SHA_DIGEST_LENGTH;
    205     inf->pieces = (uint8_t *) val->val.s.s; /* Ugly, but avoids a memcpy */
    206     val->val.s.s = NULL;
     205    inf->pieces = (uint8_t *) tr_bencStealStr( val );
    207206
    208207    /* TODO add more tests so we don't crash on weird files */
  • branches/pex/libtransmission/net.h

    r1425 r1540  
    6060
    6161void tr_netNtop( const struct in_addr * addr, char * buf, int len );
     62
     63
     64#define tr_addrcmp( aa, bb )    memcmp( ( void * )(aa), ( void * )(bb), 4)
  • branches/pex/libtransmission/peer.c

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    2424
    2525#include "transmission.h"
     26#include "peertree.h"
    2627
    2728#define MAX_REQUEST_COUNT 32
    2829#define OUR_REQUEST_COUNT 8  /* TODO: we should detect if we are on a
    2930                                high-speed network and adapt */
     31#define PEX_INTERVAL            60
     32#define PEER_SUPPORTS_EXTENDED_MESSAGES( bits ) ( (bits)[5] & 0x10 )
     33#define PEER_SUPPORTS_AZUREUS_PROTOCOL( bits )  ( (bits)[0] & 0x80 )
     34
     35#define PEER_MSG_CHOKE          0
     36#define PEER_MSG_UNCHOKE        1
     37#define PEER_MSG_INTERESTED     2
     38#define PEER_MSG_UNINTERESTED   3
     39#define PEER_MSG_HAVE           4
     40#define PEER_MSG_BITFIELD       5
     41#define PEER_MSG_REQUEST        6
     42#define PEER_MSG_PIECE          7
     43#define PEER_MSG_CANCEL         8
     44#define PEER_MSG_PORT           9
     45#define PEER_MSG_EXTENDED       20
    3046
    3147typedef struct tr_request_s
     
    4662#define PEER_STATUS_IDLE        1 /* Need to connect */
    4763#define PEER_STATUS_CONNECTING  2 /* Trying to send handshake */
    48 #define PEER_STATUS_HANDSHAKE   4 /* Waiting for peer's handshake */
    49 #define PEER_STATUS_CONNECTED   8 /* Got peer's handshake */
     64#define PEER_STATUS_HANDSHAKE   3 /* Waiting for peer's handshake */
     65#define PEER_STATUS_AZ_GIVER    4 /* Sending Azureus handshake */
     66#define PEER_STATUS_AZ_RECEIVER 5 /* Receiving Azureus handshake */
     67#define PEER_STATUS_CONNECTED   6 /* Got peer's handshake */
    5068    int                 status;
    5169    int                 socket;
    52     char                incoming;
     70    char                from;
     71    char                private;
     72    char                azproto;  /* azureus peer protocol is being used */
    5373    uint64_t            date;
    5474    uint64_t            keepAlive;
     75
     76#define EXTENDED_NOT_SUPPORTED   0 /* extended messages not supported */
     77#define EXTENDED_SUPPORTED       1 /* waiting to send extended handshake */
     78#define EXTENDED_HANDSHAKE       2 /* sent extended handshake */
     79    uint8_t             extStatus;
     80    uint8_t             pexStatus;   /* peer's ut_pex id, 0 if not supported */
     81    uint64_t            lastPex;     /* time when last pex packet was sent */
     82    int                 advertisedPort; /* listening port we last told peer */
     83    tr_peertree_t       sentPeers;
    5584
    5685    char                amChoking;
     
    122151}
    123152
     153#include "peerext.h"
     154#include "peeraz.h"
    124155#include "peermessages.h"
    125156#include "peerutils.h"
     
    131162 * Initializes a new peer.
    132163 **********************************************************************/
    133 tr_peer_t * tr_peerInit( struct in_addr addr, in_port_t port, int s )
     164tr_peer_t * tr_peerInit( struct in_addr addr, in_port_t port, int s, int from )
    134165{
    135166    tr_peer_t * peer = peerInit();
     167
     168    assert( 0 <= from && TR_PEER_FROM__MAX > from );
    136169
    137170    peer->socket = s;
    138171    peer->addr = addr;
    139172    peer->port = port;
     173    peer->from = from;
    140174    if( s >= 0 )
    141175    {
     176        assert( TR_PEER_FROM_INCOMING == from );
    142177        peer->status = PEER_STATUS_CONNECTING;
    143         peer->incoming = 1;
    144178    }
    145179    else
     
    157191    int i, block;
    158192
     193    peertreeFree( &peer->sentPeers );
    159194    for( i = 0; i < peer->inRequestCount; i++ )
    160195    {
     
    181216    tr_rcClose( peer->upload );
    182217    free( peer );
     218}
     219
     220void tr_peerSetPrivate( tr_peer_t * peer, int private )
     221{
     222    peer->private = private;
    183223}
    184224
     
    320360
    321361    /* Connect */
    322     if( peer->status & PEER_STATUS_IDLE )
     362    if( PEER_STATUS_IDLE == peer->status )
    323363    {
    324364        peer->socket = tr_netOpenTCP( peer->addr, peer->port, 0 );
     
    331371
    332372    /* Try to send handshake */
    333     if( peer->status & PEER_STATUS_CONNECTING )
     373    if( PEER_STATUS_CONNECTING == peer->status )
    334374    {
    335375        uint8_t buf[68];
     
    339379        memcpy( &buf[1], "BitTorrent protocol", 19 );
    340380        memset( &buf[20], 0, 8 );
     381        buf[20] = 0x80;         /* azureus protocol */
     382        buf[25] = 0x10;         /* extended messages */
    341383        memcpy( &buf[28], inf->hash, 20 );
    342384        memcpy( &buf[48], tor->id, 20 );
     
    366408        return ret;
    367409    }
     410
     411    /* Try to send Azureus handshake */
     412    if( PEER_STATUS_AZ_GIVER == peer->status )
     413    {
     414        switch( sendAZHandshake( tor, peer ) )
     415        {
     416            case TR_NET_BLOCK:
     417                break;
     418            case TR_NET_CLOSE:
     419                peer_dbg( "connection closed" );
     420                return TR_ERROR;
     421            default:
     422                peer->status = PEER_STATUS_AZ_RECEIVER;
     423                break;
     424        }
     425    }
     426
    368427    if( peer->status < PEER_STATUS_CONNECTED )
    369428    {
     
    469528int tr_peerIsConnected( tr_peer_t * peer )
    470529{
    471     return peer->status & PEER_STATUS_CONNECTED;
     530    return PEER_STATUS_CONNECTED == peer->status;
    472531}
    473532
     
    477536 *
    478537 **********************************************************************/
    479 int tr_peerIsIncoming( tr_peer_t * peer )
    480 {
    481     return peer->incoming;
     538int tr_peerIsFrom( tr_peer_t * peer )
     539{
     540    return peer->from;
    482541}
    483542
  • branches/pex/libtransmission/peer.h

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    3030typedef struct tr_peer_s tr_peer_t;
    3131
    32 tr_peer_t * tr_peerInit          ( struct in_addr, in_port_t, int socket );
     32tr_peer_t * tr_peerInit          ( struct in_addr, in_port_t, int sock, int );
    3333void        tr_peerDestroy       ( tr_peer_t * );
     34void        tr_peerSetPrivate    ( tr_peer_t *, int );
    3435void        tr_peerSetTorrent    ( tr_peer_t *, tr_torrent_t * );
    3536int         tr_peerRead          ( tr_peer_t * );
     
    3940int         tr_peerPulse         ( tr_peer_t * );
    4041int         tr_peerIsConnected   ( tr_peer_t * );
    41 int         tr_peerIsIncoming    ( tr_peer_t * );
     42int         tr_peerIsFrom        ( tr_peer_t * );
    4243int         tr_peerAmChoking     ( tr_peer_t * );
    4344int         tr_peerAmInterested  ( tr_peer_t * );
  • branches/pex/libtransmission/peermessages.h

    r1447 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    139139{
    140140    uint8_t * p;
     141    int       index = 0;
    141142
    142143    size += 4;
    143     if( 0 <= id )
     144    if( peer->azproto )
     145    {
     146        index = azmsgIdIndex( id );
     147        assert( 0 <= index );
     148        size += 4 + azmsgLen( index ) + 1;
     149    }
     150    else if( 0 <= id )
    144151    {
    145152        size++;
     
    158165    TR_HTONL( size - 4, p );
    159166    p += 4;
    160     if( 0 <= id )
     167    if( peer->azproto )
     168    {
     169        TR_HTONL( azmsgLen( index ), p );
     170        memcpy( p + 4, azmsgStr( index ), azmsgLen( index ) );
     171        p[ 4 + azmsgLen( index ) ] = AZ_EXT_VERSION;
     172        p += 4 + azmsgLen( index ) + 1;
     173    }
     174    else if( 0 <= id )
    161175    {
    162176        *p = id;
     
    176190    uint8_t * p;
    177191
    178     p = getMessagePointer( peer, 0, -1 );
     192    p = getMessagePointer( peer, 0, AZ_MSG_BT_KEEP_ALIVE );
    179193
    180194    peer_dbg( "SEND keep-alive" );
     
    336350    }
    337351}
     352
     353/***********************************************************************
     354 * sendExtended
     355 ***********************************************************************
     356 * Builds an extended message:
     357 *  - size = 6 + X (4 bytes)
     358 *  - id   = 20    (1 byte)
     359 *  - eid  = Y     (1 byte)
     360 *  - data         (X bytes)
     361 **********************************************************************/
     362static int sendExtended( tr_torrent_t * tor, tr_peer_t * peer, int id )
     363{
     364    uint8_t * p;
     365    char    * buf;
     366    int       len;
     367
     368    buf = NULL;
     369    switch( id )
     370    {
     371        case EXTENDED_HANDSHAKE_ID:
     372            buf = makeExtendedHandshake( tor, peer, &len );
     373            break;
     374        case EXTENDED_PEX_ID:
     375            buf = makeUTPex( tor, peer, &len );
     376            break;
     377        default:
     378            assert( 0 );
     379            break;
     380    }
     381    if( NULL == buf )
     382    {
     383        return 1;
     384    }
     385
     386    /* add header and queue it to be sent */
     387    p = getMessagePointer( peer, 1 + len, PEER_MSG_EXTENDED );
     388    p[0] = id;
     389    memcpy( p + 1, buf, len );
     390    free( buf );
     391
     392    return 0;
     393}
     394
     395/***********************************************************************
     396 * sendAZPex
     397 ***********************************************************************
     398 *
     399 **********************************************************************/
     400static int sendAZPex( tr_torrent_t * tor, tr_peer_t * peer )
     401{
     402    uint8_t * p;
     403    char    * buf;
     404    int       len;
     405
     406    buf = makeAZPex( tor, peer, &len );
     407    if( NULL == buf )
     408    {
     409        return 1;
     410    }
     411
     412    /* add header and queue it to be sent */
     413    p = getMessagePointer( peer, len, AZ_MSG_AZ_PEER_EXCHANGE );
     414    memcpy( p, buf, len );
     415    free( buf );
     416
     417    return 0;
     418}
  • branches/pex/libtransmission/peerparse.h

    r1535 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    441441}
    442442
     443static inline int
     444parseMessageHeader( tr_peer_t * peer, uint8_t * buf, int buflen,
     445                    int * msgid, int * msglen )
     446{
     447    if( 4 > buflen )
     448    {
     449        return TR_NET_BLOCK;
     450    }
     451
     452    /* Get payload size */
     453    TR_NTOHL( buf, *msglen );
     454
     455    if( 4 + *msglen > buflen )
     456    {
     457        /* We do not have the entire message */
     458        return TR_NET_BLOCK;
     459    }
     460
     461    if( 0 == *msglen )
     462    {
     463        /* keep-alive */
     464        peer_dbg( "GET  keep-alive" );
     465        *msgid = AZ_MSG_BT_KEEP_ALIVE;
     466        return 4;
     467    }
     468    else
     469    {
     470        /* Type of the message */
     471        *msgid = buf[4];
     472        (*msglen)--;
     473        return 5;
     474    }
     475}
     476
    443477static inline int parseMessage( tr_torrent_t * tor, tr_peer_t * peer,
    444                                 uint8_t * p, int len )
    445 {
    446     char id;
    447 
    448     /* Type of the message */
    449     id = *(p++);
    450     len--;
     478                                int id, uint8_t * p, int len )
     479{
     480    int extid;
    451481
    452482    switch( id )
     
    472502        case PEER_MSG_PORT:
    473503            return parsePort( peer, p, len );
     504        case PEER_MSG_EXTENDED:
     505            if( EXTENDED_NOT_SUPPORTED == peer->extStatus )
     506            {
     507                break;
     508            }
     509            if( 0 < len )
     510            {
     511                extid = p[0];
     512                p++;
     513                len--;
     514                if( EXTENDED_HANDSHAKE_ID == extid )
     515                {
     516                    return parseExtendedHandshake( peer, p, len );
     517                }
     518                else if( 0 < peer->pexStatus && extid == peer->pexStatus )
     519                {
     520                    return parseUTPex( tor, peer, p, len );
     521                }
     522                peer_dbg( "Unknown extended message '%hhu'", extid );
     523            }
     524            return 1;
     525        case AZ_MSG_AZ_PEER_EXCHANGE:
     526            if( peer->azproto && peer->pexStatus )
     527            {
     528                return parseAZPex( tor, peer, p, len );
     529            }
     530            break;
     531        case AZ_MSG_INVALID:
     532            return 0;
    474533    }
    475534
     
    527586    int       len;
    528587    uint8_t * p   = peer->buf;
    529     uint8_t * end = &p[peer->pos];
    530588    int       ret;
     589    int       msgid;
    531590
    532591    if( peer->banned )
     
    539598    while( peer->pos >= 4 )
    540599    {
    541         if( peer->status & PEER_STATUS_HANDSHAKE )
     600        if( PEER_STATUS_HANDSHAKE == peer->status )
    542601        {
    543602            char * client;
     
    566625            }
    567626
    568             peer->status  = PEER_STATUS_CONNECTED;
     627            peer->status = PEER_STATUS_CONNECTED;
     628            if( PEER_SUPPORTS_EXTENDED_MESSAGES( &p[20] ) )
     629            {
     630                peer_dbg( "extended messages supported" );
     631                peer->extStatus = EXTENDED_SUPPORTED;
     632            }
     633            else if( PEER_SUPPORTS_AZUREUS_PROTOCOL( &p[20] ) )
     634            {
     635                peer->azproto = 1;
     636                peer->status  = PEER_STATUS_AZ_GIVER;
     637                peer->date    = tr_date();
     638            }
    569639            memcpy( peer->id, &p[48], 20 );
    570640            p            += 68;
     
    588658            free( client );
    589659
    590             sendBitfield( tor, peer );
     660          justconnected:
     661            if( PEER_STATUS_CONNECTED == peer->status )
     662            {
     663                if( EXTENDED_SUPPORTED == peer->extStatus )
     664                {
     665                    if( sendExtended( tor, peer, EXTENDED_HANDSHAKE_ID ) )
     666                    {
     667                        return TR_ERROR;
     668                    }
     669                    peer->extStatus = EXTENDED_HANDSHAKE;
     670                }
     671                sendBitfield( tor, peer );
     672            }
    591673
    592674            continue;
    593675        }
    594        
    595         /* Get payload size */
    596         TR_NTOHL( p, len );
    597         p += 4;
    598 
    599         if( len > 9 + tor->blockSize )
     676        else if( peer->status < PEER_STATUS_CONNECTED )
     677        {
     678            ret = parseAZMessageHeader( peer, p, peer->pos, &msgid, &len );
     679            if( TR_NET_BLOCK & ret )
     680            {
     681                break;
     682            }
     683            else if( TR_NET_CLOSE & ret )
     684            {
     685                return TR_ERROR;
     686            }
     687            else
     688            {
     689                p         += ret;
     690                peer->pos -= ret;
     691                assert( len <= peer->pos );
     692                if( AZ_MSG_AZ_HANDSHAKE != msgid ||
     693                    parseAZHandshake( peer, p, len ) )
     694                {
     695                    return TR_ERROR;
     696                }
     697                p           += len;
     698                peer->pos   -= len;
     699                assert( 0 <= peer->pos );
     700                peer->status = PEER_STATUS_CONNECTED;
     701                goto justconnected;
     702            }
     703        }
     704
     705        if( peer->azproto )
     706        {
     707            ret = parseAZMessageHeader( peer, p, peer->pos, &msgid, &len );
     708        }
     709        else
     710        {
     711            ret = parseMessageHeader( peer, p, peer->pos, &msgid, &len );
     712        }
     713        if( TR_NET_BLOCK & ret )
     714        {
     715            break;
     716        }
     717        else if( TR_NET_CLOSE & ret )
     718        {
     719            return TR_ERROR;
     720        }
     721
     722        if( len > 8 + tor->blockSize )
    600723        {
    601724            /* This should never happen. Drop that peer */
     725            /* XXX could an extended message be longer than this? */
    602726            peer_dbg( "message too large (%d bytes)", len );
    603727            return TR_ERROR;
    604728        }
    605729
     730        p         += ret;
     731        peer->pos -= ret;
     732        assert( 0 <= peer->pos );
     733
     734        /* don't try to parse zero-length messages */
    606735        if( !len )
    607736        {
    608             /* keep-alive */
    609             peer_dbg( "GET  keep-alive" );
    610             peer->pos -= 4;
    611737            continue;
    612738        }
    613739
    614         if( &p[len] > end )
    615         {
    616             /* We do not have the entire message */
    617             p -= 4;
    618             break;
    619         }
    620 
    621         /* Remaining data after this message */
    622         peer->pos -= 4 + len;
    623 
    624         if( ( ret = parseMessage( tor, peer, p, len ) ) )
     740        if( ( ret = parseMessage( tor, peer, msgid, p, len ) ) )
    625741        {
    626742            return ret;
    627743        }
    628744
    629         p += len;
     745        p         += len;
     746        peer->pos -= len;
     747        assert( 0 <= peer->pos );
    630748    }
    631749
  • branches/pex/libtransmission/peerutils.h

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    3535
    3636    peer              = calloc( sizeof( tr_peer_t ), 1 );
     37    peertreeInit( &peer->sentPeers );
    3738    peer->amChoking   = 1;
    3839    peer->peerChoking = 1;
     
    4849{
    4950    /* Wait until we got the peers' ids */
    50     if( peer1->status < PEER_STATUS_CONNECTED ||
    51         peer2->status < PEER_STATUS_CONNECTED )
     51    if( peer1->status <= PEER_STATUS_HANDSHAKE ||
     52        peer2->status <= PEER_STATUS_HANDSHAKE )
    5253    {
    5354        return 1;
     
    5960static int checkPeer( tr_peer_t * peer )
    6061{
     62    tr_torrent_t * tor = peer->tor;
     63    uint64_t       now;
     64
     65    now = tr_date();
     66
    6167    if( peer->status < PEER_STATUS_CONNECTED &&
    62         tr_date() > peer->date + 8000 )
     68        now > peer->date + 8000 )
    6369    {
    6470        /* If it has been too long, don't wait for the socket
     
    7076    /* Drop peers who haven't even sent a keep-alive within the
    7177       last 3 minutes */
    72     if( tr_date() > peer->date + 180000 )
     78    if( now > peer->date + 180000 )
    7379    {
    7480        peer_dbg( "read timeout" );
     
    7884    /* Drop peers which are supposed to upload but actually
    7985       haven't sent anything within the last minute */
    80     if( peer->inRequestCount && tr_date() > peer->date + 60000 )
     86    if( peer->inRequestCount && now > peer->date + 60000 )
    8187    {
    8288        peer_dbg( "bad uploader" );
     
    8490    }
    8591
    86     if( peer->status & PEER_STATUS_CONNECTED )
     92    if( PEER_STATUS_CONNECTED == peer->status )
    8793    {
    8894        /* Send keep-alive every 2 minutes */
    89         if( tr_date() > peer->keepAlive + 120000 )
     95        if( now > peer->keepAlive + 120000 )
    9096        {
    9197            sendKeepAlive( peer );
    92             peer->keepAlive = tr_date();
     98            peer->keepAlive = now;
     99        }
     100
     101        /* Resend extended handshake if our public port changed */
     102        if( EXTENDED_HANDSHAKE == peer->extStatus &&
     103            tor->publicPort != peer->advertisedPort )
     104        {
     105            sendExtended( tor, peer, EXTENDED_HANDSHAKE_ID );
     106        }
     107
     108        /* Send peer list */
     109        if( !peer->private && 0 < peer->pexStatus )
     110        {
     111            if( 0 == peer->lastPex )
     112            {
     113                /* randomize time when first pex message is sent */
     114                peer->lastPex = now - 1000 * tr_rand( PEX_INTERVAL );
     115            }
     116            if( now > peer->lastPex + 1000 * PEX_INTERVAL )
     117            {
     118                if( ( EXTENDED_HANDSHAKE == peer->extStatus &&
     119                      !sendExtended( tor, peer, EXTENDED_PEX_ID ) ) ||
     120                    ( peer->azproto && !sendAZPex( tor, peer ) ) )
     121                {
     122                    peer->lastPex = now + 1000 * tr_rand( PEX_INTERVAL / 10 );
     123                }
     124            }
    93125        }
    94126    }
  • branches/pex/libtransmission/shared.c

    r1462 r1540  
    341341            break;
    342342        }
    343         s->peers[s->peerCount++] = tr_peerInit( addr, 0, socket );
     343        s->peers[s->peerCount++] = tr_peerInit( addr, 0, socket,
     344                                                TR_PEER_FROM_INCOMING );
    344345    }
    345346}
  • branches/pex/libtransmission/torrent.c

    r1537 r1540  
    123123    tor->id       = h->id;
    124124    tor->key      = h->key;
     125    tor->azId     = h->azId;
    125126    tor->finished = 0;
    126127
     
    286287    if( peerCount > 0 )
    287288    {
    288         tr_torrentAddCompact( tor, peerCompact, peerCount );
     289        tr_torrentAddCompact( tor, TR_PEER_FROM_TRACKER,
     290                              peerCompact, peerCount );
    289291        free( peerCompact );
    290292    }
     
    323325
    324326    s->peersTotal       = 0;
    325     s->peersIncoming    = 0;
     327    bzero( s->peersFrom, sizeof( s->peersFrom ) );
    326328    s->peersUploading   = 0;
    327329    s->peersDownloading = 0;
     
    334336        {
    335337            (s->peersTotal)++;
    336            
    337             if( tr_peerIsIncoming( peer ) )
    338             {
    339                 (s->peersIncoming)++;
    340             }
     338            (s->peersFrom[ tr_peerIsFrom( peer ) ])++;
    341339            if( tr_peerAmInterested( peer ) && !tr_peerIsChoking( peer ) )
    342340            {
     
    426424           
    427425            peers[i].isConnected   = tr_peerIsConnected( peer );
    428             peers[i].isIncoming    = tr_peerIsIncoming( peer );
     426            peers[i].from          = tr_peerIsFrom( peer );
    429427            peers[i].progress      = tr_peerProgress( peer );
    430428            peers[i].port          = tr_peerPort( peer );
     
    632630    }
    633631
     632    tr_peerSetPrivate( peer, tor->info.flags & TR_FLAG_PRIVATE );
    634633    tr_peerSetTorrent( peer, tor );
    635634    tor->peers[tor->peerCount++] = peer;
    636635}
    637636
    638 void tr_torrentAddCompact( tr_torrent_t * tor, uint8_t * buf, int count )
     637void tr_torrentAddCompact( tr_torrent_t * tor, int from,
     638                           uint8_t * buf, int count )
    639639{
    640640    struct in_addr addr;
     
    648648        memcpy( &port, buf, 2 ); buf += 2;
    649649
    650         peer = tr_peerInit( addr, port, -1 );
     650        peer = tr_peerInit( addr, port, -1, from );
    651651        tr_torrentAttachPeer( tor, peer );
    652652    }
     
    692692        if( peerCount > 0 )
    693693        {
    694             tr_torrentAddCompact( tor, peerCompact, peerCount );
     694            tr_torrentAddCompact( tor, TR_PEER_FROM_TRACKER,
     695                                  peerCompact, peerCount );
    695696            free( peerCompact );
    696697        }
  • branches/pex/libtransmission/transmission.c

    r1463 r1540  
    5656        r         = tr_rand( 36 );
    5757        h->key[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
     58    }
     59
     60    /* Azureus identity */
     61    for( i = 0; i < TR_AZ_ID_LEN; i++ )
     62    {
     63        h->azId[i] = tr_rand( 0xff );
    5864    }
    5965
  • branches/pex/libtransmission/transmission.h

    r1517 r1540  
    5252#define TR_DEFAULT_PORT   9090
    5353
     54#define TR_PEER_FROM_INCOMING   0 /* connections made to the listening port */
     55#define TR_PEER_FROM_TRACKER    1 /* peers received from a tracker */
     56#define TR_PEER_FROM_CACHE      2 /* peers read from the peer cache */
     57#define TR_PEER_FROM_PEX        3 /* peers discovered via PEX */
     58#define TR_PEER_FROM__MAX       4
     59
    5460/***********************************************************************
    5561 * Error codes
     
    399405    int                 eta;
    400406    int                 peersTotal;
    401     int                 peersIncoming;
     407    int                 peersFrom[TR_PEER_FROM__MAX];
    402408    int                 peersUploading;
    403409    int                 peersDownloading;
     
    421427   
    422428    int     isConnected;
    423     int     isIncoming;
     429    int     from;
    424430    float   progress;
    425431    int     port;
  • branches/pex/libtransmission/upnp.c

    r1463 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2006 Transmission authors and contributors
     4 * Copyright (c) 2006-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    847847                               "PortMappingProtocol", "TCP",
    848848                               "InternalClient", dev->myaddr,
    849                                "PortMappingDescription",
    850                                    "Added by Transmission",
     849                               "PortMappingDescription", "Added by " TR_NAME,
    851850                               NULL );
    852851            break;
  • branches/pex/libtransmission/utils.c

    r1444 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
  • branches/pex/libtransmission/utils.h

    r1534 r1540  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
Note: See TracChangeset for help on using the changeset viewer.