Changeset 7176
- Timestamp:
- Nov 29, 2008, 4:44:24 PM (12 years ago)
- Location:
- branches/1.4x
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.4x/Transmission.xcodeproj/project.pbxproj
r7025 r7176 86 86 A219798B0D07B78400438EA7 /* GroupToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = A219798A0D07B78400438EA7 /* GroupToolbarItem.m */; }; 87 87 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 */; }; 88 90 A22180980D148A71007D09ED /* GroupsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A22180970D148A71007D09ED /* GroupsWindowController.m */; }; 89 91 A22180B60D148F0F007D09ED /* GroupsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A22180B50D148F0F007D09ED /* GroupsWindow.xib */; }; … … 124 126 A259317E0A73B2CC002F4FE7 /* TransmissionHelp in Resources */ = {isa = PBXBuildFile; fileRef = A259316A0A73B2CC002F4FE7 /* TransmissionHelp */; }; 125 127 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 */; }; 126 130 A25D2CBD0CF4C73E0096A262 /* stats.c in Sources */ = {isa = PBXBuildFile; fileRef = A25D2CBB0CF4C7190096A262 /* stats.c */; }; 127 131 A25D2CBE0CF4C73E0096A262 /* stats.h in Headers */ = {isa = PBXBuildFile; fileRef = A25D2CBA0CF4C7190096A262 /* stats.h */; }; … … 477 481 A219798A0D07B78400438EA7 /* GroupToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GroupToolbarItem.m; path = macosx/GroupToolbarItem.m; sourceTree = "<group>"; }; 478 482 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>"; }; 479 485 A22180960D148A71007D09ED /* GroupsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupsWindowController.h; path = macosx/GroupsWindowController.h; sourceTree = "<group>"; }; 480 486 A22180970D148A71007D09ED /* GroupsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GroupsWindowController.m; path = macosx/GroupsWindowController.m; sourceTree = "<group>"; }; … … 523 529 A25AFDE70D1038AD0092A1BA /* MenuLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuLabel.h; path = macosx/MenuLabel.h; sourceTree = "<group>"; }; 524 530 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>"; }; 525 533 A25D2CBA0CF4C7190096A262 /* stats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stats.h; path = libtransmission/stats.h; sourceTree = "<group>"; }; 526 534 A25D2CBB0CF4C7190096A262 /* stats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = stats.c; path = libtransmission/stats.c; sourceTree = "<group>"; }; … … 1121 1129 4D36BA630CA2F00800A63CA5 /* handshake.c */, 1122 1130 4D36BA640CA2F00800A63CA5 /* handshake.h */, 1131 A25B40080EDCB1B8005DD3F6 /* iobuf.c */, 1132 A25B40090EDCB1B8005DD3F6 /* iobuf.h */, 1123 1133 4D36BA650CA2F00800A63CA5 /* peer-io.c */, 1124 1134 4D36BA660CA2F00800A63CA5 /* peer-io.h */, … … 1158 1168 BEFC1E000C07861A00B0BB3C /* ratecontrol.h */, 1159 1169 BEFC1E010C07861A00B0BB3C /* ratecontrol.c */, 1170 A21FBBA90EDA78C300BC3C51 /* bandwidth.h */, 1171 A21FBBAA0EDA78C300BC3C51 /* bandwidth.c */, 1160 1172 BEFC1E020C07861A00B0BB3C /* platform.h */, 1161 1173 BEFC1E030C07861A00B0BB3C /* platform.c */, … … 1429 1441 A2DF58590DE4B2B1000795D5 /* JSON_parser.h in Headers */, 1430 1442 A25E03E20E4015380086C225 /* tr-getopt.h in Headers */, 1443 A21FBBAB0EDA78C300BC3C51 /* bandwidth.h in Headers */, 1444 A25B400B0EDCB1B8005DD3F6 /* iobuf.h in Headers */, 1431 1445 ); 1432 1446 runOnlyForDeploymentPostprocessing = 0; … … 1841 1855 A25E03E30E4015380086C225 /* tr-getopt.c in Sources */, 1842 1856 4DB74F080E8CD75100AEB1A8 /* wildmat.c in Sources */, 1857 A21FBBAC0EDA78C300BC3C51 /* bandwidth.c in Sources */, 1858 A25B400A0EDCB1B8005DD3F6 /* iobuf.c in Sources */, 1843 1859 ); 1844 1860 runOnlyForDeploymentPostprocessing = 0; -
branches/1.4x/libtransmission/Makefile.am
r7103 r7176 13 13 14 14 libtransmission_a_SOURCES = \ 15 bandwidth.c \ 15 16 bencode.c \ 16 17 blocklist.c \ … … 24 25 handshake.c \ 25 26 inout.c \ 27 iobuf.c \ 26 28 json.c \ 27 29 JSON_parser.c \ … … 57 59 58 60 noinst_HEADERS = \ 61 bandwidth.h \ 59 62 bencode.h \ 60 63 blocklist.h \ … … 68 71 handshake.h \ 69 72 inout.h \ 73 iobuf.h \ 70 74 json.h \ 71 75 JSON_parser.h \ -
branches/1.4x/libtransmission/handshake.c
r6988 r7176 25 25 #include "crypto.h" 26 26 #include "handshake.h" 27 #include "iobuf.h" 27 28 #include "peer-io.h" 28 29 #include "peer-mgr.h" … … 89 90 struct tr_handshake 90 91 { 91 unsigned int havePeerID : 1;92 unsigned int haveSentBitTorrentHandshake : 1;92 tr_bool havePeerID; 93 tr_bool haveSentBitTorrentHandshake; 93 94 tr_peerIo * io; 94 95 tr_crypto * crypto; … … 334 335 /* send it */ 335 336 setReadState( handshake, AWAITING_YB ); 336 tr_peerIoWriteBuf( handshake->io, outbuf );337 tr_peerIoWriteBuf( handshake->io, outbuf, FALSE ); 337 338 338 339 /* cleanup */ … … 486 487 tr_cryptoDecryptInit( handshake->crypto ); 487 488 setReadState( handshake, AWAITING_VC ); 488 tr_peerIoWriteBuf( handshake->io, outbuf );489 tr_peerIoWriteBuf( handshake->io, outbuf, FALSE ); 489 490 490 491 /* cleanup */ … … 712 713 int msgSize; 713 714 uint8_t * msg = buildHandshakeMessage( handshake, &msgSize ); 714 tr_peerIoWrite( handshake->io, msg, msgSize );715 tr_peerIoWrite( handshake->io, msg, msgSize, FALSE ); 715 716 tr_free( msg ); 716 717 handshake->haveSentBitTorrentHandshake = 1; … … 780 781 781 782 setReadState( handshake, AWAITING_PAD_A ); 782 tr_peerIoWrite( handshake->io, outbuf, walk - outbuf );783 tr_peerIoWrite( handshake->io, outbuf, walk - outbuf, FALSE ); 783 784 return READ_NOW; 784 785 } … … 992 993 993 994 /* send it out */ 994 tr_peerIoWriteBuf( handshake->io, outbuf );995 tr_peerIoWriteBuf( handshake->io, outbuf, FALSE ); 995 996 evbuffer_free( outbuf ); 996 997 … … 1029 1030 1030 1031 static ReadState 1031 canRead( struct bufferevent * evin, 1032 void * arg ) 1033 { 1034 tr_handshake * handshake = (tr_handshake *) arg; 1035 struct evbuffer * inbuf = EVBUFFER_INPUT ( evin ); 1032 canRead( struct tr_iobuf * iobuf, void * arg, size_t * piece ) 1033 { 1034 tr_handshake * handshake = arg; 1035 struct evbuffer * inbuf = tr_iobuf_input( iobuf ); 1036 1036 ReadState ret; 1037 1037 int readyForMore = TRUE; 1038 1039 /* no piece data in handshake */ 1040 *piece = 0; 1038 1041 1039 1042 dbgmsg( handshake, "handling canRead; state is [%s]", … … 1137 1140 1138 1141 static void 1139 gotError( struct bufferevent * evbuf UNUSED,1140 short 1141 void *arg )1142 gotError( struct tr_iobuf * iobuf UNUSED, 1143 short what, 1144 void * arg ) 1142 1145 { 1143 1146 tr_handshake * handshake = (tr_handshake *) arg; … … 1157 1160 handshake->haveSentBitTorrentHandshake = 1; 1158 1161 setReadState( handshake, AWAITING_HANDSHAKE ); 1159 tr_peerIoWrite( handshake->io, msg, msgSize );1162 tr_peerIoWrite( handshake->io, msg, msgSize, FALSE ); 1160 1163 tr_free( msg ); 1161 1164 } … … 1179 1182 { 1180 1183 tr_handshake * handshake; 1181 1182 tr_peerIoSetBandwidthUnlimited( io, TR_UP );1183 tr_peerIoSetBandwidthUnlimited( io, TR_DOWN );1184 1184 1185 1185 handshake = tr_new0( tr_handshake, 1 ); … … 1204 1204 handshake->haveSentBitTorrentHandshake = 1; 1205 1205 setReadState( handshake, AWAITING_HANDSHAKE ); 1206 tr_peerIoWrite( handshake->io, msg, msgSize );1206 tr_peerIoWrite( handshake->io, msg, msgSize, FALSE ); 1207 1207 tr_free( msg ); 1208 1208 } -
branches/1.4x/libtransmission/net.c
r6944 r7176 123 123 } 124 124 125 int 126 tr_netOpenTCP( const struct in_addr * addr, 127 tr_port_t port ) 125 static void 126 setSndBuf( 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 139 int 140 tr_netOpenTCP( tr_session * session, 141 const struct in_addr * addr, 142 tr_port_t port ) 128 143 { 129 144 int s; … … 133 148 if( ( s = createSocket( type ) ) < 0 ) 134 149 return -1; 150 151 setSndBuf( session, s ); 135 152 136 153 memset( &sock, 0, sizeof( sock ) ); … … 198 215 199 216 int 200 tr_netAccept( int b, 201 struct in_addr * addr, 202 tr_port_t * port ) 203 { 204 return makeSocketNonBlocking( tr_fdSocketAccept( b, addr, port ) ); 217 tr_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; 205 225 } 206 226 -
branches/1.4x/libtransmission/net.h
r6924 r7176 22 22 * DEALINGS IN THE SOFTWARE. 23 23 *****************************************************************************/ 24 25 #ifndef __TRANSMISSION__ 26 #error only libtransmission should #include this header. 27 #endif 24 28 25 29 #ifndef _TR_NET_H_ … … 59 63 struct in_addr; 60 64 struct sockaddr_in; 65 struct tr_session; 61 66 62 67 /*********************************************************************** … … 70 75 * Sockets 71 76 **********************************************************************/ 72 int tr_netOpenTCP( const struct in_addr * addr, 77 int tr_netOpenTCP( struct tr_handle * session, 78 const struct in_addr * addr, 73 79 tr_port_t port ); 74 80 75 81 int tr_netBindTCP( int port ); 76 82 77 int tr_netAccept( int s, 78 struct in_addr *, 79 tr_port_t * ); 83 int tr_netAccept( struct tr_handle * session, 84 int bound, 85 struct in_addr * setme_addr, 86 tr_port_t * setme_port ); 80 87 81 88 int tr_netSetTOS( int s, -
branches/1.4x/libtransmission/peer-common.h
r6876 r7176 10 10 * $Id$ 11 11 */ 12 13 #ifndef __TRANSMISSION__ 14 #error only libtransmission should #include this header. 15 #endif 12 16 13 17 #ifndef TR_PEER_H … … 50 54 { 51 55 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 */ 57 62 } 58 63 tr_peer_event; -
branches/1.4x/libtransmission/peer-io.c
r7069 r7176 27 27 28 28 #include "transmission.h" 29 #include "bandwidth.h" 29 30 #include "crypto.h" 31 #include "iobuf.h" 32 #include "list.h" 30 33 #include "net.h" 31 34 #include "peer-io.h" 32 #include "ratecontrol.h"33 35 #include "trevent.h" 34 36 #include "utils.h" 35 37 38 #define MAGIC_NUMBER 206745 36 39 #define IO_TIMEOUT_SECS 8 37 40 38 41 static size_t 39 addPacketOverhead( size_t d )42 getPacketOverhead( size_t d ) 40 43 { 41 44 /** … … 57 60 static const double assumed_payload_data_rate = 94.0; 58 61 59 return (size_t)( d * ( 100.0 / assumed_payload_data_rate ) );62 return (size_t)( d * ( 100.0 / assumed_payload_data_rate ) - d ); 60 63 } 61 64 … … 70 73 } while( 0 ) 71 74 72 struct tr_bandwidth 73 { 74 unsigned int isUnlimited : 1; 75 size_t bytesUsed; 76 size_t bytesLeft; 75 struct tr_datatype 76 { 77 tr_bool isPieceData; 78 size_t length; 77 79 }; 78 80 79 81 struct tr_peerIo 80 82 { 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; 111 114 }; 112 113 /**114 ***115 **/116 117 static void118 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 void161 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 else170 {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 else178 {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 }185 115 186 116 /*** … … 189 119 190 120 static void 191 didWriteWrapper( struct bufferevent * e, 192 void * vio ) 121 didWriteWrapper( struct tr_iobuf * iobuf, 122 size_t bytes_transferred, 123 void * vio ) 193 124 { 194 125 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 ) 201 128 { 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 ) ); 212 145 } 213 146 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 ); 218 149 } 219 150 220 151 static void 221 canReadWrapper( struct bufferevent * e, 222 void * vio ) 152 canReadWrapper( struct tr_iobuf * iobuf, 153 size_t bytes_transferred UNUSED, 154 void * vio ) 223 155 { 224 156 int done = 0; … … 226 158 tr_peerIo * io = vio; 227 159 tr_session * session = io->session; 228 const size_t len = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );229 160 230 161 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 }248 162 249 163 /* try to consume the input buffer */ … … 254 168 while( !done && !err ) 255 169 { 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 } 257 182 258 183 switch( ret ) 259 184 { 260 185 case READ_NOW: 261 if( EVBUFFER_LENGTH( e->input ))186 if( EVBUFFER_LENGTH( tr_iobuf_input( iobuf ))) 262 187 continue; 263 188 done = 1; … … 276 201 tr_globalUnlock( session ); 277 202 } 278 279 if( !err )280 io->bufferSize[TR_DOWN] = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );281 203 } 282 204 283 205 static void 284 gotErrorWrapper( struct bufferevent * e,285 short 286 void *userData )206 gotErrorWrapper( struct tr_iobuf * iobuf, 207 short what, 208 void * userData ) 287 209 { 288 210 tr_peerIo * c = userData; 289 211 290 212 if( c->gotError ) 291 c->gotError( e, what, c->userData );213 c->gotError( iobuf, what, c->userData ); 292 214 } 293 215 … … 299 221 bufevNew( tr_peerIo * io ) 300 222 { 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 235 static int 236 isPeerIo( const tr_peerIo * io ) 237 { 238 return ( io != NULL ) && ( io->magicNumber == MAGIC_NUMBER ); 314 239 } 315 240 … … 328 253 329 254 io = tr_new0( tr_peerIo, 1 ); 255 io->magicNumber = MAGIC_NUMBER; 330 256 io->crypto = tr_cryptoNew( torrentHash, isIncoming ); 331 257 io->session = session; … … 336 262 io->timeout = IO_TIMEOUT_SECS; 337 263 io->timeCreated = time( NULL ); 338 io->output = evbuffer_new( );339 io->bandwidth[TR_UP].isUnlimited = 1;340 io->bandwidth[TR_DOWN].isUnlimited = 1;341 264 bufevNew( io ); 265 tr_peerIoSetBandwidth( io, session->bandwidth ); 342 266 return io; 343 267 } … … 371 295 assert( torrentHash ); 372 296 373 socket = tr_netOpenTCP( in_addr, port );297 socket = tr_netOpenTCP( session, in_addr, port ); 374 298 375 299 return socket < 0 … … 383 307 tr_peerIo * io = vio; 384 308 385 evbuffer_free( io->output);386 bufferevent_free( io->bufev);309 tr_peerIoSetBandwidth( io, NULL ); 310 tr_iobuf_free( io->iobuf ); 387 311 tr_netClose( io->socket ); 388 312 tr_cryptoFree( io->crypto ); 313 tr_list_free( &io->output_datatypes, tr_free ); 314 315 io->magicNumber = 0xDEAD; 389 316 tr_free( io ); 390 317 } … … 405 332 tr_peerIoGetSession( tr_peerIo * io ) 406 333 { 407 assert( i o);334 assert( isPeerIo( io ) ); 408 335 assert( io->session ); 409 336 … … 415 342 uint16_t * port ) 416 343 { 417 assert( i o);344 assert( isPeerIo( io ) ); 418 345 419 346 if( port ) … … 443 370 tr_peerIoTryRead( tr_peerIo * io ) 444 371 { 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 ); 447 374 } 448 375 … … 476 403 tr_netClose( io->socket ); 477 404 478 io->socket = tr_netOpenTCP( &io->in_addr, io->port );405 io->socket = tr_netOpenTCP( io->session, &io->in_addr, io->port ); 479 406 480 407 if( io->socket >= 0 ) 481 408 { 409 tr_bandwidth * bandwidth = io->bandwidth; 410 tr_peerIoSetBandwidth( io, NULL ); 411 482 412 tr_netSetTOS( io->socket, io->session->peerSocketTOS ); 483 484 bufferevent_free( io->bufev ); 413 tr_iobuf_free( io->iobuf ); 485 414 bufevNew( io ); 415 416 tr_peerIoSetBandwidth( io, bandwidth ); 486 417 return 0; 487 418 } … … 495 426 { 496 427 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 ); 499 430 } 500 431 … … 507 438 const uint8_t * hash ) 508 439 { 509 assert( i o);440 assert( isPeerIo( io ) ); 510 441 511 442 tr_cryptoSetTorrentHash( io->crypto, hash ); … … 515 446 tr_peerIoGetTorrentHash( tr_peerIo * io ) 516 447 { 517 assert( i o);448 assert( isPeerIo( io ) ); 518 449 assert( io->crypto ); 519 450 … … 524 455 tr_peerIoHasTorrentHash( const tr_peerIo * io ) 525 456 { 526 assert( i o);457 assert( isPeerIo( io ) ); 527 458 assert( io->crypto ); 528 459 … … 538 469 const uint8_t * peer_id ) 539 470 { 540 assert( i o);471 assert( isPeerIo( io ) ); 541 472 542 473 if( ( io->peerIdIsSet = peer_id != NULL ) ) … … 549 480 tr_peerIoGetPeersId( const tr_peerIo * io ) 550 481 { 551 assert( i o);482 assert( isPeerIo( io ) ); 552 483 assert( io->peerIdIsSet ); 553 484 … … 563 494 int flag ) 564 495 { 565 assert( i o);496 assert( isPeerIo( io ) ); 566 497 assert( flag == 0 || flag == 1 ); 567 498 … … 573 504 int flag ) 574 505 { 575 assert( i o);506 assert( isPeerIo( io ) ); 576 507 assert( flag == 0 || flag == 1 ); 577 508 … … 582 513 tr_peerIoSupportsLTEP( const tr_peerIo * io ) 583 514 { 584 assert( i o);515 assert( isPeerIo( io ) ); 585 516 586 517 return io->extendedProtocolSupported; … … 590 521 tr_peerIoSupportsFEXT( const tr_peerIo * io ) 591 522 { 592 assert( i o);523 assert( isPeerIo( io ) ); 593 524 594 525 return io->fastPeersSupported; … … 599 530 **/ 600 531 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; 532 static size_t 533 getDesiredOutputBufferSize( 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 ); 608 543 } 609 544 … … 611 546 tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ) 612 547 { 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; 625 551 626 552 if( desiredLen > currentLen ) 627 553 freeSpace = desiredLen - currentLen; 628 else629 freeSpace = 0;630 554 631 555 return freeSpace; … … 633 557 634 558 void 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 ); 559 tr_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 ); 669 574 } 670 575 … … 683 588 int encryptionMode ) 684 589 { 685 assert( i o);590 assert( isPeerIo( io ) ); 686 591 assert( encryptionMode == PEER_ENCRYPTION_NONE 687 592 || encryptionMode == PEER_ENCRYPTION_RC4 ); … … 700 605 **/ 701 606 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 { 607 void 608 tr_peerIoWrite( tr_peerIo * io, 609 const void * writeme, 610 size_t writemeLen, 611 int isPieceData ) 612 { 613 struct tr_datatype * datatype; 724 614 assert( tr_amInEventThread( io->session ) ); 725 615 dbgmsg( io, "adding %zu bytes into io->output", writemeLen ); 726 616 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 626 void 627 tr_peerIoWriteBuf( tr_peerIo * io, 628 struct evbuffer * buf, 629 int isPieceData ) 738 630 { 739 631 const size_t n = EVBUFFER_LENGTH( buf ); 740 632 741 tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n );633 tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n, isPieceData ); 742 634 evbuffer_drain( buf, n ); 743 635 } … … 875 767 return time( NULL ) - io->timeCreated; 876 768 } 877 -
branches/1.4x/libtransmission/peer-io.h
r7055 r7176 11 11 */ 12 12 13 #ifndef __TRANSMISSION__ 14 #error only libtransmission should #include this header. 15 #endif 16 13 17 #ifndef TR_PEER_IO_H 14 18 #define TR_PEER_IO_H … … 20 24 struct in_addr; 21 25 struct evbuffer; 22 struct bufferevent; 23 struct tr_handle; 26 struct tr_bandwidth; 24 27 struct tr_crypto; 28 struct tr_iobuf; 25 29 typedef struct tr_peerIo tr_peerIo; 26 30 … … 29 33 **/ 30 34 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, 35 tr_peerIo* tr_peerIoNewOutgoing( struct tr_handle * session, 36 const struct in_addr * addr, 37 int port, 38 const uint8_t * torrentHash ); 39 40 tr_peerIo* tr_peerIoNewIncoming( struct tr_handle * session, 39 41 const struct in_addr * addr, 40 42 uint16_t port, … … 109 111 ReadState; 110 112 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 113 typedef ReadState ( *tr_can_read_cb )( struct tr_iobuf * iobuf, 114 void * user_data, 115 size_t * setme_piece_byte_count ); 116 117 typedef void ( *tr_did_write_cb )( tr_peerIo * io, 118 size_t bytesWritten, 119 int wasPieceData, 120 void * userData ); 121 122 typedef void ( *tr_net_error_cb )( struct tr_iobuf * ev, 123 short what, 124 void * userData ); 125 126 void 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 136 void tr_peerIoWrite ( tr_peerIo * io, 137 const void * writeme, 138 size_t writemeLen, 139 int isPieceData ); 140 141 void tr_peerIoWriteBuf ( tr_peerIo * io, 142 struct evbuffer * buf, 143 int isPieceData ); 136 144 137 145 /** … … 196 204 **/ 197 205 198 size_t tr_peerIoGetBandwidthUsed( const tr_peerIo * io,199 tr_direction direction );200 201 206 size_t tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ); 202 207 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 ); 208 void tr_peerIoSetBandwidth( tr_peerIo * io, 209 struct tr_bandwidth * bandwidth ); 210 211 void tr_peerIoBandwidthUsed( tr_peerIo * io, 212 tr_direction direction, 213 size_t byteCount, 214 int isPieceData ); 215 209 216 210 217 -
branches/1.4x/libtransmission/peer-mgr-private.h
r7055 r7176 10 10 * $Id$ 11 11 */ 12 13 #ifndef __TRANSMISSION__ 14 #error only libtransmission should #include this header. 15 #endif 12 16 13 17 #ifndef TR_PEER_MGR_PRIVATE_H … … 24 28 #include "publish.h" /* tr_publisher_tag */ 25 29 30 struct tr_bandwidth; 26 31 struct tr_bitfield; 27 32 struct tr_peerIo; 28 33 struct tr_peermsgs; 29 struct tr_ratecontrol;30 34 31 35 enum … … 38 42 typedef struct tr_peer 39 43 { 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; 45 49 46 50 /* number of bad pieces they've contributed to */ … … 68 72 tr_publisher_tag msgsTag; 69 73 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; 73 75 } 74 76 tr_peer; -
branches/1.4x/libtransmission/peer-mgr.c
r7116 r7176 20 20 21 21 #include "transmission.h" 22 #include "bandwidth.h" 23 #include "bencode.h" 22 24 #include "blocklist.h" 23 25 #include "clients.h" … … 32 34 #include "peer-msgs.h" 33 35 #include "ptrarray.h" 34 #include "ratecontrol.h"35 36 #include "stats.h" /* tr_statsAddUploaded, tr_statsAddDownloaded */ 36 37 #include "torrent.h" … … 60 61 61 62 /* max # of peers to ask fer per torrent per reconnect pulse */ 62 MAX_RECONNECTIONS_PER_PULSE = 2,63 MAX_RECONNECTIONS_PER_PULSE = 4, 63 64 64 65 /* max number of peers to ask for per second overall. 65 66 * this throttle is to avoid overloading the router */ 66 MAX_CONNECTIONS_PER_SECOND = 4,67 MAX_CONNECTIONS_PER_SECOND = 8, 67 68 68 69 /* number of unchoked peers per torrent. 69 70 * FIXME: this probably ought to be configurable */ 70 MAX_UNCHOKED_PEERS = 1 2,71 MAX_UNCHOKED_PEERS = 14, 71 72 72 73 /* 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, 74 75 75 76 /* use for bitwise operations w/peer_atom.myflags */ … … 107 108 typedef struct 108 109 { 109 unsigned int isRunning : 1;110 tr_bool isRunning; 110 111 111 112 uint8_t hash[SHA_DIGEST_LENGTH]; … … 131 132 tr_ptrArray * incomingHandshakes; /* tr_handshake */ 132 133 tr_timer * bandwidthTimer; 133 tr_ratecontrol * globalPoolRawSpeed[2];134 134 }; 135 135 … … 323 323 324 324 static tr_peer* 325 peerConstructor( const struct in_addr * in_addr )325 peerConstructor( tr_torrent * tor, const struct in_addr * in_addr ) 326 326 { 327 327 tr_peer * p; … … 329 329 p = tr_new0( tr_peer, 1 ); 330 330 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 ); 333 332 return p; 334 333 } … … 346 345 if( peer == NULL ) 347 346 { 348 peer = peerConstructor( in_addr );347 peer = peerConstructor( torrent->tor, in_addr ); 349 348 tr_ptrArrayInsertSorted( torrent->peers, peer, peerCompare ); 350 349 } … … 368 367 tr_free( peer->client ); 369 368 370 tr_ rcClose( peer->pieceSpeed[TR_CLIENT_TO_PEER]);371 tr_rcClose( peer->pieceSpeed[TR_PEER_TO_CLIENT] ); 369 tr_bandwidthFree( peer->bandwidth ); 370 372 371 tr_free( peer ); 373 372 } … … 517 516 m->torrents = tr_ptrArrayNew( ); 518 517 m->incomingHandshakes = tr_ptrArrayNew( ); 519 m->globalPoolRawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );520 m->globalPoolRawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );521 518 m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC ); 522 519 return m; … … 529 526 530 527 tr_timerFree( &manager->bandwidthTimer ); 531 tr_rcClose( manager->globalPoolRawSpeed[TR_CLIENT_TO_PEER] );532 tr_rcClose( manager->globalPoolRawSpeed[TR_PEER_TO_CLIENT] );533 528 534 529 /* free the handshakes. Abort invokes handshakeDoneCB(), which removes … … 1017 1012 const time_t now = time( NULL ); 1018 1013 tr_torrent * tor = t->tor; 1014 1019 1015 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 ) { 1028 1026 struct peer_atom * a = getExistingAtom( t, &peer->in_addr ); 1029 1027 a->piece_data_time = now; 1030 1028 } 1029 1031 1030 break; 1032 1031 } … … 1036 1035 const time_t now = time( NULL ); 1037 1036 tr_torrent * tor = t->tor; 1037 1038 1038 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 1044 1040 /* only add this to downloadedCur if we got it from a peer -- 1045 1041 * webseeds shouldn't count against our ratio. As one tracker … … 1048 1044 * to manage the swarms, not the web server and does not fit 1049 1045 * into the jurisdiction of the tracker." */ 1050 if( peer )1046 if( peer && e->wasPieceData ) 1051 1047 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 */ 1052 1054 if( peer ) { 1053 1055 struct peer_atom * a = getExistingAtom( t, &peer->in_addr ); 1054 1056 a->piece_data_time = now; 1055 1057 } 1058 1056 1059 break; 1057 1060 } … … 1276 1279 if( !peer_id ) 1277 1280 peer->client = NULL; 1278 else 1279 { 1281 else { 1280 1282 char client[128]; 1281 1283 tr_clientForId( client, sizeof( client ), peer_id ); 1282 1284 peer->client = tr_strdup( client ); 1283 1285 } 1286 1284 1287 peer->port = port; 1285 1288 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 ); 1289 1291 1290 1292 success = TRUE; … … 1768 1770 assert( direction==TR_CLIENT_TO_PEER || direction==TR_PEER_TO_CLIENT ); 1769 1771 1770 return tr_ rcRate( peer->pieceSpeed[direction]);1772 return tr_bandwidthGetPieceSpeed( peer->bandwidth, direction ); 1771 1773 } 1772 1774 … … 1799 1801 tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ), 1800 1802 sizeof( stat->client ) ); 1801 stat->port = peer->port;1803 stat->port = ntohs( peer->port ); 1802 1804 stat->from = atom->from; 1803 1805 stat->progress = peer->progress; … … 1841 1843 struct ChokeData 1842 1844 { 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; 1846 1848 int rate; 1847 1849 tr_peer * peer; … … 1903 1905 n->isInterested = peer->peerIsInterested; 1904 1906 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; 1907 1908 } 1908 1909 } … … 2321 2322 ****/ 2322 2323 2323 static double2324 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 02343 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 #endif2349 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 set2357 * @param direction whether to allocate upload or download bandwidth2358 * @param history recent bandwidth history for these peers2359 * @param desiredAvgKB overall bandwidth goal for this set of peers2360 */2361 static void2362 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 else2386 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 = bytesUsed2398 ? ( meritBytes *2399 tr_peerIoGetBandwidthUsed( peer->io,2400 direction ) ) /2401 bytesUsed2402 : ( meritBytes / candidateCount );2403 tr_peerIoSetBandwidth( peer->io, direction, merit + welfare );2404 }2405 2406 /* cleanup */2407 tr_free( candidates );2408 }2409 2410 static size_t2411 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_t2427 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 void2443 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 2456 2324 static void 2457 2325 pumpAllPeers( tr_peerMgr * mgr ) … … 2460 2328 int i, j; 2461 2329 2462 for( i = 0; i <torrentCount; ++i )2330 for( i=0; i<torrentCount; ++i ) 2463 2331 { 2464 2332 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 ) 2466 2334 { 2467 2335 tr_peer * peer = tr_ptrArrayNth( t->peers, j ); … … 2471 2339 } 2472 2340 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 */ 2341 static int 2342 bandwidthPulse( void * vmgr ) 2343 { 2344 tr_peerMgr * mgr = vmgr; 2345 managerLock( mgr ); 2346 2496 2347 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 ); 2566 2350 pumpAllPeers( mgr ); 2567 2568 /* cleanup */2569 tr_ptrArrayFree( globalPool, NULL );2570 return allBytesUsed;2571 }2572 2573 static int2574 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 );2584 2351 2585 2352 managerUnlock( mgr ); 2586 2353 return TRUE; 2587 2354 } 2588 -
branches/1.4x/libtransmission/peer-mgr.h
r7055 r7176 10 10 * $Id$ 11 11 */ 12 13 #ifndef __TRANSMISSION__ 14 #error only libtransmission should #include this header. 15 #endif 12 16 13 17 #ifndef TR_PEER_MGR_H -
branches/1.4x/libtransmission/peer-msgs.c
r7168 r7176 25 25 #include "crypto.h" 26 26 #include "inout.h" 27 #include "iobuf.h" 27 28 #ifdef WIN32 28 29 #include "net.h" /* for ECONN */ … … 261 262 struct tr_peermsgs 262 263 { 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; 268 268 269 269 uint8_t state; … … 286 286 tr_publisher_t * publisher; 287 287 288 struct evbuffer * outBlock; /* buffer of the current piece message */289 288 struct evbuffer * outMessages; /* all the non-piece messages */ 290 289 … … 345 344 } 346 345 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 ) 348 351 349 352 /** … … 430 433 **/ 431 434 432 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0 };435 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0 }; 433 436 434 437 static void … … 484 487 static void 485 488 fireClientGotData( tr_peermsgs * msgs, 486 uint32_t length ) 489 uint32_t length, 490 int wasPieceData ) 487 491 { 488 492 tr_peer_event e = blankEvent; … … 490 494 e.length = length; 491 495 e.eventType = TR_PEER_CLIENT_GOT_DATA; 496 e.wasPieceData = wasPieceData; 492 497 publish( msgs, &e ); 493 498 } 494 499 495 500 static void 496 firePeerGotData( tr_peermsgs * msgs, 497 uint32_t length ) 501 firePeerGotData( tr_peermsgs * msgs, 502 uint32_t length, 503 int wasPieceData ) 498 504 { 499 505 tr_peer_event e = blankEvent; … … 501 507 e.length = length; 502 508 e.eventType = TR_PEER_PEER_GOT_DATA; 509 e.wasPieceData = wasPieceData; 510 503 511 publish( msgs, &e ); 504 512 } … … 906 914 **/ 907 915 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 ); 909 918 req.time_requested = time( NULL ); 910 919 reqListAppend( &msgs->clientWillAskFor, &req ); … … 918 927 struct request_list a = msgs->clientWillAskFor; 919 928 struct request_list b = msgs->clientAskedFor; 929 dbgmsg( msgs, "cancelling all requests to peer" ); 920 930 921 931 msgs->clientAskedFor = REQUEST_LIST_INIT; … … 945 955 assert( length > 0 ); 946 956 957 947 958 /* have we asked the peer for this piece? */ 948 959 req.index = pieceIndex; … … 951 962 952 963 /* 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 ); 954 966 fireCancelledReq( msgs, &req ); 967 } 955 968 956 969 /* if it's already been sent, send a cancel message too */ 957 970 if( reqListRemove( &msgs->clientAskedFor, &req ) ) { 971 dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32"\n", pieceIndex, offset, length ); 958 972 protocolSendCancel( msgs, &req ); 959 973 fireCancelledReq( msgs, &req ); … … 1029 1043 } 1030 1044 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 ); 1033 1046 1034 1047 /* does the peer prefer encrypted connections? */ … … 1300 1313 const struct peer_request * req ); 1301 1314 1302 static void1303 clientGotBytes( tr_peermsgs * msgs,1304 uint32_t byteCount )1305 {1306 msgs->info->pieceDataActivityDate = time( NULL );1307 fireClientGotData( msgs, byteCount );1308 }1309 1310 1315 static int 1311 readBtPiece( tr_peermsgs * msgs, 1312 struct evbuffer * inbuf, 1313 size_t inlen ) 1316 readBtPiece( tr_peermsgs * msgs, 1317 struct evbuffer * inbuf, 1318 size_t inlen, 1319 size_t * setme_piece_bytes_read ) 1314 1320 { 1315 1321 struct peer_request * req = &msgs->incoming.blockReq; … … 1343 1349 tr_peerIoReadBytes( msgs->io, inbuf, buf, n ); 1344 1350 evbuffer_add( msgs->incoming.block, buf, n ); 1345 clientGotBytes( msgs, n ); 1351 fireClientGotData( msgs, n, TRUE ); 1352 *setme_piece_bytes_read += n; 1346 1353 tr_free( buf ); 1347 1354 dbgmsg( msgs, "got %d bytes for block %u:%u->%u ... %d remain", … … 1540 1547 1541 1548 static 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 void1551 1549 decrementDownloadedCount( tr_peermsgs * msgs, 1552 1550 uint32_t byteCount ) … … 1635 1633 } 1636 1634 1635 static int peerPulse( void * vmsgs ); 1636 1637 static void 1638 didWrite( 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 1637 1645 static ReadState 1638 canRead( struct bufferevent * evin, 1639 void * vmsgs ) 1646 canRead( struct tr_iobuf * iobuf, void * vmsgs, size_t * piece ) 1640 1647 { 1641 1648 ReadState ret; 1642 1649 tr_peermsgs * msgs = vmsgs; 1643 struct evbuffer * in = EVBUFFER_INPUT ( evin);1650 struct evbuffer * in = tr_iobuf_input( iobuf ); 1644 1651 const size_t inlen = EVBUFFER_LENGTH( in ); 1645 1652 … … 1650 1657 else if( msgs->state == AWAITING_BT_PIECE ) 1651 1658 { 1652 ret = inlen ? readBtPiece( msgs, in, inlen ) : READ_LATER;1659 ret = inlen ? readBtPiece( msgs, in, inlen, piece ) : READ_LATER; 1653 1660 } 1654 1661 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 ); 1668 1679 1669 1680 return ret; 1670 }1671 1672 static void1673 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 );1678 1681 } 1679 1682 … … 1691 1694 ( rateToClient * 30 * 1024 ) / peer->torrent->blockSize; 1692 1695 1693 peer->minActiveRequests = 4; 1694 peer->maxActiveRequests = peer->minActiveRequests + 1695 estimatedBlocksInNext30Seconds; 1696 peer->minActiveRequests = 8; 1697 peer->maxActiveRequests = peer->minActiveRequests + estimatedBlocksInNext30Seconds; 1696 1698 return TRUE; 1697 1699 } … … 1705 1707 } 1706 1708 1709 static size_t 1710 fillOutputBuffer( 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 1707 1783 static int 1708 1784 peerPulse( void * vmsgs ) … … 1713 1789 ratePulse( msgs ); 1714 1790 1715 /*tr_peerIoTryRead( msgs->io );*/1716 1791 pumpRequestQueue( msgs, now ); 1717 1792 expireOldRequests( msgs, now ); 1718 1793 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; 1809 1797 1810 1798 return TRUE; /* loop forever */ … … 1819 1807 1820 1808 static void 1821 gotError( struct bufferevent * evbuf UNUSED,1822 short 1823 void *vmsgs )1809 gotError( struct tr_iobuf * iobuf UNUSED, 1810 short what, 1811 void * vmsgs ) 1824 1812 { 1825 1813 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 ); 1828 1815 if( what & ( EVBUFFER_EOF | EVBUFFER_ERROR ) ) 1829 1816 dbgmsg( vmsgs, "libevent got an error! what=%hd, errno=%d (%s)", … … 1843 1830 field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) ); 1844 1831 1832 #if 0 1845 1833 if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) ) 1846 1834 { … … 1848 1836 speed over a truly random sample -- let's limit the pool size to 1849 1837 the first 1000 pieces so large torrents don't bog things down */ 1850 size_t poolSize = MIN( msgs->torrent->info.pieceCount,1851 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 ); 1853 1841 1854 1842 /* 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; 1857 1846 1858 1847 /* pull random piece indices from the pool */ 1859 1848 while( ( poolSize > 0 ) && ( lazyCount < LAZY_PIECE_COUNT ) ) 1860 1849 { 1861 const int 1850 const int pos = tr_cryptoWeakRandInt( poolSize ); 1862 1851 const tr_piece_index_t piece = pool[pos]; 1863 1852 tr_bitfieldRem( field, piece ); … … 1869 1858 tr_free( pool ); 1870 1859 } 1860 #endif 1871 1861 1872 1862 tr_peerIoWriteUint32( msgs->io, out, … … 1947 1937 if( msgs->peerSupportsPex && tr_torrentAllowsPex( msgs->torrent ) ) 1948 1938 { 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 1954 1945 /* build the diffs */ 1955 1946 diffs.added = tr_new( tr_pex, newCount ); … … 1970 1961 if( diffs.addedCount || diffs.droppedCount ) 1971 1962 { 1972 int 1973 tr_benc 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; 1977 1968 struct evbuffer * out = msgs->outMessages; 1978 1969 … … 1987 1978 /* "added" */ 1988 1979 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 ) { 1991 1981 memcpy( walk, &diffs.added[i].in_addr, 4 ); walk += 4; 1992 1982 memcpy( walk, &diffs.added[i].port, 2 ); walk += 2; … … 2006 1996 /* "dropped" */ 2007 1997 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 ) { 2010 1999 memcpy( walk, &diffs.dropped[i].in_addr, 4 ); walk += 4; 2011 2000 memcpy( walk, &diffs.dropped[i].port, 2 ); walk += 2; … … 2021 2010 tr_peerIoWriteUint8 ( msgs->io, out, msgs->ut_pex_id ); 2022 2011 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 2027 2015 tr_free( benc ); 2028 2016 tr_bencFree( &val ); 2029 2017 } 2030 2018 2019 /* cleanup */ 2031 2020 tr_free( diffs.added ); 2032 2021 tr_free( diffs.dropped ); … … 2077 2066 m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS; 2078 2067 m->incoming.block = evbuffer_new( ); 2079 m->outBlock = evbuffer_new( );2080 2068 m->peerAllowedPieces = NULL; 2081 2069 m->peerAskedFor = REQUEST_LIST_INIT; … … 2092 2080 tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of 2093 2081 inactivity */ 2094 tr_peerIoSetIOFuncs( m->io, canRead, NULL, gotError, m );2082 tr_peerIoSetIOFuncs( m->io, canRead, didWrite, gotError, m ); 2095 2083 ratePulse( m ); 2096 2084 … … 2112 2100 evbuffer_free( msgs->incoming.block ); 2113 2101 evbuffer_free( msgs->outMessages ); 2114 evbuffer_free( msgs->outBlock );2115 2102 tr_free( msgs->pex ); 2116 2103 -
branches/1.4x/libtransmission/port-forwarding.c
r6795 r7176 33 33 struct tr_shared 34 34 { 35 unsigned int isEnabled : 1;36 unsigned int isShuttingDown : 1;35 tr_bool isEnabled; 36 tr_bool isShuttingDown; 37 37 38 38 tr_port_forwarding natpmpStatus; … … 43 43 int publicPort; 44 44 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; 50 50 }; 51 51 … … 146 146 break; 147 147 148 socket = tr_netAccept( s-> bindSocket, &addr, &port );148 socket = tr_netAccept( s->session, s->bindSocket, &addr, &port ); 149 149 if( socket < 0 ) 150 150 break; … … 152 152 tr_deepLog( __FILE__, __LINE__, NULL, 153 153 "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 ); 158 157 } 159 158 } … … 178 177 tr_natpmpClose( shared->natpmp ); 179 178 tr_upnpClose( shared->upnp ); 180 shared-> h->shared = NULL;179 shared->session->shared = NULL; 181 180 tr_free( shared ); 182 181 keepPulsing = 0; … … 191 190 192 191 tr_shared * 193 tr_sharedInit( tr_ handle * h,194 int isEnabled,195 int publicPort )192 tr_sharedInit( tr_session * session, 193 int isEnabled, 194 int publicPort ) 196 195 { 197 196 tr_shared * s = tr_new0( tr_shared, 1 ); 198 197 199 s-> h = h;198 s->session = session; 200 199 s->publicPort = publicPort; 201 200 s->bindPort = -1; … … 203 202 s->natpmp = tr_natpmpInit( ); 204 203 s->upnp = tr_upnpInit( ); 205 s->pulseTimer = tr_timerNew( h, sharedPulse, s, 1000 );204 s->pulseTimer = tr_timerNew( session, sharedPulse, s, 1000 ); 206 205 s->isEnabled = isEnabled ? 1 : 0; 207 206 s->upnpStatus = TR_PORT_UNMAPPED; … … 225 224 s->publicPort = port; 226 225 227 while( ( tor = tr_torrentNext( s-> h, tor ) ) )226 while( ( tor = tr_torrentNext( s->session, tor ) ) ) 228 227 tr_torrentChangeMyPort( tor ); 229 228 } -
branches/1.4x/libtransmission/session.c
r7069 r7176 22 22 23 23 #include "transmission.h" 24 #include "bandwidth.h" 24 25 #include "blocklist.h" 25 26 #include "fdlimit.h" … … 30 31 #include "platform.h" /* tr_lock */ 31 32 #include "port-forwarding.h" 32 #include "ratecontrol.h"33 33 #include "rpc-server.h" 34 34 #include "stats.h" … … 255 255 h->proxyUsername = tr_strdup( proxyUsername ); 256 256 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; 261 259 262 260 if( configDir == NULL ) … … 277 275 /* Initialize rate and file descripts controls */ 278 276 279 h->uploadLimit = uploadLimit;280 h->useUploadLimit = useUploadLimit;281 h->downloadLimit = downloadLimit;282 h->useDownloadLimit = useDownloadLimit;283 284 277 tr_fdInit( globalPeerLimit ); 285 278 h->shared = tr_sharedInit( h, isPortForwardingEnabled, publicPort ); 286 279 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 ); 287 286 288 287 /* first %s is the application name … … 444 443 445 444 void 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; 445 tr_sessionSetSpeedLimitEnabled( tr_session * session, 446 tr_direction dir, 447 int isLimited ) 448 { 449 tr_bandwidthSetLimited( session->bandwidth, dir, isLimited ); 450 } 451 452 int 453 tr_sessionIsSpeedLimitEnabled( const tr_session * session, 454 tr_direction dir ) 455 { 456 return !tr_bandwidthIsLimited( session->bandwidth, dir ); 457 } 458 459 void 460 tr_sessionSetSpeedLimit( tr_session * session, 461 tr_direction dir, 462 int desiredSpeed ) 463 { 464 tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, desiredSpeed ); 465 } 466 467 int 468 tr_sessionGetSpeedLimit( const tr_session * session, 469 tr_direction dir ) 470 { 471 return tr_bandwidthGetDesiredSpeed( session->bandwidth, dir ); 482 472 } 483 473 … … 506 496 tr_sessionGetPieceSpeed( const tr_session * session, tr_direction dir ) 507 497 { 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; 511 499 } 512 500 … … 514 502 tr_sessionGetRawSpeed( const tr_session * session, tr_direction dir ) 515 503 { 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; 519 505 } 520 506 … … 630 616 631 617 /* 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 ); 636 619 tr_lockFree( session->lock ); 637 620 for( i = 0; i < session->metainfoLookupCount; ++i ) -
branches/1.4x/libtransmission/session.h
r7069 r7176 22 22 * DEALINGS IN THE SOFTWARE. 23 23 *****************************************************************************/ 24 25 #ifndef __TRANSMISSION__ 26 #error only libtransmission should #include this header. 27 #endif 24 28 25 29 #ifndef TR_INTERNAL_H … … 49 53 }; 50 54 51 struct tr_ ratecontrol;55 struct tr_bandwidth; 52 56 53 57 struct tr_handle 54 58 { 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; 64 66 65 67 tr_encryption_mode encryptionMode; … … 85 87 char * proxyPassword; 86 88 87 int uploadLimit;88 int downloadLimit;89 90 89 struct tr_list * blocklists; 91 90 struct tr_peerMgr * peerMgr; … … 106 105 int metainfoLookupCount; 107 106 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; 111 109 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; 114 115 }; 115 116 -
branches/1.4x/libtransmission/torrent.c
r7069 r7176 33 33 34 34 #include "transmission.h" 35 #include "bandwidth.h" 35 36 #include "bencode.h" 36 37 #include "completion.h" … … 143 144 void 144 145 tr_torrentSetSpeedMode( tr_torrent * tor, 145 tr_direction dir ection,146 tr_direction dir, 146 147 tr_speedlimit mode ) 147 148 { 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 ); 152 157 } 153 158 154 159 tr_speedlimit 155 160 tr_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]; 160 167 } 161 168 162 169 void 163 170 tr_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 ); 178 175 } 179 176 180 177 int 181 178 tr_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 ); 195 182 } 196 183 … … 497 484 randomizeTiers( info ); 498 485 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 ); 503 487 504 488 tor->blockSize = getBlockSize( info->pieceSize ); … … 542 526 tr_torrentInitFilePieces( tor ); 543 527 544 tor->uploadLimit = 0;545 tor->downloadLimit = 0;546 528 tor->swarmSpeed = tr_rcInit( ); 547 529 … … 815 797 s->peersFrom ); 816 798 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 ); 821 803 822 804 usableSeeds += tor->info.webseedCount; … … 1101 1083 h->torrentCount--; 1102 1084 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 ); 1107 1086 1108 1087 tr_metainfoFree( inf ); -
branches/1.4x/libtransmission/torrent.h
r7069 r7176 23 23 *****************************************************************************/ 24 24 25 #ifndef __TRANSMISSION__ 26 #error only libtransmission should #include this header. 27 #endif 28 25 29 #ifndef TR_TORRENT_H 26 30 #define TR_TORRENT_H 1 27 31 32 struct tr_bandwidth; 28 33 struct tr_ratecontrol; 29 34 … … 168 173 tr_info info; 169 174 170 int uploadLimit; 171 tr_speedlimit uploadLimitMode; 172 int downloadLimit; 173 tr_speedlimit downloadLimitMode; 175 tr_speedlimit speedLimitMode[2]; 174 176 175 177 struct tr_ratecontrol * swarmSpeed; … … 216 218 void * completeness_func_user_data; 217 219 218 unsigned int isRunning : 1;219 unsigned int isDeleting : 1;220 tr_bool isRunning; 221 tr_bool isDeleting; 220 222 221 223 uint16_t maxConnectedPeers; … … 230 232 int uniqueId; 231 233 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; 238 235 }; 239 236 -
branches/1.4x/libtransmission/transmission.h
r7069 r7176 53 53 typedef uint32_t tr_piece_index_t; 54 54 typedef uint64_t tr_block_index_t; 55 typedef uint8_t tr_bool; 56 55 57 56 58 /** -
branches/1.4x/libtransmission/webseed.c
r7078 r7176 27 27 struct tr_webseed 28 28 { 29 unsigned int busy : 1;30 unsigned int dead : 1;29 tr_bool busy; 30 tr_bool dead; 31 31 32 32 uint8_t hash[SHA_DIGEST_LENGTH]; … … 52 52 ***/ 53 53 54 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0 };54 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0 }; 55 55 56 56 static void … … 94 94 e.eventType = TR_PEER_CLIENT_GOT_DATA; 95 95 e.length = length; 96 e.wasPieceData = TRUE; 97 96 98 publish( w, &e ); 97 99 }
Note: See TracChangeset
for help on using the changeset viewer.