Changeset 3897


Ignore:
Timestamp:
Nov 20, 2007, 2:28:11 AM (15 years ago)
Author:
charles
Message:

partial backport of libT to 0.9x. 0.9x will probably be broken for a little bit.

Location:
branches/0.9x
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • branches/0.9x

    • Property svn:externals
      •  

        old new  
        1 third-party/libevent  -r474 http://levent.svn.sourceforge.net/svnroot/levent/trunk/libevent
         1third-party/libevent http://levent.svn.sourceforge.net/svnroot/levent/branches/patches-1.4
  • branches/0.9x/libtransmission/Makefile.am

    r3651 r3897  
    2828    ratecontrol.c \
    2929    shared.c \
    30     strlcat.c \
    31     strlcpy.c \
    3230    torrent.c \
    3331    tracker.c \
  • branches/0.9x/libtransmission/bencode.c

    r3683 r3897  
    2929#include <stdlib.h>
    3030
     31#include <event.h>
     32
    3133#include "transmission.h"
    3234#include "bencode.h"
     
    391393}
    392394
    393 char * tr_bencSaveMalloc( benc_val_t * val, int * len )
    394 {
    395     char * buf   = NULL;
    396     int alloc = 0;
    397 
    398     *len = 0;
    399     if( tr_bencSave( val, &buf, len, &alloc ) )
    400     {
    401         if( NULL != buf )
    402         {
    403             free(buf);
    404         }
    405         *len = 0;
    406         return NULL;
    407     }
    408 
    409     return buf;
    410 }
    411 
    412 typedef struct
     395struct KeyIndex
    413396{
    414397    const char * key;
    415398    int index;
    416 }
    417 KeyIndex;
     399};
    418400
    419401static int compareKeyIndex( const void * va, const void * vb )
    420402{
    421     const KeyIndex * a = (const KeyIndex *) va;
    422     const KeyIndex * b = (const KeyIndex *) vb;
     403    const struct KeyIndex * a = va;
     404    const struct KeyIndex * b = vb;
    423405    return strcmp( a->key, b->key );
    424406}
    425407
    426 int tr_bencSave( benc_val_t * val, char ** buf, int * used, int * max )
    427 {
    428     int ii;   
     408static void
     409saveImpl( struct evbuffer * out, const benc_val_t * val )
     410{
     411    int ii;
    429412
    430413    switch( val->type )
    431414    {
    432415        case TYPE_INT:
    433             if( tr_sprintf( buf, used, max, "i%"PRId64"e", val->val.i ) )
    434                 return 1;
     416            evbuffer_add_printf( out, "i%"PRId64"e", val->val.i );
    435417            break;
    436418
    437419        case TYPE_STR:
    438             if( tr_sprintf( buf, used, max, "%i:", val->val.s.i ) ||
    439                 tr_concat( buf, used,  max, val->val.s.s, val->val.s.i ) )
    440                 return 1;
     420            evbuffer_add_printf( out, "%i:", val->val.s.i );
     421            evbuffer_add( out, val->val.s.s, val->val.s.i );
    441422            break;
    442423
    443424        case TYPE_LIST:
    444             if( tr_sprintf( buf, used, max, "l" ) )
    445                 return 1;
     425            evbuffer_add_printf( out, "l" );
    446426            for( ii = 0; val->val.l.count > ii; ii++ )
    447                 if( tr_bencSave( val->val.l.vals + ii, buf, used, max ) )
    448                     return 1;
    449             if( tr_sprintf( buf, used, max, "e" ) )
    450                 return 1;
     427                saveImpl( out, val->val.l.vals + ii );
     428            evbuffer_add_printf( out, "e" );
    451429            break;
    452430
     
    454432            /* Keys must be strings and appear in sorted order
    455433               (sorted as raw strings, not alphanumerics). */
    456             if( tr_sprintf( buf, used, max, "d" ) )
    457                 return 1;
     434            evbuffer_add_printf( out, "d" );
    458435            if( 1 ) {
    459436                int i;
    460                 KeyIndex * indices = tr_new( KeyIndex, val->val.l.count );
     437                struct KeyIndex * indices = tr_new( struct KeyIndex, val->val.l.count );
    461438                for( ii=i=0; i<val->val.l.count; i+=2 ) {
    462439                    indices[ii].key = val->val.l.vals[i].val.s.s;
     
    464441                    ii++;
    465442                }
    466                 qsort( indices, ii, sizeof(KeyIndex), compareKeyIndex );
     443                qsort( indices, ii, sizeof(struct KeyIndex), compareKeyIndex );
    467444                for( i=0; i<ii; ++i ) {
    468445                    const int index = indices[i].index;
    469                     if( tr_bencSave( val->val.l.vals + index,     buf, used, max ) ||
    470                         tr_bencSave( val->val.l.vals + index + 1, buf, used, max ) ) {
    471                         tr_free( indices );
    472                         return 1;
    473                     }
     446                    saveImpl( out, val->val.l.vals + index );
     447                    saveImpl( out, val->val.l.vals + index + 1 );
    474448                }
    475449                tr_free( indices );
    476             }
    477             if( tr_sprintf( buf, used, max, "e" ) )
    478                 return 1;
    479             break;
    480     }
    481 
    482     return 0;
     450            }
     451            evbuffer_add_printf( out, "e" );
     452            break;
     453    }
     454}
     455
     456char*
     457tr_bencSave( const benc_val_t * val, int * len )
     458{
     459    struct evbuffer * buf = evbuffer_new( );
     460    char * ret;
     461    saveImpl( buf, val );
     462    if( len != NULL )
     463        *len = EVBUFFER_LENGTH( buf );
     464    ret = tr_strndup( (char*) EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
     465    evbuffer_free( buf );
     466    return ret;
    483467}
    484468
  • branches/0.9x/libtransmission/bencode.h

    r3105 r3897  
    8787benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key );
    8888
    89 char * tr_bencSaveMalloc( benc_val_t * val, int * len );
    90 int    tr_bencSave( benc_val_t * val, char ** buf,
    91                           int * used, int * max );
     89char*  tr_bencSave( const benc_val_t * val, int * len );
    9290
    9391int    tr_bencIsStr   ( const benc_val_t * val );
  • branches/0.9x/libtransmission/completion.c

    r3662 r3897  
    4949};
    5050
     51static void
     52tr_cpReset( tr_completion * cp )
     53{
     54    tr_torrent * tor = cp->tor;
     55
     56    tr_bitfieldClear( cp->pieceBitfield );
     57    tr_bitfieldClear( cp->blockBitfield );
     58    memset( cp->completeBlocks, 0, sizeof(uint16_t) * tor->info.pieceCount );
     59
     60    cp->doneDirty = TRUE;
     61    cp->doneHave = 0;
     62    cp->doneTotal = 0;
     63    cp->completeHave = 0;
     64}
     65
    5166tr_completion * tr_cpInit( tr_torrent * tor )
    5267{
     
    7085    tr_bitfieldFree( cp->blockBitfield );
    7186    tr_free(         cp );
    72 }
    73 
    74 void tr_cpReset( tr_completion * cp )
    75 {
    76     tr_torrent * tor = cp->tor;
    77 
    78     tr_bitfieldClear( cp->pieceBitfield );
    79     tr_bitfieldClear( cp->blockBitfield );
    80     memset( cp->completeBlocks, 0, sizeof(uint16_t) * tor->info.pieceCount );
    81 
    82     cp->doneDirty = TRUE;
    83     cp->doneHave = 0;
    84     cp->doneTotal = 0;
    85     cp->completeHave = 0;
    8687}
    8788
     
    311312        b -= (info->pieceSize - (info->totalSize % info->pieceSize));
    312313
    313    return b;
     314    return b;
    314315}
    315316
     
    317318tr_cpHaveTotal( const tr_completion * cp )
    318319{
    319    return cp->completeHave;
    320 }
     320    return cp->completeHave;
     321}
  • branches/0.9x/libtransmission/completion.h

    r3178 r3897  
    3232tr_completion  * tr_cpInit( tr_torrent * );
    3333void             tr_cpClose( tr_completion * );
    34 void             tr_cpReset( tr_completion * );
    3534
    3635/* General */
  • branches/0.9x/libtransmission/fdlimit.c

    r3811 r3897  
    3636#include <fcntl.h> /* O_LARGEFILE */
    3737
    38 #include <sys/queue.h> /* libevent needs this */
    39 #include <sys/types.h> /* libevent needs this */
    4038#include <event.h>
    41 #include <evhttp.h>
    4239#include <evutil.h>
    4340
     
    9087enum
    9188{
    92     TR_MAX_SOCKETS = 512,
    93 
    94     TR_MAX_OPEN_FILES = 16, /* real files, not sockets */
    95 
    96     TR_RESERVED_FDS   = 16 /* sockets reserved for tracker connections */
     89    TR_MAX_SOCKETS = 320,
     90
     91    TR_MAX_OPEN_FILES = 8, /* real files, not sockets */
     92
     93    TR_RESERVED_FDS = 16 /* sockets reserved for tracker connections */
    9794};
    9895
     
    135132    if( write ) {
    136133        char * tmp = tr_strdup( filename );
    137         const int val = tr_mkdirp( dirname(tmp), 0700 );
     134        const int val = tr_mkdirp( dirname(tmp), 0777 );
    138135        tr_free( tmp );
    139136        if( val )
     
    150147#endif
    151148    errno = 0;
    152     file->fd = open( filename, flags, 0600 );
     149    file->fd = open( filename, flags, 0666 );
    153150    if( file->fd < 0 ) {
    154151        if( errno ) {
  • branches/0.9x/libtransmission/handshake.c

    r3681 r3897  
    1919#include <libgen.h> /* basename */
    2020
    21 #include <sys/types.h> /* event.h needs this */
    2221#include <event.h>
    2322
     
    9190    unsigned int havePeerID                   : 1;
    9291    unsigned int haveSentBitTorrentHandshake  : 1;
    93     unsigned int allowUnencryptedPeers        : 1;
    9492    tr_peerIo * io;
    9593    tr_crypto * crypto;
     
    9896    uint8_t mySecret[KEY_LEN];
    9997    uint8_t state;
     98    tr_encryption_mode encryptionMode;
    10099    uint16_t pad_c_len;
    101100    uint16_t pad_d_len;
     
    326325
    327326static uint32_t
    328 getCryptoProvide( const tr_handshake * handshake UNUSED )
    329 {
    330     uint32_t i = 0;
    331 
    332     i |= CRYPTO_PROVIDE_CRYPTO; /* always allow crypto */
    333 
    334 #if 0
    335     /* by the time we send a crypto_provide, we _know_
    336      * the peer supports encryption. */
    337     if( handshake->allowUnencryptedPeers )
    338         i |= CRYPTO_PROVIDE_PLAINTEXT;
    339 #endif
    340 
    341    return i;
     327getCryptoProvide( const tr_handshake * handshake )
     328{
     329    uint32_t provide = 0;
     330
     331    switch( handshake->encryptionMode )
     332    {
     333        case TR_ENCRYPTION_REQUIRED:
     334        case TR_ENCRYPTION_PREFERRED:
     335            provide |= CRYPTO_PROVIDE_CRYPTO;
     336            break;
     337
     338        case TR_PLAINTEXT_PREFERRED:
     339            provide |= CRYPTO_PROVIDE_CRYPTO | CRYPTO_PROVIDE_PLAINTEXT;
     340            break;
     341    }
     342
     343    return provide;
     344}
     345
     346static uint32_t
     347getCryptoSelect( const tr_handshake * handshake, uint32_t crypto_provide )
     348{
     349    uint32_t choices[4];
     350    int i, nChoices=0;
     351
     352    switch( handshake->encryptionMode )
     353    {
     354        case TR_ENCRYPTION_REQUIRED:
     355            choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO;
     356            break;
     357
     358        case TR_ENCRYPTION_PREFERRED:
     359            choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO;
     360            choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT;
     361            break;
     362
     363        case TR_PLAINTEXT_PREFERRED:
     364            choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT;
     365            choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO;
     366            break;
     367    }
     368
     369    for( i=0; i<nChoices; ++i )
     370        if( crypto_provide & choices[i] )
     371            return choices[i];
     372
     373    return 0;
    342374}
    343375
     
    546578        tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_NONE );
    547579
    548         if( !handshake->allowUnencryptedPeers )
     580        if( handshake->encryptionMode == TR_ENCRYPTION_REQUIRED )
    549581        {
    550582            dbgmsg( handshake, "peer is unencrypted, and we're disallowing that" );
     
    842874    }
    843875
    844 dbgmsg( handshake, "sending crypto_select" );
    845876    /* send crypto_select */
    846     {
    847 dbgmsg( handshake, "handshake->crypto_provide is %d", (int)handshake->crypto_provide );
    848         if( handshake->crypto_provide & CRYPTO_PROVIDE_CRYPTO )
    849             crypto_select = CRYPTO_PROVIDE_CRYPTO;
    850         else if( handshake->allowUnencryptedPeers )
    851             crypto_select = CRYPTO_PROVIDE_PLAINTEXT;
    852         else {
    853 dbgmsg( handshake, "gronk..." );
    854             evbuffer_free( outbuf );
    855             tr_handshakeDone( handshake, FALSE );
    856             return READ_DONE;
    857         }
    858 
    859 dbgmsg( handshake, "we select crypto_select as %d...", (int)crypto_select );
     877    crypto_select = getCryptoSelect( handshake, handshake->crypto_provide );
     878    if( crypto_select ) {
     879        dbgmsg( handshake, "selecting crypto mode '%d'", (int)crypto_select );
    860880        tr_peerIoWriteUint32( handshake->io, outbuf, crypto_select );
     881    } else {
     882        dbgmsg( handshake, "peer didn't offer an encryption mode we like." );
     883        evbuffer_free( outbuf );
     884        tr_handshakeDone( handshake, FALSE );
     885        return READ_DONE;
    861886    }
    862887
     
    944969{
    945970    dbgmsg( handshake, "handshakeDone: %s", isOK ? "connected" : "aborting" );
    946     tr_peerIoSetIOFuncs( handshake->io, NULL, NULL, NULL, NULL );
     971    tr_peerIoSetIOFuncs( handshake->io, NULL, NULL, NULL );
    947972
    948973    fireDoneFunc( handshake, isOK );
     
    966991     * try a plaintext handshake */
    967992    if(    ( ( handshake->state == AWAITING_YB ) || ( handshake->state == AWAITING_VC ) )
    968         && ( handshake->allowUnencryptedPeers )
     993        && ( handshake->encryptionMode != TR_ENCRYPTION_REQUIRED )
    969994        && ( !tr_peerIoReconnect( handshake->io ) ) )
    970995    {
     
    9921017tr_handshake*
    9931018tr_handshakeNew( tr_peerIo           * io,
    994                  tr_encryption_mode    encryption_mode,
     1019                 tr_encryption_mode    encryptionMode,
    9951020                 handshakeDoneCB       doneCB,
    9961021                 void                * doneUserData )
     
    10011026    handshake->io = io;
    10021027    handshake->crypto = tr_peerIoGetCrypto( io );
    1003     handshake->allowUnencryptedPeers = encryption_mode!=TR_ENCRYPTION_REQUIRED;
     1028    handshake->encryptionMode = encryptionMode;
    10041029    handshake->doneCB = doneCB;
    10051030    handshake->doneUserData = doneUserData;
    10061031    handshake->handle = tr_peerIoGetHandle( io );
    10071032   
    1008     tr_peerIoSetIOMode( handshake->io, EV_READ|EV_WRITE, 0 );
    1009     tr_peerIoSetIOFuncs( handshake->io, canRead, NULL, gotError, handshake );
     1033    tr_peerIoSetIOFuncs( handshake->io, canRead, gotError, handshake );
    10101034
    10111035    if( tr_peerIoIsIncoming( handshake->io ) )
    10121036        setReadState( handshake, AWAITING_HANDSHAKE );
    1013     else
     1037    else if( encryptionMode != TR_PLAINTEXT_PREFERRED )
    10141038        sendYa( handshake );
     1039    else {
     1040        int msgSize;
     1041        uint8_t * msg = buildHandshakeMessage( handshake, &msgSize );
     1042        handshake->haveSentBitTorrentHandshake = 1;
     1043        setReadState( handshake, AWAITING_HANDSHAKE );
     1044        tr_peerIoWrite( handshake->io, msg, msgSize );
     1045        tr_free( msg );
     1046    }
    10151047
    10161048    return handshake;
  • branches/0.9x/libtransmission/inout.c

    r3780 r3897  
    2626#include "inout.h"
    2727#include "list.h"
    28 #include "net.h"
    2928#include "platform.h"
    3029#include "peer-mgr.h"
    3130#include "utils.h"
    32 
    33 struct tr_io
    34 {
    35     tr_torrent * tor;
    36 };
    3731
    3832/****
     
    7872        ret = TR_ERROR_IO_OTHER;
    7973    else if( func( fd, buf, buflen ) != buflen )
    80         ret = tr_ioErrorFromErrno ();
     74        ret = tr_ioErrorFromErrno( );
    8175    else
    8276        ret = TR_OK;
  • branches/0.9x/libtransmission/ipcparse.c

    r3808 r3897  
    3131
    3232#include "transmission.h"
     33#include "utils.h"
    3334
    3435#include "ipcparse.h"
     
    141142    { "autostart",           2, IPC_MSG_AUTOSTART,    RB_ENTRY_INITIALIZER() },
    142143    { "bad-format",          2, IPC_MSG_BAD,          RB_ENTRY_INITIALIZER() },
     144    { "encryption",          2, IPC_MSG_CRYPTO,       RB_ENTRY_INITIALIZER() },
    143145    { "directory",           2, IPC_MSG_DIR,          RB_ENTRY_INITIALIZER() },
    144146    { "downlimit",           2, IPC_MSG_DOWNLIMIT,    RB_ENTRY_INITIALIZER() },
     
    146148    { "get-automap",         2, IPC_MSG_GETAUTOMAP,   RB_ENTRY_INITIALIZER() },
    147149    { "get-autostart",       2, IPC_MSG_GETAUTOSTART, RB_ENTRY_INITIALIZER() },
     150    { "get-encryption",      2, IPC_MSG_GETCRYPTO,    RB_ENTRY_INITIALIZER() },
    148151    { "get-directory",       2, IPC_MSG_GETDIR,       RB_ENTRY_INITIALIZER() },
    149152    { "get-downlimit",       2, IPC_MSG_GETDOWNLIMIT, RB_ENTRY_INITIALIZER() },
     
    362365
    363366uint8_t *
    364 ipc_mkval( benc_val_t * pk, size_t * len )
    365 {
    366     char * buf, hex[IPC_MIN_MSG_LEN+1];
    367     int    used, max;
    368 
    369     used = IPC_MIN_MSG_LEN;
    370     max  = IPC_MIN_MSG_LEN;
    371     buf  = malloc( IPC_MIN_MSG_LEN );
    372     if( NULL == buf )
    373     {
    374         return NULL;
    375     }
    376 
    377     if( tr_bencSave( pk, &buf, &used, &max ) )
    378     {
    379         SAFEFREE( buf );
    380         return NULL;
    381     }
    382 
    383     /* ok, this check is pretty laughable */
    384     if( IPC_MAX_MSG_LEN < used )
    385     {
    386         free( buf );
     367ipc_mkval( benc_val_t * pk, size_t * setmeSize )
     368{
     369    int bencSize = 0;
     370    char * benc = tr_bencSave( pk, &bencSize );
     371    uint8_t * ret = NULL;
     372
     373    if( bencSize > IPC_MAX_MSG_LEN )
    387374        errno = EFBIG;
    388         return NULL;
    389     }
    390 
    391     assert( 0 <= used );
    392     snprintf( hex, sizeof hex, "%0*X",
    393               IPC_MIN_MSG_LEN, used - IPC_MIN_MSG_LEN );
    394     memcpy( buf, hex, IPC_MIN_MSG_LEN );
    395     *len = used;
    396 
    397     return ( uint8_t * )buf;
     375    else {
     376        const size_t size = IPC_MIN_MSG_LEN + bencSize;
     377        ret = tr_new( uint8_t, size );
     378        snprintf( (char*)ret, size, "%0*X", IPC_MIN_MSG_LEN, bencSize );
     379        memcpy( ret + IPC_MIN_MSG_LEN, benc, bencSize );
     380        *setmeSize = size;
     381    }
     382
     383    tr_free( benc );
     384    return ret;
    398385}
    399386
  • branches/0.9x/libtransmission/ipcparse.h

    r3566 r3897  
    4343    IPC_MSG_AUTOSTART,
    4444    IPC_MSG_BAD,
     45    IPC_MSG_CRYPTO,
    4546    IPC_MSG_DIR,
    4647    IPC_MSG_DOWNLIMIT,
     
    4849    IPC_MSG_GETAUTOMAP,
    4950    IPC_MSG_GETAUTOSTART,
     51    IPC_MSG_GETCRYPTO,
    5052    IPC_MSG_GETDIR,
    5153    IPC_MSG_GETDOWNLIMIT,
  • branches/0.9x/libtransmission/makemeta.c

    r3657 r3897  
    386386    if ( !builder->abortFlag ) {
    387387        size_t nmemb;
    388         char * pch = tr_bencSaveMalloc( &top, &n );
     388        char * pch = tr_bencSave( &top, &n );
    389389        FILE * fp = fopen( builder->outputFile, "wb+" );
    390390        nmemb = n;
  • branches/0.9x/libtransmission/peer-io.c

    r3555 r3897  
    1818#include <arpa/inet.h> /* inet_ntoa */
    1919
    20 #include <sys/types.h> /* event.h needs this */
    2120#include <event.h>
    2221
     
    3130#define IO_TIMEOUT_SECS 8
    3231
     32/* arbitrary */
     33#define TR_RDBUF (1024*8)
     34
    3335/**
    3436***
     
    4951    int socket;
    5052    int encryptionMode;
     53    int timeout;
    5154    struct bufferevent * bufev;
    5255    uint8_t peerId[20];
     
    5962
    6063    tr_can_read_cb     canRead;
    61     tr_did_write_cb    didWrite;
    6264    tr_net_error_cb    gotError;
    6365    void             * userData;
     
    7173
    7274static void
    73 didWriteWrapper( struct bufferevent * e, void * userData )
    74 {
    75     tr_peerIo * c = (tr_peerIo *) userData;
    76     if( c->didWrite != NULL )
    77         (*c->didWrite)( e, c->userData );
    78 }
    79 
    80 static void
    8175canReadWrapper( struct bufferevent * e, void * userData )
    8276{
    8377    int done = 0;
    84     tr_peerIo * c = (tr_peerIo *) userData;
     78    tr_peerIo * c = userData;
    8579    tr_handle * handle = c->handle;
    8680
     
    10094                    continue;
    10195            case READ_MORE:
    102                 tr_peerIoSetIOMode( c, EV_READ, 0 );
    10396            case READ_DONE:
    10497                done = 1;
     
    112105gotErrorWrapper( struct bufferevent * e, short what, void * userData )
    113106{
    114     tr_peerIo * c = (tr_peerIo *) userData;
     107    tr_peerIo * c = userData;
    115108    if( c->gotError != NULL )
    116109        (*c->gotError)( e, what, c->userData );
     
    120113***
    121114**/
     115
     116void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
    122117
    123118static tr_peerIo*
     
    137132    c->socket = socket;
    138133    c->isIncoming = isIncoming ? 1 : 0;
     134    c->timeout = IO_TIMEOUT_SECS;
    139135    c->bufev = bufferevent_new( c->socket,
    140136                                canReadWrapper,
    141                                 didWriteWrapper,
     137                                NULL,
    142138                                gotErrorWrapper,
    143139                                c );
    144     bufferevent_settimeout( c->bufev, IO_TIMEOUT_SECS, IO_TIMEOUT_SECS );
     140    bufferevent_settimeout( c->bufev, c->timeout, c->timeout );
    145141    bufferevent_enable( c->bufev, EV_READ|EV_WRITE );
     142    bufferevent_setwatermark( c->bufev, EV_READ, 0, TR_RDBUF );
     143
    146144    return c;
    147145}
     
    195193    {
    196194        io->canRead = NULL;
    197         io->didWrite = NULL;
    198195        io->gotError = NULL;
    199196        tr_runInEventThread( io->handle, io_dtor, io );
     
    235232}
    236233
     234void
     235tr_peerIoTryRead( tr_peerIo * io )
     236{
     237    if( EVBUFFER_LENGTH( io->bufev->input ) )
     238        canReadWrapper( io->bufev, io );
     239}
     240
    237241void
    238242tr_peerIoSetIOFuncs( tr_peerIo          * io,
    239243                     tr_can_read_cb       readcb,
    240                      tr_did_write_cb      writecb,
    241244                     tr_net_error_cb      errcb,
    242245                     void               * userData )
    243246{
    244247    io->canRead = readcb;
    245     io->didWrite = writecb;
    246248    io->gotError = errcb;
    247249    io->userData = userData;
    248250
    249     if( EVBUFFER_LENGTH( io->bufev->input ) )
    250         canReadWrapper( io->bufev, io );
    251 }
    252 
    253 void
    254 tr_peerIoSetIOMode( tr_peerIo * c, short enable, short disable )
    255 {
    256     tr_setBufferEventMode( c->handle, c->bufev, enable, disable );
     251    tr_peerIoTryRead( io );
    257252}
    258253
     
    278273
    279274        io->bufev = bufferevent_new( io->socket,
    280                                      canReadWrapper,
    281                                      didWriteWrapper,
    282                                      gotErrorWrapper,
     275                                     canReadWrapper, NULL, gotErrorWrapper,
    283276                                     io );
    284         bufferevent_settimeout( io->bufev, IO_TIMEOUT_SECS, IO_TIMEOUT_SECS );
     277        bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
    285278        bufferevent_enable( io->bufev, EV_READ|EV_WRITE );
     279        bufferevent_setwatermark( io->bufev, EV_READ, 0, TR_RDBUF );
    286280
    287281        return 0;
     
    294288tr_peerIoSetTimeoutSecs( tr_peerIo * io, int secs )
    295289{
    296     bufferevent_settimeout( io->bufev, secs, secs );
     290    io->timeout = secs;
     291    bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
    297292}
    298293
     
    405400                int           writeme_len )
    406401{
    407     tr_bufferevent_write( io->handle, io->bufev, writeme, writeme_len );
     402    assert( tr_amInEventThread( io->handle ) );
     403    bufferevent_write( io->bufev, writeme, writeme_len );
    408404}
    409405
     
    412408                   struct evbuffer * buf )
    413409{
    414     tr_peerIoWrite( io, EVBUFFER_DATA(buf), EVBUFFER_LENGTH(buf) );
    415     evbuffer_drain( buf, ~0 );
     410    const size_t n = EVBUFFER_LENGTH( buf );
     411    tr_peerIoWrite( io, EVBUFFER_DATA(buf), n );
     412    evbuffer_drain( buf, n );
    416413}
    417414
     
    442439}
    443440
     441/**
     442***
     443**/
     444
    444445void
    445446tr_peerIoWriteBytes( tr_peerIo        * io,
    446447                     struct evbuffer  * outbuf,
    447448                     const void       * bytes,
    448                      int                byteCount )
     449                     size_t             byteCount )
    449450{
    450451    uint8_t * tmp;
     
    469470
    470471void
     472tr_peerIoWriteUint8( tr_peerIo        * io,
     473                     struct evbuffer  * outbuf,
     474                     uint8_t            writeme )
     475{
     476    tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof(uint8_t) );
     477}
     478
     479void
    471480tr_peerIoWriteUint16( tr_peerIo        * io,
    472481                      struct evbuffer  * outbuf,
     
    478487
    479488void
    480 tr_peerIoWriteUint8( tr_peerIo        * io,
    481                      struct evbuffer  * outbuf,
    482                      uint8_t            writeme )
    483 {
    484     tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof(uint8_t) );
    485 }
    486 
    487 void
    488489tr_peerIoWriteUint32( tr_peerIo        * io,
    489490                      struct evbuffer  * outbuf,
     
    494495}
    495496
     497/***
     498****
     499***/
     500
    496501void
    497502tr_peerIoReadBytes( tr_peerIo        * io,
    498503                    struct evbuffer  * inbuf,
    499504                    void             * bytes,
    500                     int                byteCount )
    501 {
    502     assert( (int)EVBUFFER_LENGTH( inbuf ) >= byteCount );
     505                    size_t             byteCount )
     506{
     507    assert( EVBUFFER_LENGTH( inbuf ) >= byteCount );
    503508
    504509    switch( io->encryptionMode )
    505510    {
    506511        case PEER_ENCRYPTION_NONE:
    507             evbuffer_remove(  inbuf, bytes, byteCount );
     512            evbuffer_remove( inbuf, bytes, byteCount );
    508513            break;
    509514
    510515        case PEER_ENCRYPTION_RC4:
    511             evbuffer_remove(  inbuf, bytes, byteCount );
     516            evbuffer_remove( inbuf, bytes, byteCount );
    512517            tr_cryptoDecrypt( io->crypto, byteCount, bytes, bytes );
    513518            break;
     
    519524
    520525void
     526tr_peerIoReadUint8( tr_peerIo         * io,
     527                    struct evbuffer   * inbuf,
     528                    uint8_t           * setme )
     529{
     530    tr_peerIoReadBytes( io, inbuf, setme, sizeof(uint8_t) );
     531}
     532
     533void
    521534tr_peerIoReadUint16( tr_peerIo         * io,
    522535                     struct evbuffer   * inbuf,
     
    529542
    530543void
    531 tr_peerIoReadUint8( tr_peerIo         * io,
    532                     struct evbuffer   * inbuf,
    533                     uint8_t           * setme )
    534 {
    535     tr_peerIoReadBytes( io, inbuf, setme, sizeof(uint8_t) );
    536 }
    537 
    538 void
    539544tr_peerIoReadUint32( tr_peerIo         * io,
    540545                     struct evbuffer   * inbuf,
     
    549554tr_peerIoDrain( tr_peerIo        * io,
    550555                struct evbuffer  * inbuf,
    551                 int                byteCount )
     556                size_t             byteCount )
    552557{
    553558    uint8_t * tmp = tr_new( uint8_t, byteCount );
  • branches/0.9x/libtransmission/peer-io.h

    r3501 r3897  
    100100typedef enum { READ_MORE, READ_AGAIN, READ_DONE } ReadState;
    101101typedef ReadState (*tr_can_read_cb)(struct bufferevent*, void* user_data);
    102 typedef void (*tr_did_write_cb)(struct bufferevent *, void *);
    103102typedef void (*tr_net_error_cb)(struct bufferevent *, short what, void *);
    104103
    105104void  tr_peerIoSetIOFuncs( tr_peerIo        * io,
    106105                           tr_can_read_cb     readcb,
    107                            tr_did_write_cb    writecb,
    108106                           tr_net_error_cb    errcb,
    109107                           void             * user_data );
    110108
    111 void  tr_peerIoSetIOMode ( tr_peerIo   * io,
    112                            short         enable_mode,
    113                            short         disable_mode );
     109size_t tr_peerIoWriteBytesWaiting( const tr_peerIo * io );
    114110
    115 size_t tr_peerIoWriteBytesWaiting( const tr_peerIo * io );
     111void tr_peerIoTryRead( tr_peerIo * io );
    116112
    117113void tr_peerIoWrite( tr_peerIo   * io,
     
    145141                            struct evbuffer  * outbuf,
    146142                            const void       * bytes,
    147                             int                byteCount );
     143                            size_t             byteCount );
    148144
    149145void tr_peerIoWriteUint8  ( tr_peerIo        * io,
     
    162158                            struct evbuffer  * inbuf,
    163159                            void             * bytes,
    164                             int                byteCount );
     160                            size_t             byteCount );
    165161
    166162void tr_peerIoReadUint8   ( tr_peerIo        * io,
     
    178174void tr_peerIoDrain       ( tr_peerIo        * io,
    179175                            struct evbuffer  * inbuf,
    180                             int                byteCount );
     176                            size_t             byteCount );
    181177
    182178
  • branches/0.9x/libtransmission/peer-mgr-private.h

    r3553 r3897  
    2929};
    3030
     31/**
     32*** The "SWIFT" system is described by Karthik Tamilmani,
     33*** Vinay Pai, and Alexander Mohr of Stony Brook University
     34*** in their paper "SWIFT: A System With Incentives For Trading"
     35*** http://citeseer.ist.psu.edu/tamilmani04swift.html
     36***
     37*** More SWIFT constants are defined in peer-mgr.c
     38**/
     39
     40/**
     41 * Use SWIFT?
     42 */
     43static const int SWIFT_ENABLED = 1;
     44
     45/**
     46 * For every byte the peer uploads to us,
     47 * allow them to download this many bytes from us
     48 */
     49static const double SWIFT_REPAYMENT_RATIO = 1.33;
     50
     51
    3152typedef struct tr_peer
    3253{
     
    3758    unsigned int  doPurge : 1;
    3859
     60    tr_peer_status status;
    3961
    4062    /* number of bad pieces they've contributed to */
     
    6688    double rateToClient;
    6789    double rateToPeer;
     90
     91    int64_t credit;
    6892}
    6993tr_peer;
  • branches/0.9x/libtransmission/peer-mgr.c

    r3807 r3897  
    2020#include <arpa/inet.h> /* inet_ntoa */
    2121
    22 #include <sys/queue.h> /* libevent needs this */
    23 #include <sys/types.h> /* libevent needs this */
    2422#include <event.h>
    2523
     
    3836#include "ratecontrol.h"
    3937#include "shared.h"
     38#include "trcompat.h" /* strlcpy */
    4039#include "trevent.h"
    4140#include "utils.h"
    4241
     42/**
     43*** The "SWIFT" system is described by Karthik Tamilmani,
     44*** Vinay Pai, and Alexander Mohr of Stony Brook University
     45*** in their paper "SWIFT: A System With Incentives For Trading"
     46*** http://citeseer.ist.psu.edu/tamilmani04swift.html
     47***
     48*** More SWIFT constants are defined in peer-mgr-private.h
     49**/
     50
     51/**
     52 * Allow new peers to download this many bytes from
     53 * us when getting started.  This can prevent gridlock
     54 * with other peers using tit-for-tat algorithms
     55 */
     56static const int SWIFT_INITIAL_CREDIT = 64 * 1024; /* 64 KiB */
     57
     58/**
     59 * We expend a fraction of our torrent's total upload speed
     60 * on largesse by uniformly distributing free credit to
     61 * all of our peers.  This too helps prevent gridlock.
     62 */
     63static const double SWIFT_LARGESSE = 0.10; /* 10% of our UL */
     64
     65/**
     66 * How frequently to extend largesse-based credit
     67 */
     68static const int SWIFT_PERIOD_MSEC = 5000;
     69
     70
    4371enum
    4472{
     
    4775
    4876    /* how frequently to decide which peers live and die */
    49     RECONNECT_PERIOD_MSEC = (5 * 1000),
     77    RECONNECT_PERIOD_MSEC = (6 * 1000),
    5078
    5179    /* how frequently to refill peers' request lists */
     
    6088
    6189    /* arbitrary */
    62     MAX_CONNECTED_PEERS_PER_TORRENT = 60,
     90    MAX_CONNECTED_PEERS_PER_TORRENT = 50,
    6391
    6492    /* when many peers are available, keep idle ones this long */
    65     MIN_UPLOAD_IDLE_SECS = 60,
     93    MIN_UPLOAD_IDLE_SECS = (60 * 3),
    6694
    6795    /* when few peers are available, keep idle ones this long */
    68     MAX_UPLOAD_IDLE_SECS = 240,
     96    MAX_UPLOAD_IDLE_SECS = (60 * 10),
    6997
    7098    /* how many peers to unchoke per-torrent. */
    7199    /* FIXME: make this user-configurable? */
    72     NUM_UNCHOKED_PEERS_PER_TORRENT = 12, /* arbitrary */
     100    NUM_UNCHOKED_PEERS_PER_TORRENT = 10, /* arbitrary */
    73101
    74102    /* set this too high and there will be a lot of churn.
     
    116144    tr_timer * rechokeTimer;
    117145    tr_timer * refillTimer;
     146    tr_timer * swiftTimer;
    118147    tr_torrent * tor;
    119148    tr_bitfield * requested;
     
    316345    tr_peer * p;
    317346    p = tr_new0( tr_peer, 1 );
     347    p->credit = SWIFT_INITIAL_CREDIT;
    318348    p->rcToClient = tr_rcInit( );
    319349    p->rcToPeer = tr_rcInit( );
     
    399429    tr_timerFree( &t->rechokeTimer );
    400430    tr_timerFree( &t->refillTimer );
     431    tr_timerFree( &t->swiftTimer );
    401432
    402433    tr_bitfieldFree( t->requested );
     
    448479    tr_bitfield_t * ret;
    449480
     481#if 0
    450482    printf( "%d piece allowed fast set for torrent with %d pieces and hex infohash\n", setCount, pieceCount );
    451483    printf( "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x for node with IP %s:\n",
     
    453485            infohash[10], infohash[11], infohash[12], infohash[13], infohash[14], infohash[15], infohash[16], infohash[7], infohash[18], infohash[19],
    454486            inet_ntoa( *ip ) );
     487#endif
    455488   
    456489    seed = malloc(4 + SHA_DIGEST_LENGTH);
     
    551584    uint32_t peerCount;
    552585    uint32_t fastAllowed;
     586    uint32_t suggested;
    553587};
    554588
     
    560594   
    561595    /* if one *might be* fastallowed to us, get it first...
    562      * I'm putting it on top so we prioritise those pieces at
     596     * I'm putting it on top so we prioritize those pieces at
    563597     * startup, then we'll have them, and we'll be denied access
    564598     * to them */
     
    569603    if (a->priority != b->priority)
    570604        return a->priority > b->priority ? -1 : 1;
     605   
     606    /* otherwise if one was suggested to us, get it */
     607    if (a->suggested != b->suggested)
     608        return a->suggested < b->suggested ? -1 : 1;
    571609
    572610    /* try to fill partial pieces */
     
    641679                    but we're guaranteed to get the same pieces from different peers,
    642680                    so we'll build a list and pray one actually have this one */
    643                 setme->fastAllowed = tr_peerMsgIsPieceFastAllowed( peer->msgs, i);
     681                setme->fastAllowed = tr_peerMsgsIsPieceFastAllowed( peer->msgs, i );
     682                /* Also, if someone SUGGESTed a piece to us, prioritize it over non-suggested others
     683                 */
     684                setme->suggested   = tr_peerMsgsIsPieceSuggested( peer->msgs, i );
    644685            }
    645686        }
     
    731772    for( i=0; peerCount && i<blockCount; ++i )
    732773    {
    733         const int block = blocks[i];
     774        const uint64_t block = blocks[i];
    734775        const uint32_t index = tr_torBlockPiece( tor, block );
    735776        const uint32_t begin = (block * tor->blockSize) - (index * tor->info.pieceSize);
    736         const uint32_t length = tr_torBlockCountBytes( tor, block );
     777        const uint32_t length = tr_torBlockCountBytes( tor, (int)block );
    737778        int j;
    738         assert( _tr_block( tor, index, begin ) == block );
     779        assert( _tr_block( tor, index, begin ) == (int)block );
    739780        assert( begin < (uint32_t)tr_torPieceCountBytes( tor, (int)index ) );
    740781        assert( (begin + length) <= (uint32_t)tr_torPieceCountBytes( tor, (int)index ) );
    741 
    742782
    743783        /* find a peer who can ask for this block */
     
    807847
    808848static void
     849addStrike( Torrent * t, tr_peer * peer )
     850{
     851    tordbg( t, "increasing peer %s strike count to %d", tr_peerIoAddrStr(&peer->in_addr,peer->port), peer->strikes+1 );
     852
     853    if( ++peer->strikes >= MAX_BAD_PIECES_PER_PEER )
     854    {
     855        struct peer_atom * atom = getExistingAtom( t, &peer->in_addr );
     856        atom->myflags |= MYFLAG_BANNED;
     857        peer->doPurge = 1;
     858        tordbg( t, "banning peer %s", tr_peerIoAddrStr(&atom->addr,atom->port) );
     859    }
     860}
     861
     862static void
    809863msgsCallbackFunc( void * vpeer, void * vevent, void * vt )
    810864{
     
    849903            break;
    850904
     905        case TR_PEERMSG_GOT_ASSERT_ERROR:
     906            addStrike( t, peer );
     907            peer->doPurge = 1;
     908            break;
     909
    851910        case TR_PEERMSG_GOT_ERROR:
    852911            peer->doPurge = 1;
     
    936995            tr_peerIoFree( io );
    937996        }
     997        else if( tr_ptrArraySize( t->peers ) >= MAX_CONNECTED_PEERS_PER_TORRENT )
     998        {
     999            tr_peerIoFree( io );
     1000        }
    9381001        else
    9391002        {
     
    9411004
    9421005            if( peer != NULL ) /* we already have this peer */
    943             {
    944                 tr_peerIoFree( io );
    945             }
    946             else if( tr_ptrArraySize( t->peers ) >= MAX_CONNECTED_PEERS_PER_TORRENT )
    9471006            {
    9481007                tr_peerIoFree( io );
     
    10631122        for( i=0; i<peerCount; ++i )
    10641123        {
    1065             struct peer_atom * atom;
    1066             tr_peer * peer;
    1067 
    1068             peer = peers[i];
    1069             if( !tr_bitfieldHas( peer->blame, pieceIndex ) )
    1070                 continue;
    1071 
    1072             ++peer->strikes;
    1073             tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes",
    1074                        tr_peerIoAddrStr(&peer->in_addr,peer->port),
    1075                        pieceIndex, (int)peer->strikes );
    1076             if( peer->strikes < MAX_BAD_PIECES_PER_PEER )
    1077                 continue;
    1078 
    1079             atom = getExistingAtom( t, &peer->in_addr );
    1080             atom->myflags |= MYFLAG_BANNED;
    1081             peer->doPurge = 1;
    1082             tordbg( t, "banning peer %s due to corrupt data", tr_peerIoAddrStr(&atom->addr,atom->port) );
     1124            tr_peer * peer = peers[i];
     1125            if( tr_bitfieldHas( peer->blame, pieceIndex ) )
     1126            {
     1127                tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes",
     1128                           tr_peerIoAddrStr(&peer->in_addr,peer->port),
     1129                           pieceIndex, (int)peer->strikes+1 );
     1130                addStrike( t, peer );
     1131            }
    10831132        }
    10841133    }
     
    11511200static int reconnectPulse( void * vtorrent );
    11521201static int rechokePulse( void * vtorrent );
     1202static int swiftPulse( void * vtorrent );
    11531203
    11541204void
     
    11651215    assert( ( t->isRunning != 0 ) == ( t->reconnectTimer != NULL ) );
    11661216    assert( ( t->isRunning != 0 ) == ( t->rechokeTimer != NULL ) );
     1217    assert( ( t->isRunning != 0 ) == ( t->swiftTimer != NULL ) );
    11671218
    11681219    if( !t->isRunning )
     
    11781229                                       RECHOKE_PERIOD_MSEC );
    11791230
     1231        t->swiftTimer = tr_timerNew( t->manager->handle,
     1232                                     swiftPulse, t,
     1233                                     SWIFT_PERIOD_MSEC );
     1234
    11801235        reconnectPulse( t );
    11811236
    11821237        rechokePulse( t );
     1238
     1239        swiftPulse( t );
    11831240    }
    11841241
     
    11941251    tr_timerFree( &t->rechokeTimer );
    11951252    tr_timerFree( &t->reconnectTimer );
     1253    tr_timerFree( &t->swiftTimer );
    11961254
    11971255    /* disconnect the peers. */
     
    13051363    for( i=0; i<size; ++i )
    13061364        if( peers[i]->io != NULL )
    1307             tr_bitfieldAnd( pieces, peers[i]->have );
     1365            tr_bitfieldOr( pieces, peers[i]->have );
    13081366
    13091367    managerUnlock( (tr_peerMgr*)manager );
     
    13981456
    13991457        tr_netNtop( &peer->in_addr, stat->addr, sizeof(stat->addr) );
     1458        strlcpy( stat->client, (peer->client ? peer->client : ""), sizeof(stat->client) );
    14001459        stat->port             = peer->port;
    14011460        stat->from             = atom->from;
    1402         stat->client           = tr_strdup( peer->client ? peer->client : "" );
    14031461        stat->progress         = peer->progress;
    14041462        stat->isEncrypted      = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0;
     
    14071465        stat->isDownloading    = stat->uploadToRate > 0.01;
    14081466        stat->isUploading      = stat->downloadFromRate > 0.01;
     1467        stat->status           = peer->status;
    14091468    }
    14101469
     
    14231482{
    14241483    tr_peer * peer;
    1425     float rate;
    1426     int randomKey;
     1484    int rate;
    14271485    int preferred;
    14281486    int doUnchoke;
     
    14351493    const struct ChokeData * b = vb;
    14361494
     1495    /* primary key: larger speeds */
     1496    if( a->rate > b->rate )
     1497        return -1;
     1498    if ( a->rate < b->rate )
     1499        return 1;
     1500
     1501    /* secondary key: perferred peers */
    14371502    if( a->preferred != b->preferred )
    14381503        return a->preferred ? -1 : 1;
    14391504
    1440     if( a->preferred )
    1441     {
    1442         if( a->rate > b->rate ) return -1;
    1443         if( a->rate < b->rate ) return 1;
    1444         return 0;
    1445     }
    1446     else
    1447     {
    1448         return a->randomKey - b->randomKey;
    1449     }
     1505    return 0;
    14501506}
    14511507
     
    14631519
    14641520static double
    1465 getWeightedThroughput( const tr_peer * peer )
    1466 {
    1467     return ( 3 * peer->rateToPeer )
    1468          + ( 1 * peer->rateToClient );
     1521getWeightedThroughput( const tr_peer * peer, int clientIsSeed )
     1522{
     1523    return (int)( 10.0 * ( clientIsSeed ? peer->rateToPeer
     1524                                        : peer->rateToClient ) );
    14691525}
    14701526
     
    14761532    tr_peer ** peers = getConnectedPeers( t, &peerCount );
    14771533    struct ChokeData * choke = tr_new0( struct ChokeData, peerCount );
     1534    const int clientIsSeed = tr_torrentIsSeed( t->tor );
    14781535
    14791536    assert( torrentIsLocked( t ) );
     
    14841541        tr_peer * peer = peers[i];
    14851542        struct ChokeData * node;
    1486         if( peer->chokeChangedAt > fibrillationTime )
     1543        if( peer->chokeChangedAt > fibrillationTime ) {
     1544            if( !peer->peerIsChoked )
     1545                ++unchoked;
    14871546            continue;
     1547        }
    14881548
    14891549        node = &choke[size++];
    14901550        node->peer = peer;
    14911551        node->preferred = peer->peerIsInterested && !clientIsSnubbedBy(peer);
    1492         node->randomKey = tr_rand( INT_MAX );
    1493         node->rate = getWeightedThroughput( peer );
     1552        node->rate = getWeightedThroughput( peer, clientIsSeed );
    14941553    }
    14951554
    14961555    qsort( choke, size, sizeof(struct ChokeData), compareChoke );
    14971556
    1498     for( i=0; i<size && i<NUM_UNCHOKED_PEERS_PER_TORRENT; ++i ) {
     1557    for( i=0; i<size && unchoked<NUM_UNCHOKED_PEERS_PER_TORRENT; ++i ) {
    14991558        choke[i].doUnchoke = 1;
    15001559        ++unchoked;
     
    15021561
    15031562    for( ; i<size; ++i ) {
     1563        ++unchoked;
    15041564        choke[i].doUnchoke = 1;
    1505         ++unchoked;
    15061565        if( choke[i].peer->peerIsInterested )
    15071566            break;
     
    15221581    torrentLock( t );
    15231582    rechoke( t );
     1583    torrentUnlock( t );
     1584    return TRUE;
     1585}
     1586
     1587/***
     1588****
     1589***/
     1590
     1591static int
     1592swiftPulse( void * vtorrent )
     1593{
     1594    Torrent * t = vtorrent;
     1595    torrentLock( t );
     1596
     1597    if( !tr_torrentIsSeed( t->tor ) )
     1598    {
     1599        int i;
     1600        int peerCount = 0;
     1601        int deadbeatCount = 0;
     1602        tr_peer ** peers = getConnectedPeers( t, &peerCount );
     1603        tr_peer ** deadbeats = tr_new( tr_peer*, peerCount );
     1604
     1605        const double ul_KiBsec = tr_rcRate( t->tor->upload );
     1606        const double ul_KiB = ul_KiBsec * (SWIFT_PERIOD_MSEC/1000.0);
     1607        const double ul_bytes = ul_KiB * 1024;
     1608        const double freeCreditTotal = ul_bytes * SWIFT_LARGESSE;
     1609        int freeCreditPerPeer;
     1610
     1611        for( i=0; i<peerCount; ++i ) {
     1612            tr_peer * peer = peers[i];
     1613            if( peer->credit <= 0 )
     1614                deadbeats[deadbeatCount++] =  peer;
     1615        }
     1616
     1617        freeCreditPerPeer = (int)( freeCreditTotal / deadbeatCount );
     1618        for( i=0; i<deadbeatCount; ++i )
     1619            deadbeats[i]->credit = freeCreditPerPeer;
     1620
     1621        tordbg( t, "%d deadbeats, "
     1622            "who are each being granted %d bytes' credit "
     1623            "for a total of %.1f KiB, "
     1624            "%d%% of the torrent's ul speed %.1f\n",
     1625            deadbeatCount, freeCreditPerPeer,
     1626            ul_KiBsec*SWIFT_LARGESSE, (int)(SWIFT_LARGESSE*100), ul_KiBsec );
     1627
     1628        tr_free( deadbeats );
     1629        tr_free( peers );
     1630    }
     1631
    15241632    torrentUnlock( t );
    15251633    return TRUE;
     
    16331741         * now to weed it out in case someone sends it to us via pex */
    16341742        if( atom->myflags & MYFLAG_BANNED ) {
     1743#if 0
    16351744            tordbg( t, "RECONNECT peer %d (%s) is banned...",
    16361745                    i, tr_peerIoAddrStr(&atom->addr,atom->port) );
     1746#endif
    16371747            continue;
    16381748        }
     
    16401750        /* we don't need two connections to the same peer... */
    16411751        if( peerIsInUse( t, &atom->addr ) ) {
     1752#if 0
    16421753            tordbg( t, "RECONNECT peer %d (%s) is in use..",
    16431754                    i, tr_peerIoAddrStr(&atom->addr,atom->port) );
     1755#endif
    16441756            continue;
    16451757        }
     
    16471759        /* no need to connect if we're both seeds... */
    16481760        if( seed && (atom->flags & ADDED_F_SEED_FLAG) ) {
     1761#if 0
    16491762            tordbg( t, "RECONNECT peer %d (%s) is a seed and so are we..",
    16501763                    i, tr_peerIoAddrStr(&atom->addr,atom->port) );
     1764#endif
    16511765            continue;
    16521766        }
     
    16541768        /* we're wasting our time trying to connect to this bozo. */
    16551769        if( atom->numFails > 10 ) {
     1770#if 0
    16561771            tordbg( t, "RECONNECT peer %d (%s) gives us nothing but failure.",
    16571772                    i, tr_peerIoAddrStr(&atom->addr,atom->port) );
     1773#endif
    16581774            continue;
    16591775        }
     
    16921808    else
    16931809    {
    1694         int i, nCandidates, nBad, nAdd;
     1810        int i, nCandidates, nBad;
    16951811        struct peer_atom ** candidates = getPeerCandidates( t, &nCandidates );
    16961812        struct tr_peer ** connections = getPeersToClose( t, &nBad );
    1697         const int peerCount = tr_ptrArraySize( t->peers );
    16981813
    16991814        if( nBad || nCandidates )
     
    17191834
    17201835        /* add some new ones */
    1721         nAdd = !peerCount ? MAX_CONNECTED_PEERS_PER_TORRENT
    1722                           : MAX_RECONNECTIONS_PER_PULSE;
    1723         for( i=0; i<nAdd && i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i )
     1836        for( i=0; i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i )
    17241837        {
    17251838            tr_peerMgr * mgr = t->manager;
  • branches/0.9x/libtransmission/peer-msgs.c

    r3837 r3897  
    2121#include <netinet/in.h> /* struct in_addr */
    2222
    23 #include <sys/queue.h> /* libevent needs this */
    24 #include <sys/types.h> /* libevent needs this */
    2523#include <event.h>
    2624
     
    7169
    7270    PEX_INTERVAL            = (60 * 1000), /* msec between calls to sendPex() */
    73     PEER_PULSE_INTERVAL     = (100),       /* msec between calls to pulse() */
     71    PEER_PULSE_INTERVAL     = (250),       /* msec between calls to pulse() */
    7472    RATE_PULSE_INTERVAL     = (333),       /* msec between calls to ratePulse() */
    75 
    76     /* number of pieces generated for allow-fast,
    77       threshold for fast-allowing others */
    78     MAX_ALLOWED_SET_COUNT   = 10
     73     
     74    /* Fast Peers Extension constants */
     75    MAX_FAST_ALLOWED_COUNT   = 10,          /* max. number of pieces we fast-allow to another peer */
     76    MAX_FAST_ALLOWED_THRESHOLD = 10,        /* max threshold for allowing fast-pieces requests */
     77
    7978};
    8079
     
    8281{
    8382    AWAITING_BT_LENGTH,
    84     AWAITING_BT_MESSAGE
     83    AWAITING_BT_ID,
     84    AWAITING_BT_MESSAGE,
     85    AWAITING_BT_PIECE
    8586};
    8687
     
    105106}
    106107
     108/* this is raw, unchanged data from the peer regarding
     109 * the current message that it's sending us. */
     110struct tr_incoming
     111{
     112    uint32_t length; /* includes the +1 for id length */
     113    uint8_t id;
     114    struct peer_request blockReq; /* metadata for incoming blocks */
     115    struct evbuffer * block; /* piece data for incoming blocks */
     116};
     117
    107118struct tr_peermsgs
    108119{
     
    130141    time_t clientSentAnythingAt;
    131142
    132     unsigned int notListening             : 1;
     143    unsigned int peerSentBitfield         : 1;
    133144    unsigned int peerSupportsPex          : 1;
    134145    unsigned int clientSentLtepHandshake  : 1;
    135146    unsigned int peerSentLtepHandshake    : 1;
     147    unsigned int sendingBlock             : 1;
    136148   
    137149    tr_bitfield * clientAllowedPieces;
    138150    tr_bitfield * peerAllowedPieces;
    139151   
     152    tr_bitfield * clientSuggestedPieces;
     153   
    140154    uint8_t state;
    141155    uint8_t ut_pex_id;
    142156    uint16_t pexCount;
    143     uint32_t incomingMessageLength;
    144157    uint32_t maxActiveRequests;
    145158    uint32_t minActiveRequests;
     159
     160    struct tr_incoming incoming;
    146161
    147162    tr_pex * pex;
     
    251266
    252267static void
     268fireGotAssertError( tr_peermsgs * msgs )
     269{
     270    tr_peermsgs_event e = blankEvent;
     271    e.eventType = TR_PEERMSG_GOT_ASSERT_ERROR;
     272    publish( msgs, &e );
     273}
     274
     275static void
    253276fireGotError( tr_peermsgs * msgs )
    254277{
     
    426449                 uint32_t      pieceIndex )
    427450{
    428     dbgmsg( msgs, "w00t SUGGESTing them piece #%d", pieceIndex );
    429     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
    430     tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST );
    431     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     451    assert( msgs != NULL );
    432452   
    433     updateInterest( msgs );
     453    if( tr_peerIoSupportsFEXT( msgs->io ) )
     454    {
     455        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
     456        tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST );
     457        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     458    }
    434459}
    435460#endif
     
    437462sendFastHave( tr_peermsgs * msgs, int all )
    438463{
    439     dbgmsg( msgs, "w00t telling them we have %s pieces", (all ? "ALL" : "NONE" ) );
    440     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) );
    441     tr_peerIoWriteUint8( msgs->io, msgs->outMessages, ( all ? BT_HAVE_ALL
    442                                                             : BT_HAVE_NONE ) );
    443     updateInterest( msgs );
     464    assert( msgs != NULL );
     465   
     466    if( tr_peerIoSupportsFEXT( msgs->io ) )
     467    {
     468        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) );
     469        tr_peerIoWriteUint8( msgs->io, msgs->outMessages, ( all ? BT_HAVE_ALL
     470                                                                : BT_HAVE_NONE ) );
     471        updateInterest( msgs );
     472    }
    444473}
    445474
     
    467496                 uint32_t      pieceIndex)
    468497{
    469     dbgmsg( msgs, "w00t telling them we ALLOW_FAST piece #%d", pieceIndex );
    470     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
    471     tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_ALLOWED_FAST );
    472     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     498    assert( msgs != NULL );
     499   
     500    if( tr_peerIoSupportsFEXT( msgs->io ) )
     501    {
     502        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
     503        tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_ALLOWED_FAST );
     504        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     505    }
    473506}
    474507
     
    534567    {
    535568        struct peer_request * r = tr_list_pop_front( &msgs->clientWillAskFor );
     569        assert( requestIsValid( msgs, r ) );
     570        assert( tr_bitfieldHas( msgs->info->have, r->index ) );
    536571        protocolSendRequest( msgs, r );
    537572        r->time_requested = msgs->lastReqAddedAt = time( NULL );
     
    550585        fireNeedReq( msgs );
    551586}
     587
     588static int
     589pulse( void * vmsgs );
    552590
    553591int
     
    701739        tr_bencInitInt( tr_bencDictAdd( &val, "p" ), port );
    702740    tr_bencInitStr( tr_bencDictAdd( &val, "v" ), v, 0, 1 );
    703     buf = tr_bencSaveMalloc( &val, &len );
     741    buf = tr_bencSave( &val, &len );
    704742
    705743    tr_peerIoWriteUint32( msgs->io, outbuf, 2*sizeof(uint8_t) + len );
     
    713751    dbgmsg( msgs, "here is the ltep handshake we sent:" );
    714752    tr_bencPrint( &val );
     753    dbgmsg( msgs, "here is the ltep handshake we read [%s]:", tr_bencSave( &val, NULL ) );
    715754#endif
    716755
     
    739778    dbgmsg( msgs, "here is the ltep handshake we read:" );
    740779    tr_bencPrint( &val );
     780    dbgmsg( msgs, "here is the ltep handshake we read [%s]:", tr_bencSave( &val, NULL ) );
    741781#endif
    742782
     
    817857        dbgmsg( msgs, "got ltep handshake" );
    818858        parseLtepHandshake( msgs, msglen, inbuf );
    819         sendLtepHandshake( msgs );
    820         sendPex( msgs );
     859        if( tr_peerIoSupportsLTEP( msgs->io ) )
     860        {
     861            sendLtepHandshake( msgs );
     862            sendPex( msgs );
     863        }
    821864    }
    822865    else if( ltep_msgid == msgs->ut_pex_id )
     
    834877
    835878static int
    836 readBtLength( tr_peermsgs * msgs, struct evbuffer * inbuf )
     879readBtLength( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
    837880{
    838881    uint32_t len;
    839     const size_t needlen = sizeof(uint32_t);
    840 
    841     if( EVBUFFER_LENGTH(inbuf) < needlen )
     882
     883    if( inlen < sizeof(len) )
    842884        return READ_MORE;
    843885
     
    847889        dbgmsg( msgs, "got KeepAlive" );
    848890    else {
    849         msgs->incomingMessageLength = len;
     891        msgs->incoming.length = len;
     892        msgs->state = AWAITING_BT_ID;
     893    }
     894
     895    return READ_AGAIN;
     896}
     897
     898static int
     899readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen );
     900
     901static int
     902readBtId( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
     903{
     904    uint8_t id;
     905
     906    if( inlen < sizeof(uint8_t) )
     907        return READ_MORE;
     908
     909    tr_peerIoReadUint8( msgs->io, inbuf, &id );
     910    msgs->incoming.id = id;
     911
     912    if( id==BT_PIECE )
     913    {
     914        msgs->state = AWAITING_BT_PIECE;
     915        return READ_AGAIN;
     916    }
     917    else if( msgs->incoming.length != 1 )
     918    {
    850919        msgs->state = AWAITING_BT_MESSAGE;
    851     }
    852 
    853     return READ_AGAIN;
     920        return READ_AGAIN;
     921    }
     922    else return readBtMessage( msgs, inbuf, inlen-1 );
    854923}
    855924
     
    866935clientCanSendFastBlock( const tr_peermsgs * msgs UNUSED )
    867936{
    868     /* FIXME(tiennou): base this on how many blocks we've already sent this
    869      * peer, or maybe how many fast blocks per minute we've sent overall,
    870      * or maybe how much bandwidth we're already using up w/o fast peers.
    871      * I don't know what the Right Thing here is, but
    872      * the previous measurement of how many pieces we have is not enough. */
    873     return FALSE;
     937    /* We can't send a fast piece if a peer has more than MAX_FAST_ALLOWED_THRESHOLD pieces */
     938    if( tr_bitfieldCountTrueBits( msgs->info->have ) > MAX_FAST_ALLOWED_THRESHOLD )
     939        return FALSE;
     940   
     941    /* ...or if we don't have ourself enough pieces */
     942    if( tr_bitfieldCountTrueBits( tr_cpPieceBitfield( msgs->torrent->completion ) ) < MAX_FAST_ALLOWED_THRESHOLD )
     943        return FALSE;
     944
     945    /* Maybe a bandwidth limit ? */
     946    return TRUE;
    874947}
    875948
     
    9541027}
    9551028
    956 static void
     1029static int
    9571030clientGotBlock( tr_peermsgs * msgs, const uint8_t * block, const struct peer_request * req );
    9581031
     1032static void
     1033clientGotBytes( tr_peermsgs * msgs, uint32_t byteCount )
     1034{
     1035    tr_torrent * tor = msgs->torrent;
     1036    tor->activityDate = tr_date( );
     1037    tor->downloadedCur += byteCount;
     1038    msgs->info->pieceDataActivityDate = time( NULL );
     1039    msgs->info->credit += (int)(byteCount * SWIFT_REPAYMENT_RATIO);
     1040    tr_rcTransferred( msgs->info->rcToClient, byteCount );
     1041    tr_rcTransferred( tor->download, byteCount );
     1042    tr_rcTransferred( tor->handle->download, byteCount );
     1043}
     1044
     1045
    9591046static int
    960 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf )
    961 {
    962     uint8_t id;
     1047readBtPiece( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
     1048{
     1049    struct peer_request * req = &msgs->incoming.blockReq;
     1050    assert( EVBUFFER_LENGTH(inbuf) >= inlen );
     1051    dbgmsg( msgs, "In readBtPiece" );
     1052
     1053    if( !req->length )
     1054    {
     1055        if( inlen < 8 )
     1056            return READ_MORE;
     1057
     1058        tr_peerIoReadUint32( msgs->io, inbuf, &req->index );
     1059        tr_peerIoReadUint32( msgs->io, inbuf, &req->offset );
     1060        req->length = msgs->incoming.length - 9;
     1061        dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length );
     1062        return READ_AGAIN;
     1063    }
     1064    else
     1065    {
     1066        int err;
     1067
     1068        /* read in another chunk of data */
     1069        const size_t nLeft = req->length - EVBUFFER_LENGTH(msgs->incoming.block);
     1070        size_t n = MIN( nLeft, inlen );
     1071        uint8_t * buf = tr_new( uint8_t, n );
     1072        assert( EVBUFFER_LENGTH(inbuf) >= n );
     1073        tr_peerIoReadBytes( msgs->io, inbuf, buf, n );
     1074        evbuffer_add( msgs->incoming.block, buf, n );
     1075        clientGotBytes( msgs, n );
     1076        tr_free( buf );
     1077        dbgmsg( msgs, "got %d bytes for block %u:%u->%u ... %d remain",
     1078               (int)n, req->index, req->offset, req->length,
     1079               (int)( req->length - EVBUFFER_LENGTH(msgs->incoming.block) ) );
     1080        if( EVBUFFER_LENGTH(msgs->incoming.block) < req->length )
     1081            return READ_MORE;
     1082
     1083        /* we've got the whole block ... process it */
     1084        err = clientGotBlock( msgs, EVBUFFER_DATA(msgs->incoming.block), req );
     1085
     1086        /* cleanup */
     1087        evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH(msgs->incoming.block) );
     1088        req->length = 0;
     1089        msgs->state = AWAITING_BT_LENGTH;
     1090        if( !err )
     1091            return READ_AGAIN;
     1092        else {
     1093            fireGotAssertError( msgs );
     1094            return READ_DONE;
     1095        }
     1096    }
     1097}
     1098
     1099static int
     1100readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
     1101{
    9631102    uint32_t ui32;
    964     uint32_t msglen = msgs->incomingMessageLength;
     1103    uint32_t msglen = msgs->incoming.length;
     1104    const uint8_t id = msgs->incoming.id;
    9651105    const size_t startBufLen = EVBUFFER_LENGTH( inbuf );
    9661106
    967     if( EVBUFFER_LENGTH(inbuf) < msglen )
     1107    --msglen; // id length
     1108
     1109    if( inlen < msglen )
    9681110        return READ_MORE;
    9691111
    970     tr_peerIoReadUint8( msgs->io, inbuf, &id );
    971     dbgmsg( msgs, "got BT id %d, len %d, buffer size is %d", (int)id, (int)msglen, (int)EVBUFFER_LENGTH(inbuf) );
    972 
    973     if( !messageLengthIsCorrect( msgs, id, msglen ) )
     1112    dbgmsg( msgs, "got BT id %d, len %d, buffer size is %d", (int)id, (int)msglen, (int)inlen );
     1113
     1114    if( !messageLengthIsCorrect( msgs, id, msglen+1 ) )
    9741115    {
    9751116        dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen );
     
    9771118        return READ_DONE;
    9781119    }
    979 
    980     --msglen;
    9811120
    9821121    switch( id )
     
    10051144            msgs->info->peerIsInterested = 0;
    10061145            break;
    1007 
     1146           
    10081147        case BT_HAVE:
    10091148            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
    10101149            dbgmsg( msgs, "got Have: %u", ui32 );
    10111150            tr_bitfieldAdd( msgs->info->have, ui32 );
     1151            /* If this is a fast-allowed piece for this peer, mark it as normal now */
     1152            if( msgs->clientAllowedPieces != NULL && tr_bitfieldHas( msgs->clientAllowedPieces, ui32 ) )
     1153                tr_bitfieldRem( msgs->clientAllowedPieces, ui32 );
    10121154            updatePeerProgress( msgs );
    10131155            tr_rcTransferred( msgs->torrent->swarmspeed, msgs->torrent->info.pieceSize );
     
    10171159            const int clientIsSeed = tr_torrentIsSeed( msgs->torrent );
    10181160            dbgmsg( msgs, "got a bitfield" );
     1161            msgs->peerSentBitfield = 1;
    10191162            tr_peerIoReadBytes( msgs->io, inbuf, msgs->info->have->bits, msglen );
    10201163            updatePeerProgress( msgs );
     
    10451188        }
    10461189
    1047         case BT_PIECE: {
    1048             uint8_t * block;
    1049             struct peer_request req;
    1050             tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
    1051             tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
    1052             req.length = msglen - 8;
    1053             block = tr_new( uint8_t, req.length );
    1054             tr_peerIoReadBytes( msgs->io, inbuf, block, req.length );
    1055             dbgmsg( msgs, "got a Block %u:%u->%u", req.index, req.offset, req.length );
    1056             clientGotBlock( msgs, block, &req );
    1057             tr_free( block );
     1190        case BT_PIECE:
     1191            assert( 0 ); /* should be handled elsewhere! */
    10581192            break;
    1059         }
    1060 
     1193       
    10611194        case BT_PORT:
    10621195            dbgmsg( msgs, "Got a BT_PORT" );
    10631196            tr_peerIoReadUint16( msgs->io, inbuf, &msgs->info->port );
    10641197            break;
    1065 
    1066 #if 0
     1198           
    10671199        case BT_SUGGEST: {
    1068             /* FIXME(tiennou) */
    1069             uint32_t index;
    1070             tr_peerIoReadUint32( msgs->io, inbuf, &index );
     1200            dbgmsg( msgs, "Got a BT_SUGGEST" );
     1201            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
     1202            const tr_bitfield * bt = tr_cpPieceBitfield( msgs->torrent->completion );
     1203            if( tr_bitfieldHas( bt, ui32 ) )
     1204                tr_bitfieldAdd( msgs->clientSuggestedPieces, ui32 );
    10711205            break;
    10721206        }
    1073 
     1207           
    10741208        case BT_HAVE_ALL:
    10751209            dbgmsg( msgs, "Got a BT_HAVE_ALL" );
     
    10771211            updatePeerProgress( msgs );
    10781212            break;
    1079 
     1213       
     1214       
    10801215        case BT_HAVE_NONE:
    10811216            dbgmsg( msgs, "Got a BT_HAVE_NONE" );
     
    10831218            updatePeerProgress( msgs );
    10841219            break;
    1085 
     1220       
    10861221        case BT_REJECT: {
    10871222            struct peer_request req;
     
    11001235            break;
    11011236        }
    1102 #endif
    11031237
    11041238        case BT_LTEP:
     
    11131247    }
    11141248
    1115 
    1116 dbgmsg( msgs, "startBufLen was %d, msglen was %d, current inbuf len is %d", (int)startBufLen, (int)(msglen+1), (int)EVBUFFER_LENGTH(inbuf) );
    1117 
    1118     msgs->incomingMessageLength = -1;
     1249    assert( msglen + 1 == msgs->incoming.length );
     1250    assert( EVBUFFER_LENGTH(inbuf) == startBufLen - msglen );
     1251
    11191252    msgs->state = AWAITING_BT_LENGTH;
    11201253    return READ_AGAIN;
    1121 }
    1122 
    1123 static void
    1124 clientGotBytes( tr_peermsgs * msgs, uint32_t byteCount )
    1125 {
    1126     tr_torrent * tor = msgs->torrent;
    1127     tor->activityDate = tr_date( );
    1128     tor->downloadedCur += byteCount;
    1129     msgs->info->pieceDataActivityDate = time( NULL );
    1130     tr_rcTransferred( msgs->info->rcToClient, byteCount );
    1131     tr_rcTransferred( tor->download, byteCount );
    1132     tr_rcTransferred( tor->handle->download, byteCount );
    11331254}
    11341255
     
    11401261    tor->uploadedCur += byteCount;
    11411262    msgs->info->pieceDataActivityDate = time( NULL );
     1263    msgs->info->credit -= byteCount;
    11421264    tr_rcTransferred( msgs->info->rcToPeer, byteCount );
    11431265    tr_rcTransferred( tor->upload, byteCount );
     
    11451267}
    11461268
    1147 static int
    1148 canDownload( const tr_peermsgs * msgs )
    1149 {
    1150     tr_torrent * tor = msgs->torrent;
     1269static size_t
     1270getDownloadMax( const tr_peermsgs * msgs )
     1271{
     1272    static const size_t maxval = ~0;
     1273    const tr_torrent * tor = msgs->torrent;
    11511274
    11521275    if( tor->downloadLimitMode == TR_SPEEDLIMIT_GLOBAL )
    1153         return !tor->handle->useDownloadLimit || tr_rcCanTransfer( tor->handle->download );
     1276        return tor->handle->useDownloadLimit
     1277            ? tr_rcBytesLeft( tor->handle->download ) : maxval;
    11541278
    11551279    if( tor->downloadLimitMode == TR_SPEEDLIMIT_SINGLE )
    1156         return tr_rcCanTransfer( tor->download );
    1157 
    1158     return TRUE;
     1280        return tr_rcBytesLeft( tor->download );
     1281
     1282    return maxval;
    11591283}
    11601284
     
    11781302gotBadPiece( tr_peermsgs * msgs, uint32_t pieceIndex )
    11791303{
    1180     const uint32_t byteCount = tr_torPieceCountBytes( msgs->torrent, (int)pieceIndex );
     1304    const uint32_t byteCount =
     1305        tr_torPieceCountBytes( msgs->torrent, (int)pieceIndex );
    11811306    reassignBytesToCorrupt( msgs, byteCount );
    11821307}
     
    11961321}
    11971322
    1198 static void
    1199 clientGotBlock( tr_peermsgs * msgs, const uint8_t * data, const struct peer_request * req )
     1323static int
     1324clientGotBlock( tr_peermsgs                * msgs,
     1325                const uint8_t              * data,
     1326                const struct peer_request  * req )
    12001327{
    12011328    int i;
     
    12061333    assert( msgs != NULL );
    12071334    assert( req != NULL );
    1208     assert( req->length > 0 );
    1209     assert( req->length == (uint32_t)tr_torBlockCountBytes( msgs->torrent, block ) );
     1335
     1336    if( req->length != (uint32_t)tr_torBlockCountBytes( msgs->torrent, block ) )
     1337    {
     1338        dbgmsg( msgs, "wrong block size -- expected %u, got %d",
     1339                tr_torBlockCountBytes( msgs->torrent, block ), req->length );
     1340        return TR_ERROR_ASSERT;
     1341    }
    12101342
    12111343    /* save the block */
     
    12201352        clientGotUnwantedBlock( msgs, req );
    12211353        dbgmsg( msgs, "we didn't ask for this message..." );
    1222         return;
     1354        return 0;
    12231355    }
    12241356
     
    12391371        dbgmsg( msgs, "we have this block already..." );
    12401372        clientGotUnwantedBlock( msgs, req );
    1241         return;
     1373        return 0;
    12421374    }
    12431375
     
    12471379
    12481380    msgs->info->peerSentPieceDataAt = time( NULL );
    1249     clientGotBytes( msgs, req->length );
    12501381    i = tr_ioWrite( tor, req->index, req->offset, req->length, data );
    12511382    if( i )
    1252         return;
     1383        return 0;
    12531384
    12541385    tr_cpBlockAdd( tor->completion, block );
     
    12671398        {
    12681399            gotBadPiece( msgs, req->index );
    1269             return;
     1400            return 0;
    12701401        }
    12711402
    12721403        fireClientHave( msgs, req->index );
    12731404    }
     1405
     1406    return 0;
    12741407}
    12751408
     
    12801413    tr_peermsgs * msgs = (tr_peermsgs *) vmsgs;
    12811414    struct evbuffer * inbuf = EVBUFFER_INPUT ( evin );
    1282 
    1283     if( !canDownload( msgs ) )
    1284     {
    1285         msgs->notListening = 1;
    1286         tr_peerIoSetIOMode ( msgs->io, 0, EV_READ );
     1415    const size_t buflen = EVBUFFER_LENGTH( inbuf );
     1416    const size_t downloadMax = getDownloadMax( msgs );
     1417    const size_t n = MIN( buflen, downloadMax );
     1418
     1419    if( !n )
     1420    {
    12871421        ret = READ_DONE;
    12881422    }
    12891423    else switch( msgs->state )
    12901424    {
    1291         case AWAITING_BT_LENGTH:  ret = readBtLength  ( msgs, inbuf ); break;
    1292         case AWAITING_BT_MESSAGE: ret = readBtMessage ( msgs, inbuf ); break;
     1425        case AWAITING_BT_LENGTH:  ret = readBtLength ( msgs, inbuf, n ); break;
     1426        case AWAITING_BT_ID:      ret = readBtId     ( msgs, inbuf, n ); break;
     1427        case AWAITING_BT_MESSAGE: ret = readBtMessage( msgs, inbuf, n ); break;
     1428        case AWAITING_BT_PIECE:   ret = readBtPiece  ( msgs, inbuf, n ); break;
    12931429        default: assert( 0 );
    12941430    }
     
    13081444**/
    13091445
    1310 static int
    1311 canWrite( const tr_peermsgs * msgs )
    1312 {
    1313     /* don't let our outbuffer get too large */
    1314     if( tr_peerIoWriteBytesWaiting( msgs->io ) > 4096 )
    1315         return FALSE;
    1316 
    1317     return TRUE;
    1318 }
    1319 
    13201446static size_t
    13211447getUploadMax( const tr_peermsgs * msgs )
     
    13231449    static const size_t maxval = ~0;
    13241450    const tr_torrent * tor = msgs->torrent;
    1325 
    1326     if( !canWrite( msgs ) )
    1327         return 0;
     1451    const int useSwift = SWIFT_ENABLED && !tr_torrentIsSeed( msgs->torrent );
     1452    const size_t swiftLeft = msgs->info->credit;
     1453    size_t speedLeft;
     1454    size_t bufLeft;
     1455    size_t ret;
    13281456
    13291457    if( tor->uploadLimitMode == TR_SPEEDLIMIT_GLOBAL )
    1330         return tor->handle->useUploadLimit
    1331             ? tr_rcBytesLeft( tor->handle->upload ) : maxval;
    1332 
    1333     if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE )
    1334         return tr_rcBytesLeft( tor->upload );
    1335 
    1336     return maxval;
     1458        speedLeft = tor->handle->useUploadLimit ? tr_rcBytesLeft( tor->handle->upload ) : maxval;
     1459    else if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE )
     1460        speedLeft = tr_rcBytesLeft( tor->upload );
     1461    else
     1462        speedLeft = ~0;
     1463
     1464    bufLeft = 4096 - tr_peerIoWriteBytesWaiting( msgs->io );
     1465    ret = MIN( speedLeft, bufLeft );
     1466    if( useSwift)
     1467        ret = MIN( ret, swiftLeft );
     1468    return ret;
    13371469}
    13381470
     
    13581490}
    13591491
     1492static void
     1493updatePeerStatus( tr_peermsgs * msgs )
     1494{
     1495    tr_peer * peer = msgs->info;
     1496
     1497    if( !msgs->peerSentBitfield )
     1498        peer->status = TR_PEER_STATUS_HANDSHAKE;
     1499
     1500    else if( ( time(NULL) - peer->pieceDataActivityDate ) < 3 )
     1501        peer->status = peer->clientIsChoked
     1502                       ? TR_PEER_STATUS_ACTIVE_AND_CHOKED
     1503                       : TR_PEER_STATUS_ACTIVE;
     1504
     1505    else if( peer->peerIsChoked )
     1506        peer->status = TR_PEER_STATUS_PEER_IS_CHOKED;
     1507
     1508    else if( peer->clientIsChoked )
     1509        peer->status = peer->clientIsInterested
     1510                       ? TR_PEER_STATUS_CLIENT_IS_INTERESTED
     1511                       : TR_PEER_STATUS_CLIENT_IS_CHOKED;
     1512
     1513    else if( msgs->clientAskedFor != NULL )
     1514        peer->status = TR_PEER_STATUS_REQUEST_SENT;
     1515
     1516    else
     1517        peer->status = TR_PEER_STATUS_READY;
     1518}
     1519
    13601520static int
    13611521pulse( void * vmsgs )
     
    13641524    tr_peermsgs * msgs = vmsgs;
    13651525    struct peer_request * r;
    1366     size_t len;
    1367 
    1368     /* if we froze out a downloaded block because of speed limits,
    1369        start listening to the peer again */
    1370     if( msgs->notListening && canDownload( msgs ) )
    1371     {
    1372         msgs->notListening = 0;
    1373         tr_peerIoSetIOMode ( msgs->io, EV_READ, 0 );
    1374     }
    1375 
     1526
     1527    tr_peerIoTryRead( msgs->io );
    13761528    pumpRequestQueue( msgs );
    1377 
    1378     if( !canWrite( msgs ) )
    1379     {
    1380     }
    1381     else if(( len = EVBUFFER_LENGTH( msgs->outBlock ) ))
     1529    updatePeerStatus( msgs );
     1530
     1531    if( msgs->sendingBlock )
    13821532    {
    13831533        const size_t uploadMax = getUploadMax( msgs );
     1534        size_t len = EVBUFFER_LENGTH( msgs->outBlock );
    13841535        const size_t outlen = MIN( len, uploadMax );
    1385         tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen );
    1386         evbuffer_drain( msgs->outBlock, outlen );
    1387         msgs->clientSentAnythingAt = now;
    1388         peerGotBytes( msgs, outlen );
    1389         len -= outlen;
    1390         dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen, (int)len );
    1391         fflush( stdout );
    1392     }
    1393     else if(( len = EVBUFFER_LENGTH( msgs->outMessages ) ))
    1394     {
    1395         tr_peerIoWriteBuf( msgs->io, msgs->outMessages );
    1396         msgs->clientSentAnythingAt = now;
    1397     }
    1398     else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS )
    1399     {
    1400         sendKeepalive( msgs );
    1401     }
    1402 
    1403     if( !EVBUFFER_LENGTH( msgs->outBlock )
    1404         && (( r = popNextRequest( msgs )))
    1405         && requestIsValid( msgs, r )
    1406         && tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) )
    1407     {
    1408         uint8_t * buf = tr_new( uint8_t, r->length );
    1409 
    1410         if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) )
     1536
     1537        assert( len );
     1538
     1539        if( outlen )
    14111540        {
    1412             tr_peerIo * io = msgs->io;
    1413             struct evbuffer * out = msgs->outBlock;
    1414 
    1415             dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length );
    1416             tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );
    1417             tr_peerIoWriteUint8 ( io, out, BT_PIECE );
    1418             tr_peerIoWriteUint32( io, out, r->index );
    1419             tr_peerIoWriteUint32( io, out, r->offset );
    1420             tr_peerIoWriteBytes ( io, out, buf, r->length );
     1541            tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen );
     1542            evbuffer_drain( msgs->outBlock, outlen );
     1543            peerGotBytes( msgs, outlen );
     1544
     1545            len -= outlen;
     1546            msgs->clientSentAnythingAt = now;
     1547            msgs->sendingBlock = len!=0;
     1548
     1549            dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen, (int)len );
    14211550        }
    1422 
    1423         tr_free( buf );
    1424         tr_free( r );
    1425 
    1426         pulse( msgs ); /* start sending it right away */
     1551        else dbgmsg( msgs, "stalled writing block... uploadMax %lu, outlen %lu", uploadMax, outlen );
     1552    }
     1553
     1554    if( !msgs->sendingBlock )
     1555    {
     1556        if(( EVBUFFER_LENGTH( msgs->outMessages ) ))
     1557        {
     1558            dbgmsg( msgs, "flushing outMessages..." );
     1559            tr_peerIoWriteBuf( msgs->io, msgs->outMessages );
     1560            msgs->clientSentAnythingAt = now;
     1561        }
     1562        else if( !EVBUFFER_LENGTH( msgs->outBlock )
     1563            && (( r = popNextRequest( msgs )))
     1564            && requestIsValid( msgs, r )
     1565            && tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) )
     1566        {
     1567            uint8_t * buf = tr_new( uint8_t, r->length );
     1568
     1569            if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) )
     1570            {
     1571                tr_peerIo * io = msgs->io;
     1572                struct evbuffer * out = msgs->outBlock;
     1573
     1574                dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length );
     1575                tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );
     1576                tr_peerIoWriteUint8 ( io, out, BT_PIECE );
     1577                tr_peerIoWriteUint32( io, out, r->index );
     1578                tr_peerIoWriteUint32( io, out, r->offset );
     1579                tr_peerIoWriteBytes ( io, out, buf, r->length );
     1580                msgs->sendingBlock = 1;
     1581            }
     1582
     1583            tr_free( buf );
     1584            tr_free( r );
     1585        }
     1586        else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS )
     1587        {
     1588            sendKeepalive( msgs );
     1589        }
    14271590    }
    14281591
     
    14311594
    14321595static void
    1433 didWrite( struct bufferevent * evin UNUSED, void * vmsgs )
    1434 {
    1435     pulse( vmsgs );
    1436 }
    1437 
    1438 static void
    14391596gotError( struct bufferevent * evbuf UNUSED, short what, void * vmsgs )
    14401597{
    1441     dbgmsg( vmsgs, "libevent got an error! what=%d, errno=%d (%s)",
    1442             (int)what, errno, strerror(errno) );
    1443     fireGotError( vmsgs );
     1598    if( what & EVBUFFER_TIMEOUT )
     1599        dbgmsg( vmsgs, "libevent got a timeout, what=%hd", what );
     1600
     1601    if( what & ( EVBUFFER_EOF | EVBUFFER_ERROR ) ) {
     1602        dbgmsg( vmsgs, "libevent got an error! what=%hd, errno=%d (%s)",
     1603                what, errno, strerror(errno) );
     1604        fireGotError( vmsgs );
     1605    }
    14441606}
    14451607
     
    15791741
    15801742        /* write the pex message */
    1581         benc = tr_bencSaveMalloc( &val, &bencLen );
     1743        benc = tr_bencSave( &val, &bencLen );
    15821744        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, 2*sizeof(uint8_t) + bencLen );
    15831745        tr_peerIoWriteUint8 ( msgs->io, msgs->outMessages, BT_LTEP );
     
    16251787    m->torrent = torrent;
    16261788    m->io = info->io;
     1789    m->info->status = TR_PEER_STATUS_HANDSHAKE;
    16271790    m->info->clientIsChoked = 1;
    16281791    m->info->peerIsChoked = 1;
     
    16301793    m->info->peerIsInterested = 0;
    16311794    m->info->have = tr_bitfieldNew( torrent->info.pieceCount );
     1795    m->state = AWAITING_BT_LENGTH;
    16321796    m->pulseTimer = tr_timerNew( m->handle, pulse, m, PEER_PULSE_INTERVAL );
    16331797    m->rateTimer = tr_timerNew( m->handle, ratePulse, m, RATE_PULSE_INTERVAL );
    16341798    m->pexTimer = tr_timerNew( m->handle, pexPulse, m, PEX_INTERVAL );
    16351799    m->outMessages = evbuffer_new( );
     1800    m->incoming.block = evbuffer_new( );
    16361801    m->outBlock = evbuffer_new( );
    16371802    m->peerAllowedPieces = NULL;
    16381803    m->clientAllowedPieces = NULL;
     1804    m->clientSuggestedPieces = NULL;
    16391805    *setme = tr_publisherSubscribe( m->publisher, func, userData );
    16401806   
     
    16461812            const struct in_addr *peerAddr = tr_peerIoGetAddress( m->io, NULL );
    16471813           
    1648             m->peerAllowedPieces = tr_peerMgrGenerateAllowedSet( MAX_ALLOWED_SET_COUNT,
     1814            m->peerAllowedPieces = tr_peerMgrGenerateAllowedSet( MAX_FAST_ALLOWED_COUNT,
    16491815                                                                 m->torrent->info.pieceCount,
    16501816                                                                 m->torrent->info.hash,
     
    16521818        }
    16531819        m->clientAllowedPieces = tr_bitfieldNew( m->torrent->info.pieceCount );
     1820       
     1821        m->clientSuggestedPieces = tr_bitfieldNew( m->torrent->info.pieceCount );
    16541822    }
    16551823   
    16561824    tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of inactivity */
    1657     tr_peerIoSetIOFuncs( m->io, canRead, didWrite, gotError, m );
    1658     tr_peerIoSetIOMode( m->io, EV_READ|EV_WRITE, 0 );
     1825    tr_peerIoSetIOFuncs( m->io, canRead, gotError, m );
    16591826    ratePulse( m );
    16601827
     
    16771844        peerProgress = m->torrent->info.pieceCount * m->info->progress;
    16781845       
    1679         if ( peerProgress < MAX_ALLOWED_SET_COUNT )
     1846        if ( peerProgress < MAX_FAST_ALLOWED_COUNT )
    16801847            sendFastAllowedSet( m );
    16811848    }
     
    16971864        tr_list_free( &msgs->peerAskedForFast, tr_free );
    16981865        tr_list_free( &msgs->peerAskedFor, tr_free );
     1866        tr_bitfieldFree( msgs->peerAllowedPieces );
     1867        tr_bitfieldFree( msgs->clientAllowedPieces );
     1868        tr_bitfieldFree( msgs->clientSuggestedPieces );
     1869        evbuffer_free( msgs->incoming.block );
    16991870        evbuffer_free( msgs->outMessages );
    17001871        evbuffer_free( msgs->outBlock );
    17011872        tr_free( msgs->pex );
    1702         msgs->pexCount = 0;
     1873
     1874        memset( msgs, ~0, sizeof( tr_peermsgs ) );
    17031875        tr_free( msgs );
    17041876    }
     
    17211893
    17221894int
    1723 tr_peerMsgIsPieceFastAllowed( const tr_peermsgs * peer,
    1724                               uint32_t            index )
     1895tr_peerMsgsIsPieceFastAllowed( const tr_peermsgs * peer,
     1896                               uint32_t            index )
    17251897{
    17261898    return tr_bitfieldHas( peer->clientAllowedPieces, index );
    17271899}
     1900
     1901int
     1902tr_peerMsgsIsPieceSuggested( const tr_peermsgs * peer,
     1903                             uint32_t            index )
     1904{
     1905    return tr_bitfieldHas( peer->clientSuggestedPieces, index );
     1906}
     1907
  • branches/0.9x/libtransmission/peer-msgs.h

    r3447 r3897  
    6666    TR_PEERMSG_PEER_PROGRESS,
    6767    TR_PEERMSG_GOT_ERROR,
     68    TR_PEERMSG_GOT_ASSERT_ERROR,
    6869    TR_PEERMSG_CANCEL,
    6970    TR_PEERMSG_NEED_REQ
     
    8889                                           tr_publisher_tag    tag );
    8990
    90 int               tr_peerMsgIsPieceFastAllowed( const tr_peermsgs * peer,
    91                                                 uint32_t            index );
     91int               tr_peerMsgsIsPieceFastAllowed( const tr_peermsgs * peer,
     92                                                 uint32_t            index );
     93
     94int               tr_peerMsgsIsPieceSuggested( const tr_peermsgs * peer,
     95                                              uint32_t            index );
    9296
    9397#endif
  • branches/0.9x/libtransmission/platform.c

    r3553 r3897  
    232232}
    233233
    234 int
    235 tr_lockTryLock( tr_lock * l ) /* success on zero! */
    236 {
    237 #ifdef __BEOS__
    238     return acquire_sem_etc( l->lock, 1, B_RELATIVE_TIMEOUT, 0 );
    239 #elif defined(WIN32)
    240     return !TryEnterCriticalSection( &l->lock );
    241 #else
    242     return pthread_mutex_trylock( &l->lock );
    243 #endif
    244 }
    245 
    246234void
    247235tr_lockLock( tr_lock * l )
    248236{
    249     tr_thread_id currentThread = tr_getCurrentThread( );
     237    const tr_thread_id currentThread = tr_getCurrentThread( );
     238
    250239    if( l->lockThread == currentThread )
    251240    {
     
    261250        pthread_mutex_lock( &l->lock );
    262251#endif
    263         l->lockThread = tr_getCurrentThread( );
     252        l->lockThread = currentThread;
    264253        l->depth = 1;
    265254    }
  • branches/0.9x/libtransmission/platform.h

    r3254 r3897  
    3939tr_lock *    tr_lockNew        ( void );
    4040void         tr_lockFree       ( tr_lock * );
    41 int          tr_lockTryLock    ( tr_lock * );
    4241void         tr_lockLock       ( tr_lock * );
    4342void         tr_lockUnlock     ( tr_lock * );
  • branches/0.9x/libtransmission/torrent.c

    r3649 r3897  
    881881
    882882void
    883 tr_torrentPeersFree( tr_peer_stat * peers, int peerCount )
    884 {
    885     int i;
    886     for( i=0; i<peerCount; ++i )
    887         tr_free( (char*) peers[i].client );
     883tr_torrentPeersFree( tr_peer_stat * peers, int peerCount UNUSED )
     884{
    888885    tr_free( peers );
    889886}
     
    10061003
    10071004static void
    1008 checkAndStartCB( tr_torrent * tor )
    1009 {
     1005checkAndStartImpl( void * vtor )
     1006{
     1007    tr_torrent * tor = vtor;
     1008
    10101009    tr_globalLock( tor->handle );
    10111010
     
    10211020    tr_globalUnlock( tor->handle );
    10221021}
    1023    
     1022
     1023static void
     1024checkAndStartCB( tr_torrent * tor )
     1025{
     1026    tr_runInEventThread( tor->handle, checkAndStartImpl, tor );
     1027}
     1028
    10241029void
    10251030tr_torrentStart( tr_torrent * tor )
     
    10391044}
    10401045
     1046static void
     1047torrentRecheckDoneImpl( void * vtor )
     1048{
     1049    tr_torrentRecheckCompleteness( vtor );
     1050}
     1051static void
     1052torrentRecheckDoneCB( tr_torrent * tor )
     1053{
     1054    tr_runInEventThread( tor->handle, torrentRecheckDoneImpl, tor );
     1055}
    10411056void
    10421057tr_torrentRecheck( tr_torrent * tor )
     
    10481063    tr_bitfieldAddRange( tor->uncheckedPieces, 0, tor->info.pieceCount );
    10491064
    1050     tr_ioRecheckAdd( tor, tr_torrentRecheckCompleteness );
     1065    tr_ioRecheckAdd( tor, torrentRecheckDoneCB );
    10511066
    10521067    tr_globalUnlock( tor->handle );
     
    10901105    tr_globalLock( tor->handle );
    10911106
     1107    tr_torrentClearStatusCallback( tor );
    10921108    tr_runInEventThread( tor->handle, closeTorrent, tor );
    10931109
  • branches/0.9x/libtransmission/transmission.c

    r3711 r3897  
    9191{
    9292    assert( handle != NULL );
    93     assert( mode==TR_ENCRYPTION_PREFERRED || mode==TR_ENCRYPTION_REQUIRED );
     93    assert( mode==TR_ENCRYPTION_PREFERRED
     94         || mode==TR_ENCRYPTION_REQUIRED
     95         || mode==TR_PLAINTEXT_PREFERRED );
    9496
    9597    handle->encryptionMode = mode;
     
    109111{
    110112    tr_handle * h;
    111     int         i;
    112113
    113114#ifndef WIN32
     
    139140
    140141    h->peerMgr = tr_peerMgrNew( h );
    141 
    142     /* Azureus identity */
    143     for( i=0; i < TR_AZ_ID_LEN; ++i )
    144         h->azId[i] = tr_rand( 0xff );
    145142
    146143    /* Initialize rate and file descripts controls */
     
    299296{
    300297    tr_handle * h = vh;
     298    tr_torrent * t;
     299
     300    for( t=h->torrentList; t!=NULL; t=t->next )
     301        tr_torrentClose( t );
     302
    301303    tr_peerMgrFree( h->peerMgr );
    302304
    303305    tr_rcClose( h->upload );
    304306    tr_rcClose( h->download );
     307   
     308    tr_natTraversalEnable( h, 0 );
     309    while( tr_handleStatus( h )->natTraversalStatus != TR_NAT_TRAVERSAL_DISABLED )
     310        tr_wait( 100 );
    305311
    306312    tr_sharedClose( h->shared );
     
    333339    free( h->tag );
    334340    free( h );
     341}
     342
     343void
     344tr_getSessionStats( const tr_handle   * handle,
     345                    tr_session_stats  * setme )
     346{
     347    assert( handle != NULL );
     348    assert( setme != NULL );
     349
     350    /* FIXME */
     351    setme->downloadedGigs   = 4;
     352    setme->downloadedBytes  = 8;
     353    setme->uploadedGigs     = 15;
     354    setme->uploadedBytes    = 16;
     355    setme->ratio            = 23;
     356    setme->filesAdded       = 42;
     357    setme->sessionCount     = 666;
     358    setme->secondsActive    = 2112;
     359}
     360
     361void
     362tr_getCumulativeSessionStats( const tr_handle   * handle,
     363                              tr_session_stats  * setme )
     364{
     365    tr_getSessionStats( handle, setme );
    335366}
    336367
  • branches/0.9x/libtransmission/transmission.h

    r3665 r3897  
    9797 * tr_init
    9898 ***********************************************************************
    99  * Initializes a libtransmission instance. Returns a obscure handle to
    100  * be passed to all functions below. The tag argument is a short string
     99 * Initializes a libtransmission instance and returns an opaque handle
     100 * to be passed to functions below. The tag argument is a short string
    101101 * unique to the program invoking tr_init(), it is currently used as
    102102 * part of saved torrent files' names to prevent one frontend from
     
    109109tr_handle * tr_init( const char * tag );
    110110
    111 typedef struct tr_tracker_info tr_tracker_info;
     111/* shut down a libtransmission instance created by tr_init(). */
     112void tr_close( tr_handle * );
     113
    112114
    113115/**
     
    115117**/
    116118
     119typedef struct tr_session_stats
     120{
     121    uint64_t downloadedGigs;  /* total down / GiB */
     122    uint64_t downloadedBytes; /* total down % GiB */
     123    uint64_t uploadedGigs;    /* total up / GiB */
     124    uint64_t uploadedBytes;   /* total up % GiB */
     125    double ratio;             /* total up / total down */
     126    uint64_t filesAdded;      /* number of files added */
     127    uint64_t sessionCount;    /* program started N times */
     128    uint64_t secondsActive;   /* how long Transmisson's been running */
     129}
     130tr_session_stats;
     131
     132/* stats from the current and past sessions. */
     133void tr_getCumulativeSessionStats( const tr_handle   * handle,
     134                                   tr_session_stats  * setme );
     135
     136/* stats from the current session. */
     137void tr_getSessionStats( const tr_handle   * handle,
     138                         tr_session_stats  * setme );
     139
     140
     141/**
     142***
     143**/
     144
    117145typedef enum
    118146{
     147    TR_PLAINTEXT_PREFERRED,
    119148    TR_ENCRYPTION_PREFERRED,
    120149    TR_ENCRYPTION_REQUIRED
     
    291320 **********************************************************************/
    292321void tr_torrentRates( tr_handle *, float *, float * );
    293 
    294 /***********************************************************************
    295  * tr_close
    296  ***********************************************************************
    297  * Frees memory allocated by tr_init.
    298  **********************************************************************/
    299 void tr_close( tr_handle * );
    300322
    301323
     
    411433const tr_info * tr_torrentInfo( const tr_torrent * );
    412434
    413 #if 0
    414 /***********************************************************************
    415  * tr_torrentScrape
    416  ***********************************************************************
    417  * Asks the tracker for the count of seeders and leechers. Returns 0
    418  * and fills 's' and 'l' if successful. Otherwise returns 1 if the
    419  * tracker doesn't support the scrape protocol, is unreachable or
    420  * replied with some error. tr_torrentScrape may block up to 20 seconds
    421  * before returning.
    422  **********************************************************************/
    423 int tr_torrentScrape( tr_torrent *, int * s, int * l, int * d );
    424 #endif
    425 
    426435void   tr_torrentSetFolder( tr_torrent *, const char * );
    427436const char * tr_torrentGetFolder( const tr_torrent * );
     
    567576tr_piece;
    568577   
     578typedef struct tr_tracker_info
     579{
     580    char * address;
     581    int    port;
     582    char * announce;
     583    char * scrape;
     584}
     585tr_tracker_info;
     586
    569587struct tr_info
    570588{
     
    696714};
    697715
     716typedef enum
     717{
     718    TR_PEER_STATUS_HANDSHAKE,
     719    TR_PEER_STATUS_PEER_IS_CHOKED,
     720    TR_PEER_STATUS_CLIENT_IS_CHOKED,
     721    TR_PEER_STATUS_CLIENT_IS_INTERESTED,
     722    TR_PEER_STATUS_READY,
     723    TR_PEER_STATUS_ACTIVE_AND_CHOKED,
     724    TR_PEER_STATUS_REQUEST_SENT,
     725    TR_PEER_STATUS_ACTIVE
     726}
     727tr_peer_status;
     728
    698729struct tr_peer_stat
    699730{
    700     char    addr[INET_ADDRSTRLEN];
    701     const char * client;
     731    char addr[INET_ADDRSTRLEN];
     732    char client[80];
    702733   
    703734    unsigned int isEncrypted   : 1;
    704735    unsigned int isDownloading : 1;
    705736    unsigned int isUploading   : 1;
     737
     738    tr_peer_status status;
    706739
    707740    uint8_t  from;
     
    719752    char               * message;
    720753    struct tr_msg_list * next;
    721 };
    722 
    723 struct tr_tracker_info
    724 {
    725     char * address;
    726     int    port;
    727     char * announce;
    728     char * scrape;
    729754};
    730755
  • branches/0.9x/libtransmission/trevent.c

    r3797 r3897  
    6565{
    6666    TR_EV_EVHTTP_MAKE_REQUEST,
    67     TR_EV_BUFFEREVENT_SET,
    68     TR_EV_BUFFEREVENT_WRITE,
    6967    TR_EV_TIMER_ADD,
    70     TR_EV_TIMER_DEL,
    7168    TR_EV_EXEC
    7269};
     
    134131                break;
    135132
    136             case TR_EV_TIMER_DEL:
    137                 event_del( &cmd->timer->event );
    138                 tr_free( cmd->timer );
    139                 --eh->timerCount;
    140                 break;
    141 
    142133            case TR_EV_EVHTTP_MAKE_REQUEST:
    143134                evhttp_make_request( cmd->evcon, cmd->req, cmd->evtype, cmd->uri );
    144135                tr_free( cmd->uri );
    145                 break;
    146 
    147            case TR_EV_BUFFEREVENT_SET:
    148                 bufferevent_enable( cmd->bufev, cmd->enable );
    149                 bufferevent_disable( cmd->bufev, cmd->disable );
    150                 break;
    151 
    152             case TR_EV_BUFFEREVENT_WRITE:
    153                 bufferevent_write( cmd->bufev, cmd->buf, cmd->buflen );
    154                 tr_free( cmd->buf );
    155136                break;
    156137
     
    255236    tr_lockUnlock( eh->lock );
    256237}
     238
     239int
     240tr_amInEventThread( struct tr_handle * handle )
     241{
     242    return tr_amInThread( handle->events->thread );
     243}
     244
    257245
    258246void
     
    277265}
    278266
    279 void
    280 tr_bufferevent_write( tr_handle             * handle,
    281                       struct bufferevent    * bufev,
    282                       const void            * buf,
    283                       size_t                  buflen )
    284 {
    285     if( tr_amInThread( handle->events->thread ) )
    286         bufferevent_write( bufev, (void*)buf, buflen );
    287     else {
    288         struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 );
    289         cmd->mode = TR_EV_BUFFEREVENT_WRITE;
    290         cmd->bufev = bufev;
    291         cmd->buf = tr_strndup( buf, buflen );
    292         cmd->buflen = buflen;
    293         pushList( handle->events, cmd );
    294     }
    295 }
    296 
    297 void
    298 tr_setBufferEventMode( struct tr_handle   * handle,
    299                        struct bufferevent * bufev,
    300                        short                mode_enable,
    301                        short                mode_disable )
    302 {
    303     if( tr_amInThread( handle->events->thread ) ) {
    304         bufferevent_enable( bufev, mode_enable );
    305         bufferevent_disable( bufev, mode_disable );
    306     } else {
    307         struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 );
    308         cmd->mode = TR_EV_BUFFEREVENT_SET;
    309         cmd->bufev = bufev;
    310         cmd->enable = mode_enable;
    311         cmd->disable = mode_disable;
    312         pushList( handle->events, cmd );
    313     }
    314 }
    315 
    316267/**
    317268***
     
    363314    /* destroy the timer directly or via the command queue */
    364315    if( timer!=NULL && !timer->inCallback ) {
    365         if( tr_amInThread( timer->eh->thread ) ) {
    366             void * del = tr_list_remove( &timer->eh->commands, timer, timerCompareFunc );
    367             --timer->eh->timerCount;
    368             event_del( &timer->event );
    369             tr_free( timer );
    370             tr_free( del );
    371         } else {
    372             struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 );
    373             cmd->mode = TR_EV_TIMER_DEL;
    374             cmd->timer = timer;
    375             pushList( timer->eh, cmd );
    376         }
     316        void * del;
     317        assert( tr_amInEventThread( timer->eh->h ) );
     318        del = tr_list_remove( &timer->eh->commands, timer, timerCompareFunc );
     319        --timer->eh->timerCount;
     320        event_del( &timer->event );
     321        tr_free( timer );
     322        tr_free( del );
    377323    }
    378324}
  • branches/0.9x/libtransmission/trevent.h

    r3457 r3897  
    3838                             char                      * uri);
    3939
    40 void tr_bufferevent_write( struct tr_handle    * tr_handle,
    41                            struct bufferevent  * bufferEvent,
    42                            const void          * buf,
    43                            size_t                buflen );
    44 
    45 
    46 void tr_setBufferEventMode( struct tr_handle   * tr_handle,
    47                             struct bufferevent * bufferEvent,
    48                             short                mode_enable,
    49                             short                mode_disable );
    50 
    5140/**
    5241***
     
    7059void tr_timerFree( tr_timer ** timer );
    7160
     61
     62int tr_amInEventThread( struct tr_handle * handle );
     63
    7264void tr_runInEventThread( struct tr_handle * handle,
    7365                          void               func( void* ),
  • branches/0.9x/libtransmission/utils.c

    r3665 r3897  
    893893#endif
    894894}
     895
     896/***
     897****
     898***/
     899
     900
     901#ifndef HAVE_STRLCPY
     902
     903/*
     904 * Copy src to string dst of size siz.  At most siz-1 characters
     905 * will be copied.  Always NUL terminates (unless siz == 0).
     906 * Returns strlen(src); if retval >= siz, truncation occurred.
     907 */
     908size_t
     909strlcpy(char *dst, const char *src, size_t siz)
     910{
     911        char *d = dst;
     912        const char *s = src;
     913        size_t n = siz;
     914
     915        /* Copy as many bytes as will fit */
     916        if (n != 0) {
     917                while (--n != 0) {
     918                        if ((*d++ = *s++) == '\0')
     919                                break;
     920                }
     921        }
     922
     923        /* Not enough room in dst, add NUL and traverse rest of src */
     924        if (n == 0) {
     925                if (siz != 0)
     926                        *d = '\0';              /* NUL-terminate dst */
     927                while (*s++)
     928                        ;
     929        }
     930
     931        return(s - src - 1);    /* count does not include NUL */
     932}
     933
     934#endif /* HAVE_STRLCPY */
     935
     936
     937#ifndef HAVE_STRLCAT
     938
     939/*
     940 * Appends src to string dst of size siz (unlike strncat, siz is the
     941 * full size of dst, not space left).  At most siz-1 characters
     942 * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
     943 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
     944 * If retval >= siz, truncation occurred.
     945 */
     946size_t
     947strlcat(char *dst, const char *src, size_t siz)
     948{
     949        char *d = dst;
     950        const char *s = src;
     951        size_t n = siz;
     952        size_t dlen;
     953
     954        /* Find the end of dst and adjust bytes left but don't go past end */
     955        while (n-- != 0 && *d != '\0')
     956                d++;
     957        dlen = d - dst;
     958        n = siz - dlen;
     959
     960        if (n == 0)
     961                return(dlen + strlen(s));
     962        while (*s != '\0') {
     963                if (n != 1) {
     964                        *d++ = *s;
     965                        n--;
     966                }
     967                s++;
     968        }
     969        *d = '\0';
     970
     971        return(dlen + (s - src));       /* count does not include NUL */
     972}
     973
     974#endif /* HAVE_STRLCAT */
Note: See TracChangeset for help on using the changeset viewer.