Changeset 7176


Ignore:
Timestamp:
Nov 29, 2008, 4:44:24 PM (10 years ago)
Author:
charles
Message:

(1.4x libT) backport the bandwidth fixes back to the 1.4x branch, pass #2: most of the bandwidth code, plus autoconf and xcode makefile stuff

Location:
branches/1.4x
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • branches/1.4x/Transmission.xcodeproj/project.pbxproj

    r7025 r7176  
    8686                A219798B0D07B78400438EA7 /* GroupToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = A219798A0D07B78400438EA7 /* GroupToolbarItem.m */; };
    8787                A21DFF100A292B2B007C5F76 /* Transfers.png in Resources */ = {isa = PBXBuildFile; fileRef = A21DFF0F0A292B2B007C5F76 /* Transfers.png */; };
     88                A21FBBAB0EDA78C300BC3C51 /* bandwidth.h in Headers */ = {isa = PBXBuildFile; fileRef = A21FBBA90EDA78C300BC3C51 /* bandwidth.h */; };
     89                A21FBBAC0EDA78C300BC3C51 /* bandwidth.c in Sources */ = {isa = PBXBuildFile; fileRef = A21FBBAA0EDA78C300BC3C51 /* bandwidth.c */; };
    8890                A22180980D148A71007D09ED /* GroupsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A22180970D148A71007D09ED /* GroupsWindowController.m */; };
    8991                A22180B60D148F0F007D09ED /* GroupsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A22180B50D148F0F007D09ED /* GroupsWindow.xib */; };
     
    124126                A259317E0A73B2CC002F4FE7 /* TransmissionHelp in Resources */ = {isa = PBXBuildFile; fileRef = A259316A0A73B2CC002F4FE7 /* TransmissionHelp */; };
    125127                A25AFDE90D1038AD0092A1BA /* MenuLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = A25AFDE80D1038AD0092A1BA /* MenuLabel.m */; };
     128                A25B400A0EDCB1B8005DD3F6 /* iobuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A25B40080EDCB1B8005DD3F6 /* iobuf.c */; };
     129                A25B400B0EDCB1B8005DD3F6 /* iobuf.h in Headers */ = {isa = PBXBuildFile; fileRef = A25B40090EDCB1B8005DD3F6 /* iobuf.h */; };
    126130                A25D2CBD0CF4C73E0096A262 /* stats.c in Sources */ = {isa = PBXBuildFile; fileRef = A25D2CBB0CF4C7190096A262 /* stats.c */; };
    127131                A25D2CBE0CF4C73E0096A262 /* stats.h in Headers */ = {isa = PBXBuildFile; fileRef = A25D2CBA0CF4C7190096A262 /* stats.h */; };
     
    477481                A219798A0D07B78400438EA7 /* GroupToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GroupToolbarItem.m; path = macosx/GroupToolbarItem.m; sourceTree = "<group>"; };
    478482                A21DFF0F0A292B2B007C5F76 /* Transfers.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Transfers.png; path = macosx/Images/Transfers.png; sourceTree = "<group>"; };
     483                A21FBBA90EDA78C300BC3C51 /* bandwidth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bandwidth.h; path = libtransmission/bandwidth.h; sourceTree = "<group>"; };
     484                A21FBBAA0EDA78C300BC3C51 /* bandwidth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bandwidth.c; path = libtransmission/bandwidth.c; sourceTree = "<group>"; };
    479485                A22180960D148A71007D09ED /* GroupsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupsWindowController.h; path = macosx/GroupsWindowController.h; sourceTree = "<group>"; };
    480486                A22180970D148A71007D09ED /* GroupsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GroupsWindowController.m; path = macosx/GroupsWindowController.m; sourceTree = "<group>"; };
     
    523529                A25AFDE70D1038AD0092A1BA /* MenuLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuLabel.h; path = macosx/MenuLabel.h; sourceTree = "<group>"; };
    524530                A25AFDE80D1038AD0092A1BA /* MenuLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuLabel.m; path = macosx/MenuLabel.m; sourceTree = "<group>"; };
     531                A25B40080EDCB1B8005DD3F6 /* iobuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = iobuf.c; path = libtransmission/iobuf.c; sourceTree = "<group>"; };
     532                A25B40090EDCB1B8005DD3F6 /* iobuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = iobuf.h; path = libtransmission/iobuf.h; sourceTree = "<group>"; };
    525533                A25D2CBA0CF4C7190096A262 /* stats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stats.h; path = libtransmission/stats.h; sourceTree = "<group>"; };
    526534                A25D2CBB0CF4C7190096A262 /* stats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = stats.c; path = libtransmission/stats.c; sourceTree = "<group>"; };
     
    11211129                                4D36BA630CA2F00800A63CA5 /* handshake.c */,
    11221130                                4D36BA640CA2F00800A63CA5 /* handshake.h */,
     1131                                A25B40080EDCB1B8005DD3F6 /* iobuf.c */,
     1132                                A25B40090EDCB1B8005DD3F6 /* iobuf.h */,
    11231133                                4D36BA650CA2F00800A63CA5 /* peer-io.c */,
    11241134                                4D36BA660CA2F00800A63CA5 /* peer-io.h */,
     
    11581168                                BEFC1E000C07861A00B0BB3C /* ratecontrol.h */,
    11591169                                BEFC1E010C07861A00B0BB3C /* ratecontrol.c */,
     1170                                A21FBBA90EDA78C300BC3C51 /* bandwidth.h */,
     1171                                A21FBBAA0EDA78C300BC3C51 /* bandwidth.c */,
    11601172                                BEFC1E020C07861A00B0BB3C /* platform.h */,
    11611173                                BEFC1E030C07861A00B0BB3C /* platform.c */,
     
    14291441                                A2DF58590DE4B2B1000795D5 /* JSON_parser.h in Headers */,
    14301442                                A25E03E20E4015380086C225 /* tr-getopt.h in Headers */,
     1443                                A21FBBAB0EDA78C300BC3C51 /* bandwidth.h in Headers */,
     1444                                A25B400B0EDCB1B8005DD3F6 /* iobuf.h in Headers */,
    14311445                        );
    14321446                        runOnlyForDeploymentPostprocessing = 0;
     
    18411855                                A25E03E30E4015380086C225 /* tr-getopt.c in Sources */,
    18421856                                4DB74F080E8CD75100AEB1A8 /* wildmat.c in Sources */,
     1857                                A21FBBAC0EDA78C300BC3C51 /* bandwidth.c in Sources */,
     1858                                A25B400A0EDCB1B8005DD3F6 /* iobuf.c in Sources */,
    18431859                        );
    18441860                        runOnlyForDeploymentPostprocessing = 0;
  • branches/1.4x/libtransmission/Makefile.am

    r7103 r7176  
    1313
    1414libtransmission_a_SOURCES = \
     15    bandwidth.c \
    1516    bencode.c \
    1617    blocklist.c \
     
    2425    handshake.c \
    2526    inout.c \
     27    iobuf.c \
    2628    json.c \
    2729    JSON_parser.c \
     
    5759
    5860noinst_HEADERS = \
     61    bandwidth.h \
    5962    bencode.h \
    6063    blocklist.h \
     
    6871    handshake.h \
    6972    inout.h \
     73    iobuf.h \
    7074    json.h \
    7175    JSON_parser.h \
  • branches/1.4x/libtransmission/handshake.c

    r6988 r7176  
    2525#include "crypto.h"
    2626#include "handshake.h"
     27#include "iobuf.h"
    2728#include "peer-io.h"
    2829#include "peer-mgr.h"
     
    8990struct tr_handshake
    9091{
    91     unsigned int          havePeerID                  : 1;
    92     unsigned int          haveSentBitTorrentHandshake : 1;
     92    tr_bool               havePeerID;
     93    tr_bool               haveSentBitTorrentHandshake;
    9394    tr_peerIo *           io;
    9495    tr_crypto *           crypto;
     
    334335    /* send it */
    335336    setReadState( handshake, AWAITING_YB );
    336     tr_peerIoWriteBuf( handshake->io, outbuf );
     337    tr_peerIoWriteBuf( handshake->io, outbuf, FALSE );
    337338
    338339    /* cleanup */
     
    486487    tr_cryptoDecryptInit( handshake->crypto );
    487488    setReadState( handshake, AWAITING_VC );
    488     tr_peerIoWriteBuf( handshake->io, outbuf );
     489    tr_peerIoWriteBuf( handshake->io, outbuf, FALSE );
    489490
    490491    /* cleanup */
     
    712713        int       msgSize;
    713714        uint8_t * msg = buildHandshakeMessage( handshake, &msgSize );
    714         tr_peerIoWrite( handshake->io, msg, msgSize );
     715        tr_peerIoWrite( handshake->io, msg, msgSize, FALSE );
    715716        tr_free( msg );
    716717        handshake->haveSentBitTorrentHandshake = 1;
     
    780781
    781782    setReadState( handshake, AWAITING_PAD_A );
    782     tr_peerIoWrite( handshake->io, outbuf, walk - outbuf );
     783    tr_peerIoWrite( handshake->io, outbuf, walk - outbuf, FALSE );
    783784    return READ_NOW;
    784785}
     
    992993
    993994    /* send it out */
    994     tr_peerIoWriteBuf( handshake->io, outbuf );
     995    tr_peerIoWriteBuf( handshake->io, outbuf, FALSE );
    995996    evbuffer_free( outbuf );
    996997
     
    10291030
    10301031static ReadState
    1031 canRead( struct bufferevent * evin,
    1032          void *               arg )
    1033 {
    1034     tr_handshake *    handshake = (tr_handshake *) arg;
    1035     struct evbuffer * inbuf = EVBUFFER_INPUT ( evin );
     1032canRead( struct tr_iobuf * iobuf, void * arg, size_t * piece )
     1033{
     1034    tr_handshake *    handshake = arg;
     1035    struct evbuffer * inbuf = tr_iobuf_input( iobuf );
    10361036    ReadState         ret;
    10371037    int               readyForMore = TRUE;
     1038
     1039    /* no piece data in handshake */
     1040    *piece = 0;
    10381041
    10391042    dbgmsg( handshake, "handling canRead; state is [%s]",
     
    11371140
    11381141static void
    1139 gotError( struct bufferevent * evbuf UNUSED,
    1140           short                      what,
    1141           void *                    arg )
     1142gotError( struct tr_iobuf  * iobuf UNUSED,
     1143          short              what,
     1144          void             * arg )
    11421145{
    11431146    tr_handshake * handshake = (tr_handshake *) arg;
     
    11571160        handshake->haveSentBitTorrentHandshake = 1;
    11581161        setReadState( handshake, AWAITING_HANDSHAKE );
    1159         tr_peerIoWrite( handshake->io, msg, msgSize );
     1162        tr_peerIoWrite( handshake->io, msg, msgSize, FALSE );
    11601163        tr_free( msg );
    11611164    }
     
    11791182{
    11801183    tr_handshake * handshake;
    1181 
    1182     tr_peerIoSetBandwidthUnlimited( io, TR_UP );
    1183     tr_peerIoSetBandwidthUnlimited( io, TR_DOWN );
    11841184
    11851185    handshake = tr_new0( tr_handshake, 1 );
     
    12041204        handshake->haveSentBitTorrentHandshake = 1;
    12051205        setReadState( handshake, AWAITING_HANDSHAKE );
    1206         tr_peerIoWrite( handshake->io, msg, msgSize );
     1206        tr_peerIoWrite( handshake->io, msg, msgSize, FALSE );
    12071207        tr_free( msg );
    12081208    }
  • branches/1.4x/libtransmission/net.c

    r6944 r7176  
    123123}
    124124
    125 int
    126 tr_netOpenTCP( const struct in_addr * addr,
    127                tr_port_t              port )
     125static void
     126setSndBuf( tr_session * session UNUSED, int fd UNUSED )
     127{
     128#if 0
     129    if( fd >= 0 )
     130    {
     131        const int sndbuf = session->so_sndbuf;
     132        const int rcvbuf = session->so_rcvbuf;
     133        setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof( sndbuf ) );
     134        setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof( rcvbuf ) );
     135    }
     136#endif
     137}
     138
     139int
     140tr_netOpenTCP( tr_session            * session,
     141               const struct in_addr  * addr,
     142               tr_port_t               port )
    128143{
    129144    int                s;
     
    133148    if( ( s = createSocket( type ) ) < 0 )
    134149        return -1;
     150
     151    setSndBuf( session, s );
    135152
    136153    memset( &sock, 0, sizeof( sock ) );
     
    198215
    199216int
    200 tr_netAccept( int              b,
    201               struct in_addr * addr,
    202               tr_port_t *      port )
    203 {
    204     return makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) );
     217tr_netAccept( tr_session      * session,
     218              int               b,
     219              struct in_addr  * addr,
     220              tr_port_t       * port )
     221{
     222    int fd = makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) );
     223    setSndBuf( session, fd );
     224    return fd;
    205225}
    206226
  • branches/1.4x/libtransmission/net.h

    r6924 r7176  
    2222 * DEALINGS IN THE SOFTWARE.
    2323 *****************************************************************************/
     24
     25#ifndef __TRANSMISSION__
     26#error only libtransmission should #include this header.
     27#endif
    2428
    2529#ifndef _TR_NET_H_
     
    5963struct in_addr;
    6064struct sockaddr_in;
     65struct tr_session;
    6166
    6267/***********************************************************************
     
    7075 * Sockets
    7176 **********************************************************************/
    72 int  tr_netOpenTCP( const struct in_addr * addr,
     77int  tr_netOpenTCP( struct tr_handle     * session,
     78                    const struct in_addr * addr,
    7379                    tr_port_t              port );
    7480
    7581int  tr_netBindTCP( int port );
    7682
    77 int  tr_netAccept( int    s,
    78                    struct in_addr *,
    79                           tr_port_t * );
     83int  tr_netAccept( struct tr_handle  * session,
     84                   int                 bound,
     85                   struct in_addr    * setme_addr,
     86                   tr_port_t         * setme_port );
    8087
    8188int  tr_netSetTOS( int s,
  • branches/1.4x/libtransmission/peer-common.h

    r6876 r7176  
    1010 * $Id$
    1111 */
     12
     13#ifndef __TRANSMISSION__
     14#error only libtransmission should #include this header.
     15#endif
    1216
    1317#ifndef TR_PEER_H
     
    5054{
    5155    PeerEventType    eventType;
    52     uint32_t         pieceIndex; /* for GOT_BLOCK, CANCEL */
    53     uint32_t         offset; /* for GOT_BLOCK */
    54     uint32_t         length; /* for GOT_BLOCK + GOT_DATA */
    55     float            progress; /* for TR_PEER_PEER_PROGRESS */
    56     int              err; /* errno for TR_PEER_GOT_ERROR */
     56    uint32_t         pieceIndex;   /* for GOT_BLOCK, CANCEL */
     57    uint32_t         offset;       /* for GOT_BLOCK */
     58    uint32_t         length;       /* for GOT_BLOCK + GOT_DATA */
     59    float            progress;     /* for PEER_PROGRESS */
     60    int              err;          /* errno for GOT_ERROR */
     61    int              wasPieceData; /* for GOT_DATA */
    5762}
    5863tr_peer_event;
  • branches/1.4x/libtransmission/peer-io.c

    r7069 r7176  
    2727
    2828#include "transmission.h"
     29#include "bandwidth.h"
    2930#include "crypto.h"
     31#include "iobuf.h"
     32#include "list.h"
    3033#include "net.h"
    3134#include "peer-io.h"
    32 #include "ratecontrol.h"
    3335#include "trevent.h"
    3436#include "utils.h"
    3537
     38#define MAGIC_NUMBER 206745
    3639#define IO_TIMEOUT_SECS 8
    3740
    3841static size_t
    39 addPacketOverhead( size_t d )
     42getPacketOverhead( size_t d )
    4043{
    4144    /**
     
    5760    static const double assumed_payload_data_rate = 94.0;
    5861
    59     return (size_t)( d * ( 100.0 / assumed_payload_data_rate ) );
     62    return (size_t)( d * ( 100.0 / assumed_payload_data_rate ) - d );
    6063}
    6164
     
    7073    } while( 0 )
    7174
    72 struct tr_bandwidth
    73 {
    74     unsigned int    isUnlimited : 1;
    75     size_t          bytesUsed;
    76     size_t          bytesLeft;
     75struct tr_datatype
     76{
     77    tr_bool  isPieceData;
     78    size_t   length;
    7779};
    7880
    7981struct tr_peerIo
    8082{
    81     unsigned int           isEncrypted               : 1;
    82     unsigned int           isIncoming                : 1;
    83     unsigned int           peerIdIsSet               : 1;
    84     unsigned int           extendedProtocolSupported : 1;
    85     unsigned int           fastPeersSupported        : 1;
    86 
    87     uint8_t                encryptionMode;
    88     uint8_t                timeout;
    89     uint16_t               port;
    90     int                    socket;
    91 
    92     uint8_t                peerId[20];
    93     time_t                 timeCreated;
    94 
    95     tr_session *           session;
    96 
    97     struct in_addr         in_addr;
    98     struct bufferevent *   bufev;
    99     struct evbuffer *      output;
    100 
    101     tr_can_read_cb         canRead;
    102     tr_did_write_cb        didWrite;
    103     tr_net_error_cb        gotError;
    104     void *                 userData;
    105 
    106     size_t                 bufferSize[2];
    107 
    108     struct tr_bandwidth    bandwidth[2];
    109 
    110     tr_crypto *            crypto;
     83    tr_bool                  isEncrypted;
     84    tr_bool                  isIncoming;
     85    tr_bool                  peerIdIsSet;
     86    tr_bool                  extendedProtocolSupported;
     87    tr_bool                  fastPeersSupported;
     88
     89    int                      magicNumber;
     90
     91    uint8_t                  encryptionMode;
     92    uint8_t                  timeout;
     93    uint16_t                 port;
     94    int                      socket;
     95
     96    uint8_t                  peerId[20];
     97    time_t                   timeCreated;
     98
     99    tr_session             * session;
     100
     101    struct in_addr           in_addr;
     102    struct tr_iobuf        * iobuf;
     103    tr_list                * output_datatypes; /* struct tr_datatype */
     104
     105    tr_can_read_cb           canRead;
     106    tr_did_write_cb          didWrite;
     107    tr_net_error_cb          gotError;
     108    void *                   userData;
     109
     110    size_t                   bufferSize[2];
     111
     112    tr_bandwidth           * bandwidth;
     113    tr_crypto              * crypto;
    111114};
    112 
    113 /**
    114 ***
    115 **/
    116 
    117 static void
    118 adjustOutputBuffer( tr_peerIo * io )
    119 {
    120     struct evbuffer * live = EVBUFFER_OUTPUT( io->bufev );
    121 
    122     if( io->bandwidth[TR_UP].isUnlimited )
    123     {
    124         bufferevent_write_buffer( io->bufev, io->output );
    125     }
    126     else if( io->bandwidth[TR_UP].bytesLeft > EVBUFFER_LENGTH( live ) )
    127     {
    128         /* there's free space in bufev's output buffer;
    129            try to fill it up */
    130         const size_t desiredLength = io->bandwidth[TR_UP].bytesLeft;
    131         const size_t under = desiredLength - EVBUFFER_LENGTH( live );
    132         const size_t n = MIN( under, EVBUFFER_LENGTH( io->output ) );
    133         bufferevent_write( io->bufev, EVBUFFER_DATA( io->output ), n );
    134         evbuffer_drain( io->output, n );
    135     }
    136     else if( io->bandwidth[TR_UP].bytesLeft < EVBUFFER_LENGTH( live ) )
    137     {
    138         /* bufev's output buffer exceeds our bandwidth allocation;
    139            move the excess out of bufev so it can't be sent yet */
    140         const size_t      desiredLength = io->bandwidth[TR_UP].bytesLeft;
    141         const size_t      over = EVBUFFER_LENGTH( live ) - desiredLength;
    142         struct evbuffer * buf = evbuffer_new( );
    143         evbuffer_add( buf, EVBUFFER_DATA( live ) + desiredLength, over );
    144         evbuffer_add_buffer( buf, io->output );
    145         evbuffer_free( io->output );
    146         io->output = buf;
    147         EVBUFFER_LENGTH( live ) = desiredLength;
    148     }
    149     else if( EVBUFFER_LENGTH( live ) )
    150     {
    151         bufferevent_enable( io->bufev, EV_WRITE );
    152     }
    153 
    154     io->bufferSize[TR_UP] = EVBUFFER_LENGTH( live );
    155 
    156     dbgmsg( io, "after adjusting the output buffer, its size is now %zu",
    157             io->bufferSize[TR_UP] );
    158 }
    159 
    160 static void
    161 adjustInputBuffer( tr_peerIo * io )
    162 {
    163     if( io->bandwidth[TR_DOWN].isUnlimited )
    164     {
    165         dbgmsg( io, "unlimited reading..." );
    166         bufferevent_setwatermark( io->bufev, EV_READ, 0, 0 );
    167         bufferevent_enable( io->bufev, EV_READ );
    168     }
    169     else
    170     {
    171         const size_t n = io->bandwidth[TR_DOWN].bytesLeft;
    172         if( n == 0 )
    173         {
    174             dbgmsg( io, "disabling reads because we've hit our limit" );
    175             bufferevent_disable( io->bufev, EV_READ );
    176         }
    177         else
    178         {
    179             dbgmsg( io, "enabling reading of %zu more bytes", n );
    180             bufferevent_setwatermark( io->bufev, EV_READ, 0, n );
    181             bufferevent_enable( io->bufev, EV_READ );
    182         }
    183     }
    184 }
    185115
    186116/***
     
    189119
    190120static void
    191 didWriteWrapper( struct bufferevent * e,
    192                  void *               vio )
     121didWriteWrapper( struct tr_iobuf  * iobuf,
     122                 size_t             bytes_transferred,
     123                 void             * vio )
    193124{
    194125    tr_peerIo *  io = vio;
    195     const size_t len = EVBUFFER_LENGTH( EVBUFFER_OUTPUT( e ) );
    196 
    197     dbgmsg( io, "didWrite... io->outputBufferSize was %zu, is now %zu",
    198             io->bufferSize[TR_UP], len );
    199 
    200     if( len < io->bufferSize[TR_UP] )
     126
     127    while( bytes_transferred )
    201128    {
    202         const size_t payload = io->bufferSize[TR_UP] - len;
    203         const size_t n = addPacketOverhead( payload );
    204         struct tr_bandwidth * b = &io->bandwidth[TR_UP];
    205         b->bytesLeft -= MIN( b->bytesLeft, (size_t)n );
    206         b->bytesUsed += n;
    207         tr_rcTransferred( io->session->rawSpeed[TR_UP], n );
    208         dbgmsg( io,
    209                 "wrote %zu bytes to peer... upload bytesLeft is now %zu",
    210                 n,
    211                 b->bytesLeft );
     129        struct tr_datatype * next = io->output_datatypes->data;
     130        const size_t payload = MIN( next->length, bytes_transferred );
     131        const size_t overhead = getPacketOverhead( payload );
     132
     133        tr_bandwidthUsed( io->bandwidth, TR_UP, payload, next->isPieceData );
     134
     135        if( overhead > 0 )
     136            tr_bandwidthUsed( io->bandwidth, TR_UP, overhead, FALSE );
     137
     138        if( io->didWrite )
     139            io->didWrite( io, payload, next->isPieceData, io->userData );
     140
     141        bytes_transferred -= payload;
     142        next->length -= payload;
     143        if( !next->length )
     144            tr_free( tr_list_pop_front( &io->output_datatypes ) );
    212145    }
    213146
    214     adjustOutputBuffer( io );
    215 
    216     if( io->didWrite )
    217         io->didWrite( e, io->userData );
     147    if( EVBUFFER_LENGTH( tr_iobuf_output( iobuf ) ) )
     148        tr_iobuf_enable( io->iobuf, EV_WRITE );
    218149}
    219150
    220151static void
    221 canReadWrapper( struct bufferevent * e,
    222                 void *               vio )
     152canReadWrapper( struct tr_iobuf  * iobuf,
     153                size_t             bytes_transferred UNUSED,
     154                void              * vio )
    223155{
    224156    int          done = 0;
     
    226158    tr_peerIo *  io = vio;
    227159    tr_session * session = io->session;
    228     const size_t len = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
    229160
    230161    dbgmsg( io, "canRead" );
    231 
    232     /* if the input buffer has grown, record the bytes that were read */
    233     if( len > io->bufferSize[TR_DOWN] )
    234     {
    235         const size_t payload = len - io->bufferSize[TR_DOWN];
    236         const size_t n = addPacketOverhead( payload );
    237         struct tr_bandwidth * b = io->bandwidth + TR_DOWN;
    238         b->bytesLeft -= MIN( b->bytesLeft, (size_t)n );
    239         b->bytesUsed += n;
    240         tr_rcTransferred( io->session->rawSpeed[TR_DOWN], n );
    241         dbgmsg( io,
    242                 "%zu new input bytes. bytesUsed is %zu, bytesLeft is %zu",
    243                 n, b->bytesUsed,
    244                 b->bytesLeft );
    245 
    246         adjustInputBuffer( io );
    247     }
    248162
    249163    /* try to consume the input buffer */
     
    254168        while( !done && !err )
    255169        {
    256             const int ret = io->canRead( e, io->userData );
     170            size_t piece = 0;
     171            const size_t oldLen = EVBUFFER_LENGTH( tr_iobuf_input( iobuf ) );
     172            const int ret = io->canRead( iobuf, io->userData, &piece );
     173
     174            if( ret != READ_ERR )
     175            {
     176                const size_t used = oldLen - EVBUFFER_LENGTH( tr_iobuf_input( iobuf ) );
     177                if( piece )
     178                    tr_bandwidthUsed( io->bandwidth, TR_DOWN, piece, TRUE );
     179                if( used != piece )
     180                    tr_bandwidthUsed( io->bandwidth, TR_DOWN, used - piece, FALSE );
     181            }
    257182
    258183            switch( ret )
    259184            {
    260185                case READ_NOW:
    261                     if( EVBUFFER_LENGTH( e->input ) )
     186                    if( EVBUFFER_LENGTH( tr_iobuf_input( iobuf )))
    262187                        continue;
    263188                    done = 1;
     
    276201        tr_globalUnlock( session );
    277202    }
    278 
    279     if( !err )
    280         io->bufferSize[TR_DOWN] = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
    281203}
    282204
    283205static void
    284 gotErrorWrapper( struct bufferevent * e,
    285                  short                what,
    286                  void *              userData )
     206gotErrorWrapper( struct tr_iobuf  * iobuf,
     207                 short              what,
     208                 void             * userData )
    287209{
    288210    tr_peerIo * c = userData;
    289211
    290212    if( c->gotError )
    291         c->gotError( e, what, c->userData );
     213        c->gotError( iobuf, what, c->userData );
    292214}
    293215
     
    299221bufevNew( tr_peerIo * io )
    300222{
    301     io->bufev = bufferevent_new( io->socket,
    302                                  canReadWrapper,
    303                                  didWriteWrapper,
    304                                  gotErrorWrapper,
    305                                  io );
    306 
    307     /* tell libevent to call didWriteWrapper after every write,
    308      * not just when the write buffer is empty */
    309     bufferevent_setwatermark( io->bufev, EV_WRITE, INT_MAX, 0 );
    310 
    311     bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
    312 
    313     bufferevent_enable( io->bufev, EV_READ | EV_WRITE );
     223    io->iobuf = tr_iobuf_new( io->session,
     224                              io->bandwidth,
     225                              io->socket,
     226                              EV_READ | EV_WRITE,
     227                              canReadWrapper,
     228                              didWriteWrapper,
     229                              gotErrorWrapper,
     230                              io );
     231
     232    tr_iobuf_settimeout( io->iobuf, io->timeout, io->timeout );
     233}
     234
     235static int
     236isPeerIo( const tr_peerIo * io )
     237{
     238    return ( io != NULL ) && ( io->magicNumber == MAGIC_NUMBER );
    314239}
    315240
     
    328253
    329254    io = tr_new0( tr_peerIo, 1 );
     255    io->magicNumber = MAGIC_NUMBER;
    330256    io->crypto = tr_cryptoNew( torrentHash, isIncoming );
    331257    io->session = session;
     
    336262    io->timeout = IO_TIMEOUT_SECS;
    337263    io->timeCreated = time( NULL );
    338     io->output = evbuffer_new( );
    339     io->bandwidth[TR_UP].isUnlimited = 1;
    340     io->bandwidth[TR_DOWN].isUnlimited = 1;
    341264    bufevNew( io );
     265    tr_peerIoSetBandwidth( io, session->bandwidth );
    342266    return io;
    343267}
     
    371295    assert( torrentHash );
    372296
    373     socket = tr_netOpenTCP( in_addr, port );
     297    socket = tr_netOpenTCP( session, in_addr, port );
    374298
    375299    return socket < 0
     
    383307    tr_peerIo * io = vio;
    384308
    385     evbuffer_free( io->output );
    386     bufferevent_free( io->bufev );
     309    tr_peerIoSetBandwidth( io, NULL );
     310    tr_iobuf_free( io->iobuf );
    387311    tr_netClose( io->socket );
    388312    tr_cryptoFree( io->crypto );
     313    tr_list_free( &io->output_datatypes, tr_free );
     314
     315    io->magicNumber = 0xDEAD;
    389316    tr_free( io );
    390317}
     
    405332tr_peerIoGetSession( tr_peerIo * io )
    406333{
    407     assert( io );
     334    assert( isPeerIo( io ) );
    408335    assert( io->session );
    409336
     
    415342                           uint16_t * port )
    416343{
    417     assert( io );
     344    assert( isPeerIo( io ) );
    418345
    419346    if( port )
     
    443370tr_peerIoTryRead( tr_peerIo * io )
    444371{
    445     if( EVBUFFER_LENGTH( io->bufev->input ) )
    446         canReadWrapper( io->bufev, io );
     372    if( EVBUFFER_LENGTH( tr_iobuf_input( io->iobuf )))
     373        (*canReadWrapper)( io->iobuf, ~0, io );
    447374}
    448375
     
    476403        tr_netClose( io->socket );
    477404
    478     io->socket = tr_netOpenTCP( &io->in_addr, io->port );
     405    io->socket = tr_netOpenTCP( io->session, &io->in_addr, io->port );
    479406
    480407    if( io->socket >= 0 )
    481408    {
     409        tr_bandwidth * bandwidth = io->bandwidth;
     410        tr_peerIoSetBandwidth( io, NULL );
     411
    482412        tr_netSetTOS( io->socket, io->session->peerSocketTOS );
    483 
    484         bufferevent_free( io->bufev );
     413        tr_iobuf_free( io->iobuf );
    485414        bufevNew( io );
     415
     416        tr_peerIoSetBandwidth( io, bandwidth );
    486417        return 0;
    487418    }
     
    495426{
    496427    io->timeout = secs;
    497     bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
    498     bufferevent_enable( io->bufev, EV_READ | EV_WRITE );
     428    tr_iobuf_settimeout( io->iobuf, io->timeout, io->timeout );
     429    tr_iobuf_enable( io->iobuf, EV_READ | EV_WRITE );
    499430}
    500431
     
    507438                         const uint8_t * hash )
    508439{
    509     assert( io );
     440    assert( isPeerIo( io ) );
    510441
    511442    tr_cryptoSetTorrentHash( io->crypto, hash );
     
    515446tr_peerIoGetTorrentHash( tr_peerIo * io )
    516447{
    517     assert( io );
     448    assert( isPeerIo( io ) );
    518449    assert( io->crypto );
    519450
     
    524455tr_peerIoHasTorrentHash( const tr_peerIo * io )
    525456{
    526     assert( io );
     457    assert( isPeerIo( io ) );
    527458    assert( io->crypto );
    528459
     
    538469                     const uint8_t * peer_id )
    539470{
    540     assert( io );
     471    assert( isPeerIo( io ) );
    541472
    542473    if( ( io->peerIdIsSet = peer_id != NULL ) )
     
    549480tr_peerIoGetPeersId( const tr_peerIo * io )
    550481{
    551     assert( io );
     482    assert( isPeerIo( io ) );
    552483    assert( io->peerIdIsSet );
    553484
     
    563494                     int         flag )
    564495{
    565     assert( io );
     496    assert( isPeerIo( io ) );
    566497    assert( flag == 0 || flag == 1 );
    567498
     
    573504                     int         flag )
    574505{
    575     assert( io );
     506    assert( isPeerIo( io ) );
    576507    assert( flag == 0 || flag == 1 );
    577508
     
    582513tr_peerIoSupportsLTEP( const tr_peerIo * io )
    583514{
    584     assert( io );
     515    assert( isPeerIo( io ) );
    585516
    586517    return io->extendedProtocolSupported;
     
    590521tr_peerIoSupportsFEXT( const tr_peerIo * io )
    591522{
    592     assert( io );
     523    assert( isPeerIo( io ) );
    593524
    594525    return io->fastPeersSupported;
     
    599530**/
    600531
    601 size_t
    602 tr_peerIoGetBandwidthUsed( const tr_peerIo * io,
    603                            tr_direction      direction )
    604 {
    605     assert( io );
    606     assert( direction == TR_UP || direction == TR_DOWN );
    607     return io->bandwidth[direction].bytesUsed;
     532static size_t
     533getDesiredOutputBufferSize( const tr_peerIo * io )
     534{
     535    /* this is all kind of arbitrary, but what seems to work well is
     536     * being large enough to hold the next 15 seconds' worth of input,
     537     * or two and a half blocks, whichever is bigger.
     538     * It's okay to tweak this as needed */
     539    const double maxBlockSize = 16 * 1024; /* 16 KiB is from BT spec */
     540    const double currentSpeed = tr_bandwidthGetPieceSpeed( io->bandwidth, TR_UP );
     541    const double period = 20; /* arbitrary */
     542    return MAX( maxBlockSize*2.5, currentSpeed*1024*period );
    608543}
    609544
     
    611546tr_peerIoGetWriteBufferSpace( const tr_peerIo * io )
    612547{
    613     const size_t desiredBufferLen = 4096;
    614     const size_t currentLiveLen = EVBUFFER_LENGTH( EVBUFFER_OUTPUT( io->bufev ) );
    615 
    616     const size_t currentLbufLen = EVBUFFER_LENGTH( io->output );
    617     const size_t desiredLiveLen = io->bandwidth[TR_UP].isUnlimited
    618                                 ? INT_MAX
    619                                 : io->bandwidth[TR_UP].bytesLeft;
    620 
    621     const size_t currentLen = currentLiveLen + currentLbufLen;
    622     const size_t desiredLen = desiredBufferLen + desiredLiveLen;
    623 
    624     size_t       freeSpace = 0;
     548    const size_t desiredLen = getDesiredOutputBufferSize( io );
     549    const size_t currentLen = EVBUFFER_LENGTH( tr_iobuf_output( io->iobuf ) );
     550    size_t freeSpace = 0;
    625551
    626552    if( desiredLen > currentLen )
    627553        freeSpace = desiredLen - currentLen;
    628     else
    629         freeSpace = 0;
    630554
    631555    return freeSpace;
     
    633557
    634558void
    635 tr_peerIoSetBandwidth( tr_peerIo *  io,
    636                        tr_direction direction,
    637                        size_t       bytesLeft )
    638 {
    639     struct tr_bandwidth * b;
    640 
    641     assert( io );
    642     assert( direction == TR_UP || direction == TR_DOWN );
    643 
    644     b = io->bandwidth + direction;
    645     b->isUnlimited = 0;
    646     b->bytesUsed = 0;
    647     b->bytesLeft = bytesLeft;
    648 
    649     adjustOutputBuffer( io );
    650     adjustInputBuffer( io );
    651 }
    652 
    653 void
    654 tr_peerIoSetBandwidthUnlimited( tr_peerIo *  io,
    655                                 tr_direction direction )
    656 {
    657     struct tr_bandwidth * b;
    658 
    659     assert( io );
    660     assert( direction == TR_UP || direction == TR_DOWN );
    661 
    662     b = io->bandwidth + direction;
    663     b->isUnlimited = 1;
    664     b->bytesUsed = 0;
    665     b->bytesLeft = 0;
    666 
    667     adjustInputBuffer( io );
    668     adjustOutputBuffer( io );
     559tr_peerIoSetBandwidth( tr_peerIo     * io,
     560                       tr_bandwidth  * bandwidth )
     561{
     562    assert( isPeerIo( io ) );
     563
     564    if( io->bandwidth )
     565        tr_bandwidthRemoveBuffer( io->bandwidth, io->iobuf );
     566
     567    io->bandwidth = bandwidth;
     568    tr_iobuf_set_bandwidth( io->iobuf, bandwidth );
     569
     570    if( io->bandwidth )
     571        tr_bandwidthAddBuffer( io->bandwidth, io->iobuf );
     572
     573    tr_iobuf_enable( io->iobuf, EV_READ | EV_WRITE );
    669574}
    670575
     
    683588                        int         encryptionMode )
    684589{
    685     assert( io );
     590    assert( isPeerIo( io ) );
    686591    assert( encryptionMode == PEER_ENCRYPTION_NONE
    687592          || encryptionMode == PEER_ENCRYPTION_RC4 );
     
    700605**/
    701606
    702 int
    703 tr_peerIoWantsBandwidth( const tr_peerIo * io,
    704                          tr_direction      direction )
    705 {
    706     assert( direction == TR_UP || direction == TR_DOWN );
    707 
    708     if( direction == TR_DOWN )
    709     {
    710         return TRUE; /* FIXME -- is there a good way to test for this? */
    711     }
    712     else
    713     {
    714         return EVBUFFER_LENGTH( EVBUFFER_OUTPUT( io->bufev ) )
    715                || EVBUFFER_LENGTH( io->output );
    716     }
    717 }
    718 
    719 void
    720 tr_peerIoWrite( tr_peerIo *  io,
    721                 const void * writeme,
    722                 size_t       writemeLen )
    723 {
     607void
     608tr_peerIoWrite( tr_peerIo   * io,
     609                const void  * writeme,
     610                size_t        writemeLen,
     611                int           isPieceData )
     612{
     613    struct tr_datatype * datatype;
    724614    assert( tr_amInEventThread( io->session ) );
    725615    dbgmsg( io, "adding %zu bytes into io->output", writemeLen );
    726616
    727     if( io->bandwidth[TR_UP].isUnlimited )
    728         bufferevent_write( io->bufev, writeme, writemeLen );
    729     else
    730         evbuffer_add( io->output, writeme, writemeLen );
    731 
    732     adjustOutputBuffer( io );
    733 }
    734 
    735 void
    736 tr_peerIoWriteBuf( tr_peerIo *       io,
    737                    struct evbuffer * buf )
     617    datatype = tr_new( struct tr_datatype, 1 );
     618    datatype->isPieceData = isPieceData != 0;
     619    datatype->length = writemeLen;
     620    tr_list_append( &io->output_datatypes, datatype );
     621
     622    evbuffer_add( tr_iobuf_output( io->iobuf ), writeme, writemeLen );
     623    tr_iobuf_enable( io->iobuf, EV_WRITE );
     624}
     625
     626void
     627tr_peerIoWriteBuf( tr_peerIo         * io,
     628                   struct evbuffer   * buf,
     629                   int                 isPieceData )
    738630{
    739631    const size_t n = EVBUFFER_LENGTH( buf );
    740632
    741     tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n );
     633    tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n, isPieceData );
    742634    evbuffer_drain( buf, n );
    743635}
     
    875767    return time( NULL ) - io->timeCreated;
    876768}
    877 
  • branches/1.4x/libtransmission/peer-io.h

    r7055 r7176  
    1111 */
    1212
     13#ifndef __TRANSMISSION__
     14#error only libtransmission should #include this header.
     15#endif
     16
    1317#ifndef TR_PEER_IO_H
    1418#define TR_PEER_IO_H
     
    2024struct in_addr;
    2125struct evbuffer;
    22 struct bufferevent;
    23 struct tr_handle;
     26struct tr_bandwidth;
    2427struct tr_crypto;
     28struct tr_iobuf;
    2529typedef struct tr_peerIo tr_peerIo;
    2630
     
    2933**/
    3034
    31 tr_peerIo*           tr_peerIoNewOutgoing(
    32     struct tr_handle *     session,
    33     const struct in_addr * addr,
    34     int                    port,
    35     const  uint8_t *
    36                            torrentHash );
    37 
    38 tr_peerIo*           tr_peerIoNewIncoming( struct tr_handle *     session,
     35tr_peerIo*           tr_peerIoNewOutgoing( struct tr_handle     * session,
     36                                           const struct in_addr * addr,
     37                                           int                    port,
     38                                           const  uint8_t       * torrentHash );
     39
     40tr_peerIo*           tr_peerIoNewIncoming( struct tr_handle     * session,
    3941                                           const struct in_addr * addr,
    4042                                           uint16_t               port,
     
    109111ReadState;
    110112
    111 typedef ReadState ( *tr_can_read_cb )( struct bufferevent*, void* user_data );
    112 typedef void ( *tr_did_write_cb )( struct bufferevent *, void * );
    113 typedef void ( *tr_net_error_cb )( struct bufferevent *, short what, void * );
    114 
    115 void              tr_peerIoSetIOFuncs( tr_peerIo *     io,
    116                                        tr_can_read_cb  readcb,
    117                                        tr_did_write_cb writecb,
    118                                        tr_net_error_cb errcb,
    119                                        void *          user_data );
    120 
    121 int               tr_peerIoWantsBandwidth( const tr_peerIo * io,
    122                                                              tr_direction );
    123 
    124 #if 0
    125 void              tr_peerIoTryRead( tr_peerIo * io );
    126 
    127 #endif
    128 
    129 void              tr_peerIoWrite( tr_peerIo *  io,
    130                                   const void * writeme,
    131                                   size_t       writemeLen );
    132 
    133 void              tr_peerIoWriteBuf( tr_peerIo *       io,
    134                                      struct evbuffer * buf );
    135 
     113typedef ReadState ( *tr_can_read_cb  )( struct tr_iobuf  * iobuf,
     114                                        void             * user_data,
     115                                        size_t           * setme_piece_byte_count );
     116
     117typedef void      ( *tr_did_write_cb )( tr_peerIo        * io,
     118                                        size_t             bytesWritten,
     119                                        int                wasPieceData,
     120                                        void             * userData );
     121
     122typedef void      ( *tr_net_error_cb )( struct tr_iobuf  * ev,
     123                                        short              what,
     124                                        void             * userData );
     125
     126void    tr_peerIoSetIOFuncs      ( tr_peerIo        * io,
     127                                   tr_can_read_cb     readcb,
     128                                   tr_did_write_cb    writecb,
     129                                   tr_net_error_cb    errcb,
     130                                   void             * user_data );
     131
     132/**
     133***
     134**/
     135
     136void    tr_peerIoWrite          ( tr_peerIo         * io,
     137                                  const void        * writeme,
     138                                  size_t              writemeLen,
     139                                  int                 isPieceData );
     140
     141void    tr_peerIoWriteBuf       ( tr_peerIo         * io,
     142                                  struct evbuffer   * buf,
     143                                  int                 isPieceData );
    136144
    137145/**
     
    196204**/
    197205
    198 size_t            tr_peerIoGetBandwidthUsed( const tr_peerIo * io,
    199                                              tr_direction      direction );
    200 
    201206size_t            tr_peerIoGetWriteBufferSpace( const tr_peerIo * io );
    202207
    203 void              tr_peerIoSetBandwidth( tr_peerIo *  io,
    204                                          tr_direction direction,
    205                                          size_t       bytesLeft );
    206 
    207 void              tr_peerIoSetBandwidthUnlimited( tr_peerIo *  io,
    208                                                   tr_direction direction );
     208void              tr_peerIoSetBandwidth( tr_peerIo            * io,
     209                                         struct tr_bandwidth  * bandwidth );
     210
     211void              tr_peerIoBandwidthUsed( tr_peerIo           * io,
     212                                          tr_direction          direction,
     213                                          size_t                byteCount,
     214                                          int                   isPieceData );
     215
    209216
    210217
  • branches/1.4x/libtransmission/peer-mgr-private.h

    r7055 r7176  
    1010 * $Id$
    1111 */
     12
     13#ifndef __TRANSMISSION__
     14#error only libtransmission should #include this header.
     15#endif
    1216
    1317#ifndef TR_PEER_MGR_PRIVATE_H
     
    2428#include "publish.h" /* tr_publisher_tag */
    2529
     30struct tr_bandwidth;
    2631struct tr_bitfield;
    2732struct tr_peerIo;
    2833struct tr_peermsgs;
    29 struct tr_ratecontrol;
    3034
    3135enum
     
    3842typedef struct tr_peer
    3943{
    40     unsigned int             peerIsChoked       : 1;
    41     unsigned int             peerIsInterested   : 1;
    42     unsigned int             clientIsChoked     : 1;
    43     unsigned int             clientIsInterested : 1;
    44     unsigned int             doPurge            : 1;
     44    tr_bool                  peerIsChoked;
     45    tr_bool                  peerIsInterested;
     46    tr_bool                  clientIsChoked;
     47    tr_bool                  clientIsInterested;
     48    tr_bool                  doPurge;
    4549
    4650    /* number of bad pieces they've contributed to */
     
    6872    tr_publisher_tag         msgsTag;
    6973
    70     /* the rate at which pieces are being transferred between client and peer.
    71      * protocol overhead is NOT included; this is only the piece data */
    72     struct tr_ratecontrol  * pieceSpeed[2];
     74    struct tr_bandwidth    * bandwidth;
    7375}
    7476tr_peer;
  • branches/1.4x/libtransmission/peer-mgr.c

    r7116 r7176  
    2020
    2121#include "transmission.h"
     22#include "bandwidth.h"
     23#include "bencode.h"
    2224#include "blocklist.h"
    2325#include "clients.h"
     
    3234#include "peer-msgs.h"
    3335#include "ptrarray.h"
    34 #include "ratecontrol.h"
    3536#include "stats.h" /* tr_statsAddUploaded, tr_statsAddDownloaded */
    3637#include "torrent.h"
     
    6061
    6162    /* max # of peers to ask fer per torrent per reconnect pulse */
    62     MAX_RECONNECTIONS_PER_PULSE = 2,
     63    MAX_RECONNECTIONS_PER_PULSE = 4,
    6364
    6465    /* max number of peers to ask for per second overall.
    6566    * this throttle is to avoid overloading the router */
    66     MAX_CONNECTIONS_PER_SECOND = 4,
     67    MAX_CONNECTIONS_PER_SECOND = 8,
    6768
    6869    /* number of unchoked peers per torrent.
    6970     * FIXME: this probably ought to be configurable */
    70     MAX_UNCHOKED_PEERS = 12,
     71    MAX_UNCHOKED_PEERS = 14,
    7172
    7273    /* number of bad pieces a peer is allowed to send before we ban them */
    73     MAX_BAD_PIECES_PER_PEER = 3,
     74    MAX_BAD_PIECES_PER_PEER = 5,
    7475
    7576    /* use for bitwise operations w/peer_atom.myflags */
     
    107108typedef struct
    108109{
    109     unsigned int    isRunning : 1;
     110    tr_bool         isRunning;
    110111
    111112    uint8_t         hash[SHA_DIGEST_LENGTH];
     
    131132    tr_ptrArray     * incomingHandshakes; /* tr_handshake */
    132133    tr_timer        * bandwidthTimer;
    133     tr_ratecontrol  * globalPoolRawSpeed[2];
    134134};
    135135
     
    323323
    324324static tr_peer*
    325 peerConstructor( const struct in_addr * in_addr )
     325peerConstructor( tr_torrent * tor, const struct in_addr * in_addr )
    326326{
    327327    tr_peer * p;
     
    329329    p = tr_new0( tr_peer, 1 );
    330330    memcpy( &p->in_addr, in_addr, sizeof( struct in_addr ) );
    331     p->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    332     p->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
     331    p->bandwidth = tr_bandwidthNew( tor->session, tor->bandwidth );
    333332    return p;
    334333}
     
    346345    if( peer == NULL )
    347346    {
    348         peer = peerConstructor( in_addr );
     347        peer = peerConstructor( torrent->tor, in_addr );
    349348        tr_ptrArrayInsertSorted( torrent->peers, peer, peerCompare );
    350349    }
     
    368367    tr_free( peer->client );
    369368
    370     tr_rcClose( peer->pieceSpeed[TR_CLIENT_TO_PEER] );
    371     tr_rcClose( peer->pieceSpeed[TR_PEER_TO_CLIENT] );
     369    tr_bandwidthFree( peer->bandwidth );
     370
    372371    tr_free( peer );
    373372}
     
    517516    m->torrents = tr_ptrArrayNew( );
    518517    m->incomingHandshakes = tr_ptrArrayNew( );
    519     m->globalPoolRawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    520     m->globalPoolRawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    521518    m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC );
    522519    return m;
     
    529526
    530527    tr_timerFree( &manager->bandwidthTimer );
    531     tr_rcClose( manager->globalPoolRawSpeed[TR_CLIENT_TO_PEER] );
    532     tr_rcClose( manager->globalPoolRawSpeed[TR_PEER_TO_CLIENT] );
    533528
    534529    /* free the handshakes.  Abort invokes handshakeDoneCB(), which removes
     
    10171012            const time_t now = time( NULL );
    10181013            tr_torrent * tor = t->tor;
     1014
    10191015            tor->activityDate = now;
    1020             tor->uploadedCur += e->length;
    1021             if( peer )
    1022                 tr_rcTransferred ( peer->pieceSpeed[TR_CLIENT_TO_PEER], e->length );
    1023             tr_rcTransferred ( tor->pieceSpeed[TR_CLIENT_TO_PEER], e->length );
    1024             tr_rcTransferred ( tor->session->pieceSpeed[TR_CLIENT_TO_PEER], e->length );
    1025             tr_statsAddUploaded( tor->session, e->length );
    1026             if( peer )
    1027             {
     1016
     1017            if( e->wasPieceData )
     1018                tor->uploadedCur += e->length;
     1019
     1020            /* update the stats */
     1021            if( e->wasPieceData )
     1022                tr_statsAddUploaded( tor->session, e->length );
     1023
     1024            /* update our atom */
     1025            if( peer ) {
    10281026                struct peer_atom * a = getExistingAtom( t, &peer->in_addr );
    10291027                a->piece_data_time = now;
    10301028            }
     1029
    10311030            break;
    10321031        }
     
    10361035            const time_t now = time( NULL );
    10371036            tr_torrent * tor = t->tor;
     1037
    10381038            tor->activityDate = now;
    1039             tr_statsAddDownloaded( tor->session, e->length );
    1040             if( peer )
    1041                 tr_rcTransferred ( peer->pieceSpeed[TR_PEER_TO_CLIENT], e->length );
    1042             tr_rcTransferred ( tor->pieceSpeed[TR_PEER_TO_CLIENT], e->length );
    1043             tr_rcTransferred ( tor->session->pieceSpeed[TR_PEER_TO_CLIENT], e->length );
     1039
    10441040            /* only add this to downloadedCur if we got it from a peer --
    10451041             * webseeds shouldn't count against our ratio.  As one tracker
     
    10481044             * to manage the swarms, not the web server and does not fit
    10491045             * into the jurisdiction of the tracker." */
    1050             if( peer )
     1046            if( peer && e->wasPieceData )
    10511047                tor->downloadedCur += e->length;
     1048
     1049            /* update the stats */
     1050            if( e->wasPieceData )
     1051                tr_statsAddDownloaded( tor->session, e->length );
     1052
     1053            /* update our atom */
    10521054            if( peer ) {
    10531055                struct peer_atom * a = getExistingAtom( t, &peer->in_addr );
    10541056                a->piece_data_time = now;
    10551057            }
     1058
    10561059            break;
    10571060        }
     
    12761279                if( !peer_id )
    12771280                    peer->client = NULL;
    1278                 else
    1279                 {
     1281                else {
    12801282                    char client[128];
    12811283                    tr_clientForId( client, sizeof( client ), peer_id );
    12821284                    peer->client = tr_strdup( client );
    12831285                }
     1286
    12841287                peer->port = port;
    12851288                peer->io = io;
    1286                 peer->msgs =
    1287                     tr_peerMsgsNew( t->tor, peer, peerCallbackFunc, t,
    1288                                     &peer->msgsTag );
     1289                peer->msgs = tr_peerMsgsNew( t->tor, peer, peerCallbackFunc, t, &peer->msgsTag );
     1290                tr_peerIoSetBandwidth( io, peer->bandwidth );
    12891291
    12901292                success = TRUE;
     
    17681770    assert( direction==TR_CLIENT_TO_PEER || direction==TR_PEER_TO_CLIENT );
    17691771
    1770     return tr_rcRate( peer->pieceSpeed[direction] );
     1772    return tr_bandwidthGetPieceSpeed( peer->bandwidth, direction );
    17711773}
    17721774
     
    17991801        tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ),
    18001802                   sizeof( stat->client ) );
    1801         stat->port               = peer->port;
     1803        stat->port               = ntohs( peer->port );
    18021804        stat->from               = atom->from;
    18031805        stat->progress           = peer->progress;
     
    18411843struct ChokeData
    18421844{
    1843     unsigned int    doUnchoke    : 1;
    1844     unsigned int    isInterested : 1;
    1845     unsigned int    isChoked     : 1;
     1845    tr_bool         doUnchoke;
     1846    tr_bool         isInterested;
     1847    tr_bool         isChoked;
    18461848    int             rate;
    18471849    tr_peer *       peer;
     
    19031905            n->isInterested = peer->peerIsInterested;
    19041906            n->isChoked     = peer->peerIsChoked;
    1905             n->rate = (int)(tr_peerGetPieceSpeed( peer, TR_CLIENT_TO_PEER )
    1906                             + tr_peerGetPieceSpeed( peer, TR_PEER_TO_CLIENT ) );
     1907            n->rate         = tr_peerGetPieceSpeed( peer, TR_CLIENT_TO_PEER ) * 1024;
    19071908        }
    19081909    }
     
    23212322****/
    23222323
    2323 static double
    2324 allocateHowMuch( double                  desired_average_kb_per_sec,
    2325                  const tr_ratecontrol  * ratecontrol )
    2326 {
    2327     const int pulses_per_history = TR_RATECONTROL_HISTORY_MSEC / BANDWIDTH_PERIOD_MSEC;
    2328     const double seconds_per_pulse = BANDWIDTH_PERIOD_MSEC / 1000.0;
    2329     const double baseline_bytes_per_pulse = desired_average_kb_per_sec * 1024.0 * seconds_per_pulse;
    2330     const double min = baseline_bytes_per_pulse * 0.80;
    2331     const double max = baseline_bytes_per_pulse * 1.10;
    2332     const double current_bytes_per_pulse = tr_rcRate( ratecontrol ) * 1024.0 * seconds_per_pulse;
    2333     const double next_pulse_bytes = baseline_bytes_per_pulse * ( pulses_per_history + 1 )
    2334                                   - ( current_bytes_per_pulse * pulses_per_history );
    2335     double clamped;
    2336 
    2337     /* clamp the return value to lessen oscillation */
    2338     clamped = next_pulse_bytes;
    2339     clamped = MAX( clamped, min );
    2340     clamped = MIN( clamped, max );
    2341 
    2342 #if 0
    2343 fprintf( stderr, "desiredAvgKB is %5.2f, rate is %5.2f, allocating %5.2f (%5.2f)\n",
    2344          desired_average_kb_per_sec,
    2345          tr_rcRate( ratecontrol ),
    2346          clamped/1024.0,
    2347          next_pulse_bytes/1024.0 );
    2348 #endif
    2349 
    2350     return clamped;
    2351 }
    2352 
    2353 /**
    2354  * Distributes a fixed amount of bandwidth among a set of peers.
    2355  *
    2356  * @param peerArray peers whose client-to-peer bandwidth will be set
    2357  * @param direction whether to allocate upload or download bandwidth
    2358  * @param history recent bandwidth history for these peers
    2359  * @param desiredAvgKB overall bandwidth goal for this set of peers
    2360  */
    2361 static void
    2362 setPeerBandwidth( tr_ptrArray          * peerArray,
    2363                   const tr_direction     direction,
    2364                   const tr_ratecontrol * ratecontrol,
    2365                   double                 desiredAvgKB )
    2366 {
    2367     const int    peerCount = tr_ptrArraySize( peerArray );
    2368     const double bytes = allocateHowMuch( desiredAvgKB, ratecontrol );
    2369     const double welfareBytes = MIN( 2048, bytes * 0.2 );
    2370     const double meritBytes = MAX( 0, bytes - welfareBytes );
    2371     tr_peer **   peers = (tr_peer**) tr_ptrArrayBase( peerArray );
    2372     tr_peer **   candidates = tr_new( tr_peer *, peerCount );
    2373     int          i;
    2374     int          candidateCount;
    2375     double       welfare;
    2376     size_t       bytesUsed;
    2377 
    2378     assert( meritBytes >= 0.0 );
    2379     assert( welfareBytes >= 0.0 );
    2380     assert( direction == TR_UP || direction == TR_DOWN );
    2381 
    2382     for( i = candidateCount = 0; i < peerCount; ++i )
    2383         if( tr_peerIoWantsBandwidth( peers[i]->io, direction ) )
    2384             candidates[candidateCount++] = peers[i];
    2385         else
    2386             tr_peerIoSetBandwidth( peers[i]->io, direction, 0 );
    2387 
    2388     for( i = bytesUsed = 0; i < candidateCount; ++i )
    2389         bytesUsed += tr_peerIoGetBandwidthUsed( candidates[i]->io,
    2390                                                 direction );
    2391 
    2392     welfare = welfareBytes / candidateCount;
    2393 
    2394     for( i = 0; i < candidateCount; ++i )
    2395     {
    2396         tr_peer *    peer = candidates[i];
    2397         const double merit = bytesUsed
    2398                              ? ( meritBytes *
    2399                                 tr_peerIoGetBandwidthUsed( peer->io,
    2400                                                            direction ) ) /
    2401                              bytesUsed
    2402                              : ( meritBytes / candidateCount );
    2403         tr_peerIoSetBandwidth( peer->io, direction, merit + welfare );
    2404     }
    2405 
    2406     /* cleanup */
    2407     tr_free( candidates );
    2408 }
    2409 
    2410 static size_t
    2411 countHandshakeBandwidth( tr_ptrArray * handshakes,
    2412                          tr_direction  direction )
    2413 {
    2414     const int n = tr_ptrArraySize( handshakes );
    2415     int       i;
    2416     size_t    total;
    2417 
    2418     for( i = total = 0; i < n; ++i )
    2419     {
    2420         tr_peerIo * io = tr_handshakeGetIO( tr_ptrArrayNth( handshakes, i ) );
    2421         total += tr_peerIoGetBandwidthUsed( io, direction );
    2422     }
    2423     return total;
    2424 }
    2425 
    2426 static size_t
    2427 countPeerBandwidth( tr_ptrArray * peers,
    2428                     tr_direction  direction )
    2429 {
    2430     const int n = tr_ptrArraySize( peers );
    2431     int       i;
    2432     size_t    total;
    2433 
    2434     for( i = total = 0; i < n; ++i )
    2435     {
    2436         tr_peer * peer = tr_ptrArrayNth( peers, i );
    2437         total += tr_peerIoGetBandwidthUsed( peer->io, direction );
    2438     }
    2439     return total;
    2440 }
    2441 
    2442 static void
    2443 givePeersUnlimitedBandwidth( tr_ptrArray * peers,
    2444                              tr_direction  direction )
    2445 {
    2446     const int n = tr_ptrArraySize( peers );
    2447     int       i;
    2448 
    2449     for( i = 0; i < n; ++i )
    2450     {
    2451         tr_peer * peer = tr_ptrArrayNth( peers, i );
    2452         tr_peerIoSetBandwidthUnlimited( peer->io, direction );
    2453     }
    2454 }
    2455 
    24562324static void
    24572325pumpAllPeers( tr_peerMgr * mgr )
     
    24602328    int       i, j;
    24612329
    2462     for( i = 0; i < torrentCount; ++i )
     2330    for( i=0; i<torrentCount; ++i )
    24632331    {
    24642332        Torrent * t = tr_ptrArrayNth( mgr->torrents, i );
    2465         for( j = 0; j < tr_ptrArraySize( t->peers ); ++j )
     2333        for( j=0; j<tr_ptrArraySize( t->peers ); ++j )
    24662334        {
    24672335            tr_peer * peer = tr_ptrArrayNth( t->peers, j );
     
    24712339}
    24722340
    2473 /**
    2474  * Allocate bandwidth for each peer connection.
    2475  *
    2476  * @param mgr the peer manager
    2477  * @param direction whether to allocate upload or download bandwidth
    2478  * @return the amount of directional bandwidth used since the last pulse.
    2479  */
    2480 static double
    2481 allocateBandwidth( tr_peerMgr * mgr,
    2482                    tr_direction direction )
    2483 {
    2484     tr_session *  session = mgr->session;
    2485     const int     torrentCount = tr_ptrArraySize( mgr->torrents );
    2486     Torrent **    torrents = (Torrent **) tr_ptrArrayBase( mgr->torrents );
    2487     tr_ptrArray * globalPool = tr_ptrArrayNew( );
    2488     double        allBytesUsed = 0;
    2489     size_t        poolBytesUsed = 0;
    2490     int           i;
    2491 
    2492     assert( mgr );
    2493     assert( direction == TR_UP || direction == TR_DOWN );
    2494 
    2495     /* before allocating bandwidth, pump the connected peers */
     2341static int
     2342bandwidthPulse( void * vmgr )
     2343{
     2344    tr_peerMgr * mgr = vmgr;
     2345    managerLock( mgr );
     2346
    24962347    pumpAllPeers( mgr );
    2497 
    2498     for( i=0; i<torrentCount; ++i )
    2499     {
    2500         Torrent * t = torrents[i];
    2501         size_t used;
    2502         tr_speedlimit speedMode;
    2503 
    2504         /* no point in allocating bandwidth for stopped torrents */
    2505         if( tr_torrentGetActivity( t->tor ) == TR_STATUS_STOPPED )
    2506             continue;
    2507 
    2508         used = countPeerBandwidth( t->peers, direction );
    2509         countHandshakeBandwidth( t->outgoingHandshakes, direction );
    2510 
    2511         /* remember this torrent's bytes used */
    2512         tr_rcTransferred( t->tor->rawSpeed[direction], used );
    2513 
    2514         /* add this torrent's bandwidth use to allBytesUsed */
    2515         allBytesUsed += used;
    2516 
    2517         /* if piece data is disallowed, don't bother limiting bandwidth --
    2518          * we won't be asking for, or sending out, any pieces */
    2519         if( !tr_torrentIsPieceTransferAllowed( t->tor, direction ) )
    2520             speedMode = TR_SPEEDLIMIT_UNLIMITED;
    2521         else
    2522             speedMode = tr_torrentGetSpeedMode( t->tor, direction );
    2523            
    2524         /* process the torrent's peers based on its speed mode */
    2525         switch( speedMode )
    2526         {
    2527             case TR_SPEEDLIMIT_UNLIMITED:
    2528                 givePeersUnlimitedBandwidth( t->peers, direction );
    2529                 break;
    2530 
    2531             case TR_SPEEDLIMIT_SINGLE:
    2532                 setPeerBandwidth( t->peers, direction,
    2533                                   t->tor->rawSpeed[direction],
    2534                                   tr_torrentGetSpeedLimit( t->tor, direction ) );
    2535                 break;
    2536 
    2537             case TR_SPEEDLIMIT_GLOBAL:
    2538             {
    2539                 int       i;
    2540                 const int n = tr_ptrArraySize( t->peers );
    2541                 for( i = 0; i < n; ++i )
    2542                     tr_ptrArrayAppend( globalPool,
    2543                                       tr_ptrArrayNth( t->peers, i ) );
    2544                 poolBytesUsed += used;
    2545                 break;
    2546             }
    2547         }
    2548     }
    2549 
    2550     /* add incoming handshakes to the global pool */
    2551     i = countHandshakeBandwidth( mgr->incomingHandshakes, direction );
    2552     allBytesUsed += i;
    2553     poolBytesUsed += i;
    2554 
    2555     tr_rcTransferred( mgr->globalPoolRawSpeed[direction], poolBytesUsed );
    2556 
    2557     /* handle the global pool's connections */
    2558     if( !tr_sessionIsSpeedLimitEnabled( session, direction ) )
    2559         givePeersUnlimitedBandwidth( globalPool, direction );
    2560     else
    2561         setPeerBandwidth( globalPool, direction,
    2562                           mgr->globalPoolRawSpeed[direction],
    2563                           tr_sessionGetSpeedLimit( session, direction ) );
    2564 
    2565     /* now that we've allocated bandwidth, pump all the connected peers */
     2348    tr_bandwidthAllocate( mgr->session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
     2349    tr_bandwidthAllocate( mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
    25662350    pumpAllPeers( mgr );
    2567 
    2568     /* cleanup */
    2569     tr_ptrArrayFree( globalPool, NULL );
    2570     return allBytesUsed;
    2571 }
    2572 
    2573 static int
    2574 bandwidthPulse( void * vmgr )
    2575 {
    2576     tr_peerMgr * mgr = vmgr;
    2577     int          i;
    2578 
    2579     managerLock( mgr );
    2580 
    2581     /* allocate the upload and download bandwidth */
    2582     for( i = 0; i < 2; ++i )
    2583         allocateBandwidth( mgr, i );
    25842351
    25852352    managerUnlock( mgr );
    25862353    return TRUE;
    25872354}
    2588 
  • branches/1.4x/libtransmission/peer-mgr.h

    r7055 r7176  
    1010 * $Id$
    1111 */
     12
     13#ifndef __TRANSMISSION__
     14#error only libtransmission should #include this header.
     15#endif
    1216
    1317#ifndef TR_PEER_MGR_H
  • branches/1.4x/libtransmission/peer-msgs.c

    r7168 r7176  
    2525#include "crypto.h"
    2626#include "inout.h"
     27#include "iobuf.h"
    2728#ifdef WIN32
    2829#include "net.h" /* for ECONN */
     
    261262struct tr_peermsgs
    262263{
    263     unsigned int    peerSentBitfield        : 1;
    264     unsigned int    peerSupportsPex         : 1;
    265     unsigned int    clientSentLtepHandshake : 1;
    266     unsigned int    peerSentLtepHandshake   : 1;
    267     unsigned int    sendingBlock            : 1;
     264    tr_bool         peerSentBitfield;
     265    tr_bool         peerSupportsPex;
     266    tr_bool         clientSentLtepHandshake;
     267    tr_bool         peerSentLtepHandshake;
    268268
    269269    uint8_t         state;
     
    286286    tr_publisher_t *       publisher;
    287287
    288     struct evbuffer *      outBlock; /* buffer of the current piece message */
    289288    struct evbuffer *      outMessages; /* all the non-piece messages */
    290289
     
    345344}
    346345
    347 #define dbgmsg( msgs, ... ) myDebug( __FILE__, __LINE__, msgs, __VA_ARGS__ )
     346#define dbgmsg( msgs, ... ) \
     347    do { \
     348        if( tr_deepLoggingIsActive( ) ) \
     349            myDebug( __FILE__, __LINE__, msgs, __VA_ARGS__ ); \
     350    } while( 0 )
    348351
    349352/**
     
    430433**/
    431434
    432 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0 };
     435static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0 };
    433436
    434437static void
     
    484487static void
    485488fireClientGotData( tr_peermsgs * msgs,
    486                    uint32_t      length )
     489                   uint32_t      length,
     490                   int           wasPieceData )
    487491{
    488492    tr_peer_event e = blankEvent;
     
    490494    e.length = length;
    491495    e.eventType = TR_PEER_CLIENT_GOT_DATA;
     496    e.wasPieceData = wasPieceData;
    492497    publish( msgs, &e );
    493498}
    494499
    495500static void
    496 firePeerGotData( tr_peermsgs * msgs,
    497                  uint32_t      length )
     501firePeerGotData( tr_peermsgs  * msgs,
     502                 uint32_t       length,
     503                 int            wasPieceData )
    498504{
    499505    tr_peer_event e = blankEvent;
     
    501507    e.length = length;
    502508    e.eventType = TR_PEER_PEER_GOT_DATA;
     509    e.wasPieceData = wasPieceData;
     510
    503511    publish( msgs, &e );
    504512}
     
    906914    **/
    907915
    908     dbgmsg( msgs, "added req for piece %lu", (unsigned long)index );
     916    dbgmsg( msgs, "adding req for %"PRIu32":%"PRIu32"->%"PRIu32" to our `will request' list",
     917            index, offset, length );
    909918    req.time_requested = time( NULL );
    910919    reqListAppend( &msgs->clientWillAskFor, &req );
     
    918927    struct request_list a = msgs->clientWillAskFor;
    919928    struct request_list b = msgs->clientAskedFor;
     929    dbgmsg( msgs, "cancelling all requests to peer" );
    920930
    921931    msgs->clientAskedFor = REQUEST_LIST_INIT;
     
    945955    assert( length > 0 );
    946956
     957
    947958    /* have we asked the peer for this piece? */
    948959    req.index = pieceIndex;
     
    951962
    952963    /* if it's only in the queue and hasn't been sent yet, free it */
    953     if( reqListRemove( &msgs->clientWillAskFor, &req ) )
     964    if( reqListRemove( &msgs->clientWillAskFor, &req ) ) {
     965        dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32"\n", pieceIndex, offset, length );
    954966        fireCancelledReq( msgs, &req );
     967    }
    955968
    956969    /* if it's already been sent, send a cancel message too */
    957970    if( reqListRemove( &msgs->clientAskedFor, &req ) ) {
     971        dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32"\n", pieceIndex, offset, length );
    958972        protocolSendCancel( msgs, &req );
    959973        fireCancelledReq( msgs, &req );
     
    10291043    }
    10301044
    1031     dbgmsg( msgs, "here is the ltep handshake we got [%*.*s]", len, len,
    1032             tmp );
     1045    dbgmsg( msgs, "here is the handshake: [%*.*s]", len, len,  tmp );
    10331046
    10341047    /* does the peer prefer encrypted connections? */
     
    13001313                           const struct peer_request * req );
    13011314
    1302 static void
    1303 clientGotBytes( tr_peermsgs * msgs,
    1304                 uint32_t      byteCount )
    1305 {
    1306     msgs->info->pieceDataActivityDate = time( NULL );
    1307     fireClientGotData( msgs, byteCount );
    1308 }
    1309 
    13101315static int
    1311 readBtPiece( tr_peermsgs *     msgs,
    1312              struct evbuffer * inbuf,
    1313              size_t            inlen )
     1316readBtPiece( tr_peermsgs      * msgs,
     1317             struct evbuffer  * inbuf,
     1318             size_t             inlen,
     1319             size_t           * setme_piece_bytes_read )
    13141320{
    13151321    struct peer_request * req = &msgs->incoming.blockReq;
     
    13431349        tr_peerIoReadBytes( msgs->io, inbuf, buf, n );
    13441350        evbuffer_add( msgs->incoming.block, buf, n );
    1345         clientGotBytes( msgs, n );
     1351        fireClientGotData( msgs, n, TRUE );
     1352        *setme_piece_bytes_read += n;
    13461353        tr_free( buf );
    13471354        dbgmsg( msgs, "got %d bytes for block %u:%u->%u ... %d remain",
     
    15401547
    15411548static void
    1542 peerGotBytes( tr_peermsgs * msgs,
    1543               uint32_t      byteCount,
    1544               const time_t  now )
    1545 {
    1546     msgs->info->pieceDataActivityDate = now;
    1547     firePeerGotData( msgs, byteCount );
    1548 }
    1549 
    1550 static void
    15511549decrementDownloadedCount( tr_peermsgs * msgs,
    15521550                          uint32_t      byteCount )
     
    16351633}
    16361634
     1635static int peerPulse( void * vmsgs );
     1636
     1637static void
     1638didWrite( tr_peerIo * io UNUSED, size_t bytesWritten, int wasPieceData, void * vmsgs )
     1639{
     1640    tr_peermsgs * msgs = vmsgs;
     1641    firePeerGotData( msgs, bytesWritten, wasPieceData );
     1642    peerPulse( msgs );
     1643}
     1644
    16371645static ReadState
    1638 canRead( struct bufferevent * evin,
    1639          void *               vmsgs )
     1646canRead( struct tr_iobuf * iobuf, void * vmsgs, size_t * piece )
    16401647{
    16411648    ReadState         ret;
    16421649    tr_peermsgs *     msgs = vmsgs;
    1643     struct evbuffer * in = EVBUFFER_INPUT ( evin );
     1650    struct evbuffer * in = tr_iobuf_input( iobuf );
    16441651    const size_t      inlen = EVBUFFER_LENGTH( in );
    16451652
     
    16501657    else if( msgs->state == AWAITING_BT_PIECE )
    16511658    {
    1652         ret = inlen ? readBtPiece( msgs, in, inlen ) : READ_LATER;
     1659        ret = inlen ? readBtPiece( msgs, in, inlen, piece ) : READ_LATER;
    16531660    }
    16541661    else switch( msgs->state )
    1655         {
    1656             case AWAITING_BT_LENGTH:
    1657                 ret = readBtLength ( msgs, in, inlen ); break;
    1658 
    1659             case AWAITING_BT_ID:
    1660                 ret = readBtId     ( msgs, in, inlen ); break;
    1661 
    1662             case AWAITING_BT_MESSAGE:
    1663                 ret = readBtMessage( msgs, in, inlen ); break;
    1664 
    1665             default:
    1666                 assert( 0 );
    1667         }
     1662    {
     1663        case AWAITING_BT_LENGTH:
     1664            ret = readBtLength ( msgs, in, inlen ); break;
     1665
     1666        case AWAITING_BT_ID:
     1667            ret = readBtId     ( msgs, in, inlen ); break;
     1668
     1669        case AWAITING_BT_MESSAGE:
     1670            ret = readBtMessage( msgs, in, inlen ); break;
     1671
     1672        default:
     1673            assert( 0 );
     1674    }
     1675
     1676    /* log the raw data that was read */
     1677    if( EVBUFFER_LENGTH( in ) != inlen )
     1678        fireClientGotData( msgs, inlen - EVBUFFER_LENGTH( in ), FALSE );
    16681679
    16691680    return ret;
    1670 }
    1671 
    1672 static void
    1673 sendKeepalive( tr_peermsgs * msgs )
    1674 {
    1675     dbgmsg( msgs, "sending a keepalive message" );
    1676     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, 0 );
    1677     pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
    16781681}
    16791682
     
    16911694                  ( rateToClient * 30 * 1024 ) / peer->torrent->blockSize;
    16921695
    1693     peer->minActiveRequests = 4;
    1694     peer->maxActiveRequests = peer->minActiveRequests +
    1695                               estimatedBlocksInNext30Seconds;
     1696    peer->minActiveRequests = 8;
     1697    peer->maxActiveRequests = peer->minActiveRequests + estimatedBlocksInNext30Seconds;
    16961698    return TRUE;
    16971699}
     
    17051707}
    17061708
     1709static size_t
     1710fillOutputBuffer( tr_peermsgs * msgs, time_t now )
     1711{
     1712    size_t bytesWritten = 0;
     1713    struct peer_request req;
     1714    const int haveMessages = EVBUFFER_LENGTH( msgs->outMessages ) != 0;
     1715
     1716    /**
     1717    ***  Protocol messages
     1718    **/
     1719
     1720    if( haveMessages && !msgs->outMessagesBatchedAt ) /* fresh batch */
     1721    {
     1722        dbgmsg( msgs, "started an outMessages batch (length is %zu)", EVBUFFER_LENGTH( msgs->outMessages ) );
     1723        msgs->outMessagesBatchedAt = now;
     1724    }
     1725    else if( haveMessages && ( ( now - msgs->outMessagesBatchedAt ) >= msgs->outMessagesBatchPeriod ) )
     1726    {
     1727        const size_t len = EVBUFFER_LENGTH( msgs->outMessages );
     1728        /* flush the protocol messages */
     1729        dbgmsg( msgs, "flushing outMessages... to %p (length is %zu)", msgs->io, len );
     1730        tr_peerIoWriteBuf( msgs->io, msgs->outMessages, FALSE );
     1731        msgs->clientSentAnythingAt = now;
     1732        msgs->outMessagesBatchedAt = 0;
     1733        msgs->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
     1734        bytesWritten +=  len;
     1735    }
     1736
     1737    /**
     1738    ***  Blocks
     1739    **/
     1740
     1741    if( ( tr_peerIoGetWriteBufferSpace( msgs->io ) >= msgs->torrent->blockSize )
     1742        && popNextRequest( msgs, &req )
     1743        && requestIsValid( msgs, &req )
     1744        && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) )
     1745    {
     1746        /* send a block */
     1747        uint8_t * buf = tr_new( uint8_t, req.length );
     1748        const int err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf );
     1749        if( err ) {
     1750            fireError( msgs, err );
     1751        } else {
     1752            tr_peerIo * io = msgs->io;
     1753            struct evbuffer * out = evbuffer_new( );
     1754            dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length );
     1755            tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) + req.length );
     1756            tr_peerIoWriteUint8 ( io, out, BT_PIECE );
     1757            tr_peerIoWriteUint32( io, out, req.index );
     1758            tr_peerIoWriteUint32( io, out, req.offset );
     1759            tr_peerIoWriteBytes ( io, out, buf, req.length );
     1760            tr_peerIoWriteBuf( io, out, TRUE );
     1761            bytesWritten += EVBUFFER_LENGTH( out );
     1762            evbuffer_free( out );
     1763            msgs->clientSentAnythingAt = now;
     1764        }
     1765        tr_free( buf );
     1766    }
     1767
     1768    /**
     1769    ***  Keepalive
     1770    **/
     1771
     1772    if( msgs->clientSentAnythingAt
     1773        && ( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS ) )
     1774    {
     1775        dbgmsg( msgs, "sending a keepalive message" );
     1776        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, 0 );
     1777        pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
     1778    }
     1779
     1780    return bytesWritten;
     1781}
     1782
    17071783static int
    17081784peerPulse( void * vmsgs )
     
    17131789    ratePulse( msgs );
    17141790
    1715     /*tr_peerIoTryRead( msgs->io );*/
    17161791    pumpRequestQueue( msgs, now );
    17171792    expireOldRequests( msgs, now );
    17181793
    1719     if( msgs->sendingBlock )
    1720     {
    1721         const size_t uploadMax = tr_peerIoGetWriteBufferSpace( msgs->io );
    1722         size_t       len = EVBUFFER_LENGTH( msgs->outBlock );
    1723         const size_t outlen = MIN( len, uploadMax );
    1724 
    1725         assert( len );
    1726 
    1727         if( outlen )
    1728         {
    1729             tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen );
    1730             evbuffer_drain( msgs->outBlock, outlen );
    1731             peerGotBytes( msgs, outlen, now );
    1732 
    1733             len -= outlen;
    1734             msgs->clientSentAnythingAt = now;
    1735             msgs->sendingBlock = len != 0;
    1736 
    1737             dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen,
    1738                     (int)len );
    1739         }
    1740         else dbgmsg( msgs,
    1741                      "stalled writing block... uploadMax %lu, outlen %lu",
    1742                      uploadMax, outlen );
    1743     }
    1744 
    1745     if( !msgs->sendingBlock )
    1746     {
    1747         struct peer_request req;
    1748         const int haveMessages = EVBUFFER_LENGTH( msgs->outMessages ) != 0;
    1749 
    1750         if( haveMessages && !msgs->outMessagesBatchedAt ) /* fresh batch */
    1751         {
    1752             dbgmsg( msgs, "started an outMessages batch (length is %d)",
    1753                    (int)EVBUFFER_LENGTH( msgs->outMessages ) );
    1754             msgs->outMessagesBatchedAt = now;
    1755         }
    1756         else if( haveMessages
    1757                && ( ( now - msgs->outMessagesBatchedAt ) >
    1758                    msgs->outMessagesBatchPeriod ) )
    1759         {
    1760             dbgmsg( msgs, "flushing outMessages... (length is %d)",
    1761                    (int)EVBUFFER_LENGTH(
    1762                        msgs->outMessages ) );
    1763             tr_peerIoWriteBuf( msgs->io, msgs->outMessages );
    1764             msgs->clientSentAnythingAt = now;
    1765             msgs->outMessagesBatchedAt = 0;
    1766             msgs->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
    1767         }
    1768         else if( !EVBUFFER_LENGTH( msgs->outBlock )
    1769                && popNextRequest( msgs, &req )
    1770                && requestIsValid( msgs, &req )
    1771                && tr_cpPieceIsComplete( msgs->torrent->completion,
    1772                                         req.index ) )
    1773         {
    1774             uint8_t * buf = tr_new( uint8_t, req.length );
    1775             const int err = tr_ioRead( msgs->torrent,
    1776                                        req.index, req.offset, req.length,
    1777                                        buf );
    1778             if( err )
    1779             {
    1780                 fireError( msgs, err );
    1781             }
    1782             else
    1783             {
    1784                 tr_peerIo *       io = msgs->io;
    1785                 struct evbuffer * out = msgs->outBlock;
    1786 
    1787                 dbgmsg( msgs, "sending block %u:%u->%u", req.index,
    1788                         req.offset,
    1789                         req.length );
    1790                 tr_peerIoWriteUint32(
    1791                     io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) +
    1792                     req.length );
    1793                 tr_peerIoWriteUint8 ( io, out, BT_PIECE );
    1794                 tr_peerIoWriteUint32( io, out, req.index );
    1795                 tr_peerIoWriteUint32( io, out, req.offset );
    1796                 tr_peerIoWriteBytes ( io, out, buf, req.length );
    1797                 msgs->sendingBlock = 1;
    1798             }
    1799 
    1800             tr_free( buf );
    1801         }
    1802         else if( ( !haveMessages )
    1803                && ( now - msgs->clientSentAnythingAt ) >
    1804                 KEEPALIVE_INTERVAL_SECS )
    1805         {
    1806             sendKeepalive( msgs );
    1807         }
    1808     }
     1794    for( ;; )
     1795        if( fillOutputBuffer( msgs, now ) < 1 )
     1796            break;
    18091797
    18101798    return TRUE; /* loop forever */
     
    18191807
    18201808static void
    1821 gotError( struct bufferevent * evbuf UNUSED,
    1822           short                      what,
    1823           void *                    vmsgs )
     1809gotError( struct tr_iobuf  * iobuf UNUSED,
     1810          short              what,
     1811          void             * vmsgs )
    18241812{
    18251813    if( what & EVBUFFER_TIMEOUT )
    1826         dbgmsg( vmsgs, "libevent got a timeout, what=%hd, secs=%d", what,
    1827                 evbuf->timeout_read );
     1814        dbgmsg( vmsgs, "libevent got a timeout, what=%hd", what );
    18281815    if( what & ( EVBUFFER_EOF | EVBUFFER_ERROR ) )
    18291816        dbgmsg( vmsgs, "libevent got an error! what=%hd, errno=%d (%s)",
     
    18431830    field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
    18441831
     1832#if 0
    18451833    if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) )
    18461834    {
     
    18481836            speed over a truly random sample -- let's limit the pool size to
    18491837            the first 1000 pieces so large torrents don't bog things down */
    1850         size_t             poolSize = MIN( msgs->torrent->info.pieceCount,
    1851                                           1000 );
    1852         tr_piece_index_t * pool = tr_new( tr_piece_index_t, poolSize );
     1838        size_t poolSize;
     1839        const size_t maxPoolSize = MIN( msgs->torrent->info.pieceCount, 1000 );
     1840        tr_piece_index_t * pool = tr_new( tr_piece_index_t, maxPoolSize );
    18531841
    18541842        /* build the pool */
    1855         for( i = 0; i < poolSize; ++i )
    1856             pool[i] = i;
     1843        for( i=poolSize=0; i<maxPoolSize; ++i )
     1844            if( tr_bitfieldHas( field, i ) )
     1845                pool[poolSize++] = i;
    18571846
    18581847        /* pull random piece indices from the pool */
    18591848        while( ( poolSize > 0 ) && ( lazyCount < LAZY_PIECE_COUNT ) )
    18601849        {
    1861             const int              pos = tr_cryptoWeakRandInt( poolSize );
     1850            const int pos = tr_cryptoWeakRandInt( poolSize );
    18621851            const tr_piece_index_t piece = pool[pos];
    18631852            tr_bitfieldRem( field, piece );
     
    18691858        tr_free( pool );
    18701859    }
     1860#endif
    18711861
    18721862    tr_peerIoWriteUint32( msgs->io, out,
     
    19471937    if( msgs->peerSupportsPex && tr_torrentAllowsPex( msgs->torrent ) )
    19481938    {
    1949         PexDiffs          diffs;
    1950         tr_pex *          newPex = NULL;
    1951         const int         newCount = tr_peerMgrGetPeers( msgs->session->peerMgr,
    1952                                                          msgs->torrent->info.hash,
    1953                                                          &newPex );
     1939        PexDiffs diffs;
     1940        tr_pex * newPex = NULL;
     1941        const int newCount = tr_peerMgrGetPeers( msgs->session->peerMgr,
     1942                                                 msgs->torrent->info.hash,
     1943                                                 &newPex );
     1944
    19541945        /* build the diffs */
    19551946        diffs.added = tr_new( tr_pex, newCount );
     
    19701961        if( diffs.addedCount || diffs.droppedCount )
    19711962        {
    1972             int               i;
    1973             tr_benc           val;
    1974             uint8_t *         tmp, *walk;
    1975             char *            benc;
    1976             int               bencLen;
     1963            int  i;
     1964            tr_benc val;
     1965            char * benc;
     1966            int bencLen;
     1967            uint8_t * tmp, *walk;
    19771968            struct evbuffer * out = msgs->outMessages;
    19781969
     
    19871978            /* "added" */
    19881979            tmp = walk = tr_new( uint8_t, diffs.addedCount * 6 );
    1989             for( i = 0; i < diffs.addedCount; ++i )
    1990             {
     1980            for( i = 0; i < diffs.addedCount; ++i ) {
    19911981                memcpy( walk, &diffs.added[i].in_addr, 4 ); walk += 4;
    19921982                memcpy( walk, &diffs.added[i].port, 2 ); walk += 2;
     
    20061996            /* "dropped" */
    20071997            tmp = walk = tr_new( uint8_t, diffs.droppedCount * 6 );
    2008             for( i = 0; i < diffs.droppedCount; ++i )
    2009             {
     1998            for( i = 0; i < diffs.droppedCount; ++i ) {
    20101999                memcpy( walk, &diffs.dropped[i].in_addr, 4 ); walk += 4;
    20112000                memcpy( walk, &diffs.dropped[i].port, 2 ); walk += 2;
     
    20212010            tr_peerIoWriteUint8 ( msgs->io, out, msgs->ut_pex_id );
    20222011            tr_peerIoWriteBytes ( msgs->io, out, benc, bencLen );
    2023             pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
    2024             dbgmsg( msgs, "outMessage size is now %zu", EVBUFFER_LENGTH( out ) );
    2025 
    2026             /* cleanup */
     2012            pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS );
     2013            dbgmsg( msgs, "sending a pex message; outMessage size is now %zu", EVBUFFER_LENGTH( out ) );
     2014
    20272015            tr_free( benc );
    20282016            tr_bencFree( &val );
    20292017        }
    20302018
     2019        /* cleanup */
    20312020        tr_free( diffs.added );
    20322021        tr_free( diffs.dropped );
     
    20772066    m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS;
    20782067    m->incoming.block = evbuffer_new( );
    2079     m->outBlock = evbuffer_new( );
    20802068    m->peerAllowedPieces = NULL;
    20812069    m->peerAskedFor = REQUEST_LIST_INIT;
     
    20922080    tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of
    20932081                                             inactivity */
    2094     tr_peerIoSetIOFuncs( m->io, canRead, NULL, gotError, m );
     2082    tr_peerIoSetIOFuncs( m->io, canRead, didWrite, gotError, m );
    20952083    ratePulse( m );
    20962084
     
    21122100        evbuffer_free( msgs->incoming.block );
    21132101        evbuffer_free( msgs->outMessages );
    2114         evbuffer_free( msgs->outBlock );
    21152102        tr_free( msgs->pex );
    21162103
  • branches/1.4x/libtransmission/port-forwarding.c

    r6795 r7176  
    3333struct tr_shared
    3434{
    35     unsigned int          isEnabled      : 1;
    36     unsigned int          isShuttingDown : 1;
     35    tr_bool               isEnabled;
     36    tr_bool               isShuttingDown;
    3737
    3838    tr_port_forwarding    natpmpStatus;
     
    4343    int                   publicPort;
    4444
    45     tr_handle *           h;
    46     tr_timer *            pulseTimer;
    47 
    48     tr_upnp *             upnp;
    49     tr_natpmp *           natpmp;
     45    tr_timer            * pulseTimer;
     46
     47    tr_upnp             * upnp;
     48    tr_natpmp           * natpmp;
     49    tr_session          * session;
    5050};
    5151
     
    146146            break;
    147147
    148         socket = tr_netAccept( s->bindSocket, &addr, &port );
     148        socket = tr_netAccept( s->session, s->bindSocket, &addr, &port );
    149149        if( socket < 0 )
    150150            break;
     
    152152        tr_deepLog( __FILE__, __LINE__, NULL,
    153153                   "New INCOMING connection %d (%s)",
    154                    socket, tr_peerIoAddrStr( &addr,
    155                                              port ) );
    156 
    157         tr_peerMgrAddIncoming( s->h->peerMgr, &addr, port, socket );
     154                   socket, tr_peerIoAddrStr( &addr, port ) );
     155
     156        tr_peerMgrAddIncoming( s->session->peerMgr, &addr, port, socket );
    158157    }
    159158}
     
    178177        tr_natpmpClose( shared->natpmp );
    179178        tr_upnpClose( shared->upnp );
    180         shared->h->shared = NULL;
     179        shared->session->shared = NULL;
    181180        tr_free( shared );
    182181        keepPulsing = 0;
     
    191190
    192191tr_shared *
    193 tr_sharedInit( tr_handle * h,
    194                int         isEnabled,
    195                int         publicPort )
     192tr_sharedInit( tr_session  * session,
     193               int           isEnabled,
     194               int           publicPort )
    196195{
    197196    tr_shared * s = tr_new0( tr_shared, 1 );
    198197
    199     s->h            = h;
     198    s->session      = session;
    200199    s->publicPort   = publicPort;
    201200    s->bindPort     = -1;
     
    203202    s->natpmp       = tr_natpmpInit( );
    204203    s->upnp         = tr_upnpInit( );
    205     s->pulseTimer   = tr_timerNew( h, sharedPulse, s, 1000 );
     204    s->pulseTimer   = tr_timerNew( session, sharedPulse, s, 1000 );
    206205    s->isEnabled    = isEnabled ? 1 : 0;
    207206    s->upnpStatus   = TR_PORT_UNMAPPED;
     
    225224    s->publicPort = port;
    226225
    227     while( ( tor = tr_torrentNext( s->h, tor ) ) )
     226    while( ( tor = tr_torrentNext( s->session, tor ) ) )
    228227        tr_torrentChangeMyPort( tor );
    229228}
  • branches/1.4x/libtransmission/session.c

    r7069 r7176  
    2222
    2323#include "transmission.h"
     24#include "bandwidth.h"
    2425#include "blocklist.h"
    2526#include "fdlimit.h"
     
    3031#include "platform.h" /* tr_lock */
    3132#include "port-forwarding.h"
    32 #include "ratecontrol.h"
    3333#include "rpc-server.h"
    3434#include "stats.h"
     
    255255    h->proxyUsername = tr_strdup( proxyUsername );
    256256    h->proxyPassword = tr_strdup( proxyPassword );
    257     h->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    258     h->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    259     h->rawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    260     h->rawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
     257    h->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
     258    h->so_rcvbuf = 8192;
    261259
    262260    if( configDir == NULL )
     
    277275    /* Initialize rate and file descripts controls */
    278276
    279     h->uploadLimit = uploadLimit;
    280     h->useUploadLimit = useUploadLimit;
    281     h->downloadLimit = downloadLimit;
    282     h->useDownloadLimit = useDownloadLimit;
    283 
    284277    tr_fdInit( globalPeerLimit );
    285278    h->shared = tr_sharedInit( h, isPortForwardingEnabled, publicPort );
    286279    h->isPortSet = publicPort >= 0;
     280
     281    h->bandwidth = tr_bandwidthNew( h, NULL );
     282    tr_bandwidthSetDesiredSpeed( h->bandwidth, TR_UP, uploadLimit );
     283    tr_bandwidthSetDesiredSpeed( h->bandwidth, TR_DOWN, downloadLimit );
     284    tr_bandwidthSetLimited( h->bandwidth, TR_UP, useUploadLimit );
     285    tr_bandwidthSetLimited( h->bandwidth, TR_DOWN, useDownloadLimit );
    287286
    288287    /* first %s is the application name
     
    444443
    445444void
    446 tr_sessionSetSpeedLimitEnabled( tr_handle *  h,
    447                                 tr_direction direction,
    448                                 int          use_flag )
    449 {
    450     assert( h );
    451     assert( direction == TR_UP || direction == TR_DOWN );
    452 
    453     if( direction == TR_UP )
    454         h->useUploadLimit = use_flag ? 1 : 0;
    455     else
    456         h->useDownloadLimit = use_flag ? 1 : 0;
    457 }
    458 
    459 int
    460 tr_sessionIsSpeedLimitEnabled( const tr_handle * h,
    461                                tr_direction      direction )
    462 {
    463     return direction == TR_UP ? h->useUploadLimit : h->useDownloadLimit;
    464 }
    465 
    466 void
    467 tr_sessionSetSpeedLimit( tr_handle *  h,
    468                          tr_direction direction,
    469                          int          KiB_sec )
    470 {
    471     if( direction == TR_DOWN )
    472         h->downloadLimit = KiB_sec;
    473     else
    474         h->uploadLimit = KiB_sec;
    475 }
    476 
    477 int
    478 tr_sessionGetSpeedLimit( const tr_handle * h,
    479                          tr_direction      direction )
    480 {
    481     return direction == TR_UP ? h->uploadLimit : h->downloadLimit;
     445tr_sessionSetSpeedLimitEnabled( tr_session      * session,
     446                                tr_direction      dir,
     447                                int               isLimited )
     448{
     449    tr_bandwidthSetLimited( session->bandwidth, dir, isLimited );
     450}
     451
     452int
     453tr_sessionIsSpeedLimitEnabled( const tr_session  * session,
     454                               tr_direction        dir )
     455{
     456    return !tr_bandwidthIsLimited( session->bandwidth, dir );
     457}
     458
     459void
     460tr_sessionSetSpeedLimit( tr_session    * session,
     461                         tr_direction    dir,
     462                         int             desiredSpeed )
     463{
     464    tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, desiredSpeed );
     465}
     466
     467int
     468tr_sessionGetSpeedLimit( const tr_session  * session,
     469                         tr_direction        dir )
     470{
     471    return tr_bandwidthGetDesiredSpeed( session->bandwidth, dir );
    482472}
    483473
     
    506496tr_sessionGetPieceSpeed( const tr_session * session, tr_direction dir )
    507497{
    508     assert( dir==TR_UP || dir==TR_DOWN );
    509 
    510     return session ? tr_rcRate( session->pieceSpeed[dir] ) : 0.0;
     498    return session ? tr_bandwidthGetPieceSpeed( session->bandwidth, dir ) : 0.0;
    511499}
    512500
     
    514502tr_sessionGetRawSpeed( const tr_session * session, tr_direction dir )
    515503{
    516     assert( dir==TR_UP || dir==TR_DOWN );
    517 
    518     return session ? tr_rcRate( session->rawSpeed[dir] ) : 0.0;
     504    return session ? tr_bandwidthGetPieceSpeed( session->bandwidth, dir ) : 0.0;
    519505}
    520506
     
    630616
    631617    /* free the session memory */
    632     tr_rcClose( session->pieceSpeed[TR_PEER_TO_CLIENT] );
    633     tr_rcClose( session->pieceSpeed[TR_CLIENT_TO_PEER] );
    634     tr_rcClose( session->rawSpeed[TR_PEER_TO_CLIENT] );
    635     tr_rcClose( session->rawSpeed[TR_CLIENT_TO_PEER] );
     618    tr_bandwidthFree( session->bandwidth );
    636619    tr_lockFree( session->lock );
    637620    for( i = 0; i < session->metainfoLookupCount; ++i )
  • branches/1.4x/libtransmission/session.h

    r7069 r7176  
    2222 * DEALINGS IN THE SOFTWARE.
    2323 *****************************************************************************/
     24
     25#ifndef __TRANSMISSION__
     26#error only libtransmission should #include this header.
     27#endif
    2428
    2529#ifndef TR_INTERNAL_H
     
    4953};
    5054
    51 struct tr_ratecontrol;
     55struct tr_bandwidth;
    5256
    5357struct tr_handle
    5458{
    55     unsigned int                 isPortSet          : 1;
    56     unsigned int                 isPexEnabled       : 1;
    57     unsigned int                 isBlocklistEnabled : 1;
    58     unsigned int                 isProxyEnabled     : 1;
    59     unsigned int                 isProxyAuthEnabled : 1;
    60     unsigned int                 isClosed           : 1;
    61     unsigned int                 useUploadLimit     : 1;
    62     unsigned int                 useDownloadLimit   : 1;
    63     unsigned int                 useLazyBitfield    : 1;
     59    tr_bool                      isPortSet;
     60    tr_bool                      isPexEnabled;
     61    tr_bool                      isBlocklistEnabled;
     62    tr_bool                      isProxyEnabled;
     63    tr_bool                      isProxyAuthEnabled;
     64    tr_bool                      isClosed;
     65    tr_bool                      useLazyBitfield;
    6466
    6567    tr_encryption_mode           encryptionMode;
     
    8587    char *                       proxyPassword;
    8688
    87     int                          uploadLimit;
    88     int                          downloadLimit;
    89 
    9089    struct tr_list *             blocklists;
    9190    struct tr_peerMgr *          peerMgr;
     
    106105    int                          metainfoLookupCount;
    107106
    108     /* the rate at which pieces are being transferred between client and peer.
    109      * protocol overhead is NOT included; this is only the piece data */
    110     struct tr_ratecontrol     *  pieceSpeed[2];
     107    /* the size of the output buffer for peer connections */
     108    int so_sndbuf;
    111109
    112     /* the rate at which bytes are being transferred between client and peer. */
    113     struct tr_ratecontrol     *  rawSpeed[2];
     110    /* the size of the input buffer for peer connections */
     111    int so_rcvbuf;
     112
     113    /* monitors the "global pool" speeds */
     114    struct tr_bandwidth       * bandwidth;
    114115};
    115116
  • branches/1.4x/libtransmission/torrent.c

    r7069 r7176  
    3333
    3434#include "transmission.h"
     35#include "bandwidth.h"
    3536#include "bencode.h"
    3637#include "completion.h"
     
    143144void
    144145tr_torrentSetSpeedMode( tr_torrent *  tor,
    145                         tr_direction  direction,
     146                        tr_direction  dir,
    146147                        tr_speedlimit mode )
    147148{
    148     tr_speedlimit * limit = direction == TR_UP ? &tor->uploadLimitMode
    149                                                : &tor->downloadLimitMode;
    150 
    151     *limit = mode;
     149    assert( tor != NULL );
     150    assert( dir==TR_UP || dir==TR_DOWN );
     151    assert( mode==TR_SPEEDLIMIT_GLOBAL || mode==TR_SPEEDLIMIT_SINGLE || mode==TR_SPEEDLIMIT_UNLIMITED  );
     152
     153    tor->speedLimitMode[dir] = mode;
     154
     155    tr_bandwidthSetLimited( tor->bandwidth, dir, mode==TR_SPEEDLIMIT_SINGLE );
     156    tr_bandwidthHonorParentLimits( tor->bandwidth, dir, mode!=TR_SPEEDLIMIT_UNLIMITED );
    152157}
    153158
    154159tr_speedlimit
    155160tr_torrentGetSpeedMode( const tr_torrent * tor,
    156                         tr_direction       direction )
    157 {
    158     return direction == TR_UP ? tor->uploadLimitMode
    159                               : tor->downloadLimitMode;
     161                        tr_direction       dir )
     162{
     163    assert( tor != NULL );
     164    assert( dir==TR_UP || dir==TR_DOWN );
     165
     166    return tor->speedLimitMode[dir];
    160167}
    161168
    162169void
    163170tr_torrentSetSpeedLimit( tr_torrent * tor,
    164                          tr_direction direction,
    165                          int          single_KiB_sec )
    166 {
    167     switch( direction )
    168     {
    169         case TR_UP:
    170             tor->uploadLimit = single_KiB_sec; break;
    171 
    172         case TR_DOWN:
    173             tor->downloadLimit = single_KiB_sec; break;
    174 
    175         default:
    176             assert( 0 );
    177     }
     171                         tr_direction dir,
     172                         int          desiredSpeed )
     173{
     174    tr_bandwidthSetDesiredSpeed( tor->bandwidth, dir, desiredSpeed );
    178175}
    179176
    180177int
    181178tr_torrentGetSpeedLimit( const tr_torrent * tor,
    182                          tr_direction       direction )
    183 {
    184     switch( direction )
    185     {
    186         case TR_UP:
    187             return tor->uploadLimit;
    188 
    189         case TR_DOWN:
    190             return tor->downloadLimit;
    191 
    192         default:
    193             assert( 0 );
    194     }
     179                         tr_direction       dir )
     180{
     181    return tr_bandwidthGetDesiredSpeed( tor->bandwidth, dir );
    195182}
    196183
     
    497484    randomizeTiers( info );
    498485
    499     tor->rawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    500     tor->rawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    501     tor->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    502     tor->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
     486    tor->bandwidth = tr_bandwidthNew( h, h->bandwidth );
    503487
    504488    tor->blockSize = getBlockSize( info->pieceSize );
     
    542526    tr_torrentInitFilePieces( tor );
    543527
    544     tor->uploadLimit = 0;
    545     tor->downloadLimit = 0;
    546528    tor->swarmSpeed = tr_rcInit( );
    547529
     
    815797                            s->peersFrom );
    816798
    817     s->rawUploadSpeed     = tr_rcRate( tor->rawSpeed[TR_UP] );
    818     s->rawDownloadSpeed   = tr_rcRate( tor->rawSpeed[TR_DOWN] );
    819     s->pieceUploadSpeed   = tr_rcRate( tor->pieceSpeed[TR_UP] );
    820     s->pieceDownloadSpeed = tr_rcRate( tor->pieceSpeed[TR_DOWN] );
     799    s->rawUploadSpeed     = tr_bandwidthGetRawSpeed  ( tor->bandwidth, TR_UP );
     800    s->rawDownloadSpeed   = tr_bandwidthGetRawSpeed  ( tor->bandwidth, TR_DOWN );
     801    s->pieceUploadSpeed   = tr_bandwidthGetPieceSpeed( tor->bandwidth, TR_UP );
     802    s->pieceDownloadSpeed = tr_bandwidthGetPieceSpeed( tor->bandwidth, TR_DOWN );
    821803
    822804    usableSeeds += tor->info.webseedCount;
     
    11011083    h->torrentCount--;
    11021084
    1103     tr_rcClose( tor->pieceSpeed[TR_PEER_TO_CLIENT] );
    1104     tr_rcClose( tor->pieceSpeed[TR_CLIENT_TO_PEER] );
    1105     tr_rcClose( tor->rawSpeed[TR_PEER_TO_CLIENT] );
    1106     tr_rcClose( tor->rawSpeed[TR_CLIENT_TO_PEER] );
     1085    tr_bandwidthFree( tor->bandwidth );
    11071086
    11081087    tr_metainfoFree( inf );
  • branches/1.4x/libtransmission/torrent.h

    r7069 r7176  
    2323 *****************************************************************************/
    2424
     25#ifndef __TRANSMISSION__
     26#error only libtransmission should #include this header.
     27#endif
     28
    2529#ifndef TR_TORRENT_H
    2630#define TR_TORRENT_H 1
    2731
     32struct tr_bandwidth;
    2833struct tr_ratecontrol;
    2934
     
    168173    tr_info                  info;
    169174
    170     int                      uploadLimit;
    171     tr_speedlimit            uploadLimitMode;
    172     int                      downloadLimit;
    173     tr_speedlimit            downloadLimitMode;
     175    tr_speedlimit            speedLimitMode[2];
    174176
    175177    struct tr_ratecontrol *  swarmSpeed;
     
    216218    void *                     completeness_func_user_data;
    217219
    218     unsigned int               isRunning  : 1;
    219     unsigned int               isDeleting : 1;
     220    tr_bool                    isRunning;
     221    tr_bool                    isDeleting;
    220222
    221223    uint16_t                   maxConnectedPeers;
     
    230232    int                        uniqueId;
    231233
    232     /* the rate at which pieces are being transferred between client and
    233      * its peers.  protocol overhead is NOT included; only the piece data */
    234     struct tr_ratecontrol    * pieceSpeed[2];
    235 
    236     /* the rate at which bytes are being sent between client and peers */
    237     struct tr_ratecontrol    * rawSpeed[2];
     234    struct tr_bandwidth      * bandwidth;
    238235};
    239236
  • branches/1.4x/libtransmission/transmission.h

    r7069 r7176  
    5353typedef uint32_t tr_piece_index_t;
    5454typedef uint64_t tr_block_index_t;
     55typedef uint8_t tr_bool;
     56
    5557
    5658/**
  • branches/1.4x/libtransmission/webseed.c

    r7078 r7176  
    2727struct tr_webseed
    2828{
    29     unsigned int        busy : 1;
    30     unsigned int        dead : 1;
     29    tr_bool             busy;
     30    tr_bool             dead;
    3131
    3232    uint8_t             hash[SHA_DIGEST_LENGTH];
     
    5252***/
    5353
    54 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0 };
     54static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0 };
    5555
    5656static void
     
    9494    e.eventType = TR_PEER_CLIENT_GOT_DATA;
    9595    e.length = length;
     96    e.wasPieceData = TRUE;
     97
    9698    publish( w, &e );
    9799}
Note: See TracChangeset for help on using the changeset viewer.