Changeset 7455
- Timestamp:
- Dec 22, 2008, 12:51:14 AM (12 years ago)
- Location:
- branches/1.4x
- Files:
-
- 1 added
- 1 deleted
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.4x/configure.ac
r7378 r7455 4 4 dnl "0" for stable, supported releases 5 5 dnl these should be the only two lines you need to change 6 m4_define([user_agent_prefix], 1.41)7 m4_define([peer_id_prefix], -TR1410-)6 m4_define([user_agent_prefix],[1.41b4]) 7 m4_define([peer_id_prefix],[-TR141X-]) 8 8 9 9 AC_INIT([transmission],[user_agent_prefix],[http://trac.transmissionbt.com/newticket]) -
branches/1.4x/libtransmission/Makefile.am
r7294 r7455 110 110 clients-test \ 111 111 json-test \ 112 peer-msgs-test \ 112 113 rpc-test \ 113 test-fastset \114 114 test-peer-id \ 115 115 utils-test … … 152 152 rpc_test_LDFLAGS = ${apps_ldflags} 153 153 154 test_fastset_SOURCES = test-fastset.c155 test_fastset_LDADD = ${apps_ldadd}156 test_fastset_LDFLAGS = ${apps_ldflags}154 peer_msgs_test_SOURCES = peer-msgs-test.c 155 peer_msgs_test_LDADD = ${apps_ldadd} 156 peer_msgs_test_LDFLAGS = ${apps_ldflags} 157 157 158 158 test_peer_id_SOURCES = test-peer-id.c -
branches/1.4x/libtransmission/bandwidth.c
r7403 r7455 1 1 /* 2 * This file Copyright (C) 2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 19 19 #include "bandwidth.h" 20 20 #include "crypto.h" 21 #include " iobuf.h"21 #include "peer-io.h" 22 22 #include "ptrarray.h" 23 23 #include "utils.h" … … 100 100 tr_session * session; 101 101 tr_ptrArray * children; /* struct tr_bandwidth */ 102 tr_ptrArray * iobufs; /* struct tr_iobuf*/102 tr_ptrArray * peers; /* tr_peerIo */ 103 103 }; 104 104 … … 113 113 } 114 114 115 static int 116 isBandwidth( const tr_bandwidth * b )115 tr_bool 116 tr_isBandwidth( const tr_bandwidth * b ) 117 117 { 118 118 return ( b != NULL ) && ( b->magicNumber == MAGIC_NUMBER ); 119 }120 121 static int122 isDirection( const tr_direction dir )123 {124 return ( dir == TR_UP ) || ( dir == TR_DOWN );125 119 } 126 120 … … 135 129 b->session = session; 136 130 b->children = tr_ptrArrayNew( ); 137 b-> iobufs = tr_ptrArrayNew( );131 b->peers = tr_ptrArrayNew( ); 138 132 b->magicNumber = MAGIC_NUMBER; 139 b->band[TR_UP].honorParentLimits = 1;140 b->band[TR_DOWN].honorParentLimits = 1;133 b->band[TR_UP].honorParentLimits = TRUE; 134 b->band[TR_DOWN].honorParentLimits = TRUE; 141 135 tr_bandwidthSetParent( b, parent ); 142 136 return b; … … 146 140 tr_bandwidthFree( tr_bandwidth * b ) 147 141 { 148 assert( isBandwidth( b ) );142 assert( tr_isBandwidth( b ) ); 149 143 150 144 tr_bandwidthSetParent( b, NULL ); 151 tr_ptrArrayFree( b-> iobufs, NULL );145 tr_ptrArrayFree( b->peers, NULL ); 152 146 tr_ptrArrayFree( b->children, NULL ); 153 147 b->magicNumber = 0xDEAD; … … 163 157 tr_bandwidth * parent ) 164 158 { 165 assert( isBandwidth( b ) );159 assert( tr_isBandwidth( b ) ); 166 160 assert( b != parent ); 167 161 168 162 if( b->parent ) 169 163 { 170 assert( isBandwidth( b->parent ) );164 assert( tr_isBandwidth( b->parent ) ); 171 165 172 166 tr_ptrArrayRemoveSorted( b->parent->children, b, comparePointers ); 173 b->parent = NULL;167 b->parent = NULL; 174 168 } 175 169 176 170 if( parent ) 177 171 { 178 assert( isBandwidth( parent ) );172 assert( tr_isBandwidth( parent ) ); 179 173 assert( parent->parent != b ); 180 174 … … 187 181 tr_bandwidthHonorParentLimits( tr_bandwidth * b, 188 182 tr_direction dir, 189 inthonorParentLimits )190 { 191 assert( isBandwidth( b ) );192 assert( isDirection( dir ) );193 194 b->band[dir].honorParentLimits = honorParentLimits != 0;183 tr_bool honorParentLimits ) 184 { 185 assert( tr_isBandwidth( b ) ); 186 assert( tr_isDirection( dir ) ); 187 188 b->band[dir].honorParentLimits = honorParentLimits; 195 189 } 196 190 … … 204 198 double desiredSpeed ) 205 199 { 206 assert( isBandwidth( b ) );207 assert( isDirection( dir ) );200 assert( tr_isBandwidth( b ) ); 201 assert( tr_isDirection( dir ) ); 208 202 209 203 b->band[dir].desiredSpeed = desiredSpeed; … … 214 208 tr_direction dir ) 215 209 { 216 assert( isBandwidth( b ) );217 assert( isDirection( dir ) );210 assert( tr_isBandwidth( b ) ); 211 assert( tr_isDirection( dir ) ); 218 212 219 213 return b->band[dir].desiredSpeed; … … 223 217 tr_bandwidthSetLimited( tr_bandwidth * b, 224 218 tr_direction dir, 225 intisLimited )226 { 227 assert( isBandwidth( b ) );228 assert( isDirection( dir ) );229 230 b->band[dir].isLimited = isLimited != 0;231 } 232 233 int 219 tr_bool isLimited ) 220 { 221 assert( tr_isBandwidth( b ) ); 222 assert( tr_isDirection( dir ) ); 223 224 b->band[dir].isLimited = isLimited; 225 } 226 227 tr_bool 234 228 tr_bandwidthIsLimited( const tr_bandwidth * b, 235 229 tr_direction dir ) 236 230 { 237 assert( isBandwidth( b ) );238 assert( isDirection( dir ) );239 240 return b->band[dir].isLimited != 0;231 assert( tr_isBandwidth( b ) ); 232 assert( tr_isDirection( dir ) ); 233 234 return b->band[dir].isLimited; 241 235 } 242 236 … … 250 244 tr_direction dir, 251 245 int period_msec, 252 tr_ptrArray * iobuf_pool ) 253 { 254 assert( isBandwidth( b ) ); 255 assert( isDirection( dir ) ); 256 246 tr_ptrArray * peer_pool ) 247 { 248 assert( tr_isBandwidth( b ) ); 249 assert( tr_isDirection( dir ) ); 250 251 /* set the available bandwidth */ 257 252 if( b->band[dir].isLimited ) 258 253 { … … 269 264 } 270 265 266 /* traverse & repeat for the subtree */ 271 267 { 272 268 int i; 273 const int n = tr_ptrArraySize( b-> iobufs );269 const int n = tr_ptrArraySize( b->peers ); 274 270 for( i=0; i<n; ++i ) 275 tr_ptrArrayAppend( iobuf_pool, tr_ptrArrayNth( b->iobufs, i ) );271 tr_ptrArrayAppend( peer_pool, tr_ptrArrayNth( b->peers, i ) ); 276 272 } 277 273 278 274 #ifdef DEBUG_DIRECTION 279 275 if( ( dir == DEBUG_DIRECTION ) && ( n > 1 ) ) 280 fprintf( stderr, "bandwidth %p has %d iobufs\n", b, n );276 fprintf( stderr, "bandwidth %p has %d peers\n", b, n ); 281 277 #endif 282 278 … … 286 282 struct tr_bandwidth ** children = (struct tr_bandwidth**) tr_ptrArrayPeek( b->children, &n ); 287 283 for( i=0; i<n; ++i ) 288 allocateBandwidth( children[i], dir, period_msec, iobuf_pool );284 allocateBandwidth( children[i], dir, period_msec, peer_pool ); 289 285 } 290 286 } … … 295 291 int period_msec ) 296 292 { 297 int n;293 int i, n, peerCount; 298 294 tr_ptrArray * tmp; 299 struct tr_iobuf ** buffers; 300 const size_t chunkSize = 1024; /* arbitrary */ 301 295 struct tr_peerIo ** peers; 296 297 /* allocateBandwidth() is a helper function with two purposes: 298 * 1. allocate bandwidth to b and its subtree 299 * 2. accumulate an array of all the peerIos from b and its subtree. */ 302 300 tmp = tr_ptrArrayNew( ); 303 301 allocateBandwidth( b, dir, period_msec, tmp ); 304 buffers = (struct tr_iobuf**) tr_ptrArrayPeek( tmp, &n ); 305 306 /* loop through all the peers, reading and writing in small chunks, 307 * until we run out of bandwidth or peers. we do it this way to 308 * prevent one peer from using up all the bandwidth */ 309 while( n > 0 ) 310 { 311 int i; 312 for( i=0; i<n; ) 313 { 314 int byteCount; 315 if( dir == TR_UP ) 316 byteCount = tr_iobuf_flush_output_buffer( buffers[i], chunkSize ); 317 else 318 byteCount = tr_iobuf_tryread( buffers[i], chunkSize ); 319 if( byteCount == (int)chunkSize ) 320 ++i; 321 else 322 buffers[i] = buffers[--n]; 302 peers = (struct tr_peerIo**) tr_ptrArrayPeek( tmp, &peerCount ); 303 304 /* Stop all peers from listening for the socket to be ready for IO. 305 * See "Second phase of IO" lower in this function for more info. */ 306 for( i=0; i<peerCount; ++i ) 307 tr_peerIoSetEnabled( peers[i], dir, FALSE ); 308 309 /* First phase of IO. Tries to distribute bandwidth fairly to keep faster 310 * peers from starving the others. Loop through the peers, giving each a 311 * small chunk of bandwidth. Keep looping until we run out of bandwidth 312 * or pweers that can use it */ 313 n = peerCount; 314 i = n ? tr_cryptoWeakRandInt( n ) : 0; /* pick a random starting point */ 315 for( ; n>0; ) 316 { 317 const int increment = n==1 ? 4096 : 1024; 318 const int byteCount = tr_peerIoFlush( peers[i], dir, increment); 319 320 if( byteCount == increment ) 321 ++i; 322 else { 323 /* peer is done writing for now; move it to the end of the list */ 324 tr_peerIo * tmp = peers[i]; 325 peers[i] = peers[n-1]; 326 peers[n-1] = tmp; 327 --n; 323 328 } 324 } 329 330 assert( i <= n ); 331 if( i == n ) 332 i = 0; 333 } 334 335 /* Second phase of IO. To help us scale in high bandwidth situations, 336 * enable on-demand IO for peers with bandwidth left to burn. 337 * This on-demand IO is enabled until (1) the peer runs out of bandwidth, 338 * or (2) the next tr_bandwidthAllocate() call, when we start over again. */ 339 for( i=0; i<peerCount; ++i ) 340 if( tr_peerIoHasBandwidthLeft( peers[i], dir ) ) 341 tr_peerIoSetEnabled( peers[i], dir, TRUE ); 325 342 326 343 /* cleanup */ … … 333 350 334 351 void 335 tr_bandwidthAdd Buffer( tr_bandwidth* b,336 struct tr_iobuf * iobuf)337 { 338 assert( isBandwidth( b ) );339 assert( iobuf);340 341 tr_ptrArrayInsertSorted( b-> iobufs, iobuf, comparePointers );342 } 343 344 void 345 tr_bandwidthRemove Buffer( tr_bandwidth* b,346 struct tr_iobuf * iobuf)347 { 348 assert( isBandwidth( b ) );349 assert( iobuf);350 351 tr_ptrArrayRemoveSorted( b-> iobufs, iobuf, comparePointers );352 tr_bandwidthAddPeer( tr_bandwidth * b, 353 tr_peerIo * peerIo ) 354 { 355 assert( tr_isBandwidth( b ) ); 356 assert( tr_isPeerIo( peerIo ) ); 357 358 tr_ptrArrayInsertSorted( b->peers, peerIo, comparePointers ); 359 } 360 361 void 362 tr_bandwidthRemovePeer( tr_bandwidth * b, 363 tr_peerIo * peerIo ) 364 { 365 assert( tr_isBandwidth( b ) ); 366 assert( tr_isPeerIo( peerIo ) ); 367 368 tr_ptrArrayRemoveSorted( b->peers, peerIo, comparePointers ); 352 369 } 353 370 … … 361 378 size_t byteCount ) 362 379 { 363 assert( isBandwidth( b ) );364 assert( isDirection( dir ) );380 assert( tr_isBandwidth( b ) ); 381 assert( tr_isDirection( dir ) ); 365 382 366 383 if( b ) … … 379 396 tr_bandwidthGetRawSpeed( const tr_bandwidth * b, tr_direction dir ) 380 397 { 381 assert( isBandwidth( b ) );382 assert( isDirection( dir ) );398 assert( tr_isBandwidth( b ) ); 399 assert( tr_isDirection( dir ) ); 383 400 384 401 return getSpeed( &b->band[dir].raw, HISTORY_MSEC ); … … 388 405 tr_bandwidthGetPieceSpeed( const tr_bandwidth * b, tr_direction dir ) 389 406 { 390 assert( isBandwidth( b ) );391 assert( isDirection( dir ) );407 assert( tr_isBandwidth( b ) ); 408 assert( tr_isDirection( dir ) ); 392 409 393 410 return getSpeed( &b->band[dir].piece, HISTORY_MSEC ); … … 398 415 tr_direction dir, 399 416 size_t byteCount, 400 intisPieceData )417 tr_bool isPieceData ) 401 418 { 402 419 struct tr_band * band; 403 420 size_t oldBytesLeft; 404 421 405 assert( isBandwidth( b ) );406 assert( isDirection( dir ) );422 assert( tr_isBandwidth( b ) ); 423 assert( tr_isDirection( dir ) ); 407 424 408 425 band = &b->band[dir]; -
branches/1.4x/libtransmission/bandwidth.h
r7177 r7455 1 1 /* 2 * This file Copyright (C) 2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 59 59 * bandwidth they can safely use. 60 60 */ 61 61 62 typedef struct tr_bandwidth tr_bandwidth; 63 64 struct tr_peerIo; 62 65 63 66 /** … … 72 75 /** @brief destroy a tr_bandwidth object */ 73 76 void tr_bandwidthFree ( tr_bandwidth * bandwidth ); 77 78 /** @brief test to see if the pointer refers to a live bandwidth object */ 79 tr_bool tr_isBandwidth ( const tr_bandwidth * bandwidth ); 74 80 75 81 /****** … … 98 104 void tr_bandwidthSetLimited ( tr_bandwidth * bandwidth, 99 105 tr_direction direction, 100 intisLimited );106 tr_bool isLimited ); 101 107 102 108 /** 103 109 * @return nonzero if this bandwidth throttles its iobufs' speeds 104 110 */ 105 inttr_bandwidthIsLimited ( const tr_bandwidth * bandwidth,111 tr_bool tr_bandwidthIsLimited ( const tr_bandwidth * bandwidth, 106 112 tr_direction direction ); 107 113 … … 143 149 tr_direction direction, 144 150 size_t byteCount, 145 intisPieceData );151 tr_bool isPieceData ); 146 152 147 153 /****** … … 160 166 void tr_bandwidthHonorParentLimits ( tr_bandwidth * bandwidth, 161 167 tr_direction direction, 162 intisEnabled );168 tr_bool isEnabled ); 163 169 164 170 /****** … … 167 173 168 174 /** 169 * @brief add a n iobuf to this bandwidth's list of iobufs.175 * @brief add a tr_peerIo to this bandwidth's list. 170 176 * They will be notified when more bandwidth is made available for them to consume. 171 177 */ 172 void tr_bandwidthAdd Buffer( tr_bandwidth * bandwidth,173 struct tr_ iobuf * iobuf);178 void tr_bandwidthAddPeer ( tr_bandwidth * bandwidth, 179 struct tr_peerIo * peerIo ); 174 180 175 181 /** 176 182 * @brief remove an iobuf from this bandwidth's list of iobufs. 177 183 */ 178 void tr_bandwidthRemove Buffer( tr_bandwidth * bandwidth,179 struct tr_ iobuf * iobuf);184 void tr_bandwidthRemovePeer ( tr_bandwidth * bandwidth, 185 struct tr_peerIo * peerIo ); 180 186 181 187 #endif -
branches/1.4x/libtransmission/bencode-test.c
r6842 r7455 397 397 int i; 398 398 399 if( ( i = testInt( ) ))399 if(( i = testInt( ))) 400 400 return i; 401 401 402 if( ( i = testStr( ) ))402 if(( i = testStr( ))) 403 403 return i; 404 404 405 if( ( i = testParse( ) ))405 if(( i = testParse( ))) 406 406 return i; 407 407 408 if( ( i = testJSON( ) ))408 if(( i = testJSON( ))) 409 409 return i; 410 410 -
branches/1.4x/libtransmission/fastresume.c
r6896 r7455 55 55 #include "completion.h" 56 56 #include "fastresume.h" 57 #include "net.h" 57 58 #include "peer-mgr.h" 58 59 #include "platform.h" -
branches/1.4x/libtransmission/handshake.c
r7341 r7455 1 1 /* 2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 25 25 #include "crypto.h" 26 26 #include "handshake.h" 27 #include "iobuf.h"28 27 #include "peer-io.h" 29 28 #include "peer-mgr.h" … … 34 33 /* enable LibTransmission extension protocol */ 35 34 #define ENABLE_LTEP * / 36 37 /* enable fast peers extension protocol */ 38 /* #define ENABLE_FASTPEER */ 35 /* fast extensions */ 36 #define ENABLE_FAST * / 39 37 40 38 /*** … … 73 71 #endif 74 72 75 #ifdef ENABLE_FAST PEER76 #define HANDSHAKE_HAS_FASTEXT( bits ) ( ( ( bits )[7] & 0x04 ) ? 1 : 0 ) 77 #define HANDSHAKE_SET_FASTEXT( bits ) ( ( bits )[7] |= 0x04 ) 78 #else 79 #define HANDSHAKE_HAS_FASTEXT( bits ) ( 0 ) 80 #define HANDSHAKE_SET_FASTEXT( bits ) ( (void)0 ) 81 #endif 73 #ifdef ENABLE_FAST 74 #define HANDSHAKE_HAS_FASTEXT( bits ) ( ( ( bits )[7] & 0x04 ) ? 1 : 0 ) 75 #define HANDSHAKE_SET_FASTEXT( bits ) ( ( bits )[7] |= 0x04 ) 76 #else 77 #define HANDSHAKE_HAS_FASTEXT( bits ) ( 0 ) 78 #define HANDSHAKE_SET_FASTEXT( bits ) ( (void)0 ) 79 #endif 82 80 83 81 /* http://www.azureuswiki.com/index.php/Extension_negotiation_protocol … … 94 92 tr_peerIo * io; 95 93 tr_crypto * crypto; 96 struct tr_handle * handle;94 tr_session * session; 97 95 uint8_t myPublicKey[KEY_LEN]; 98 96 uint8_t mySecret[KEY_LEN]; … … 208 206 uint8_t * walk = buf; 209 207 const uint8_t * torrentHash = tr_cryptoGetTorrentHash( handshake->crypto ); 210 const tr_torrent * tor = tr_torrentFindFromHash( handshake-> handle, torrentHash );208 const tr_torrent * tor = tr_torrentFindFromHash( handshake->session, torrentHash ); 211 209 const uint8_t * peer_id = tor && tor->peer_id ? tor->peer_id : tr_getPeerId( ); 212 210 … … 250 248 const uint8_t * peer_id; 251 249 252 dbgmsg( handshake, "payload: need %d, got % d", (int)HANDSHAKE_SIZE,253 (int)EVBUFFER_LENGTH( inbuf ) );250 dbgmsg( handshake, "payload: need %d, got %zu", 251 (int)HANDSHAKE_SIZE, EVBUFFER_LENGTH( inbuf ) ); 254 252 255 253 if( EVBUFFER_LENGTH( inbuf ) < HANDSHAKE_SIZE ) … … 267 265 tr_peerIoReadBytes( handshake->io, inbuf, hash, sizeof( hash ) ); 268 266 assert( tr_peerIoHasTorrentHash( handshake->io ) ); 269 if( !tr_torrentExists( handshake-> handle, hash )267 if( !tr_torrentExists( handshake->session, hash ) 270 268 || memcmp( hash, tr_peerIoGetTorrentHash( handshake->io ), 271 269 SHA_DIGEST_LENGTH ) ) … … 285 283 handshake->peer_id ); 286 284 287 tor = tr_torrentFindFromHash( handshake-> handle, hash );285 tor = tr_torrentFindFromHash( handshake->session, hash ); 288 286 peer_id = tor && tor->peer_id ? tor->peer_id : tr_getPeerId( ); 289 287 if( !memcmp( handshake->peer_id, peer_id, PEER_ID_LEN ) ) … … 297 295 **/ 298 296 299 if( HANDSHAKE_HAS_LTEP( reserved ) ) 300 { 301 tr_peerIoEnableLTEP( handshake->io, 1 ); 302 dbgmsg( handshake, "using ltep" ); 303 } 304 305 if( HANDSHAKE_HAS_FASTEXT( reserved ) ) 306 { 307 tr_peerIoEnableFEXT( handshake->io, 1 ); 308 dbgmsg( handshake, "using fext" ); 309 } 297 tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) ); 298 299 tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) ); 310 300 311 301 return HANDSHAKE_OK; … … 410 400 return READ_LATER; 411 401 412 isEncrypted = memcmp( EVBUFFER_DATA( 413 inbuf ), HANDSHAKE_NAME, HANDSHAKE_NAME_LEN ); 402 isEncrypted = memcmp( EVBUFFER_DATA( inbuf ), HANDSHAKE_NAME, HANDSHAKE_NAME_LEN ); 414 403 if( isEncrypted ) 415 404 { … … 422 411 ( isEncrypted ? "encrypted" : "plaintext" ) ); 423 412 424 tr_peerIoSetEncryption( 425 handshake->io, isEncrypted ? PEER_ENCRYPTION_RC4 426 : PEER_ENCRYPTION_NONE ); 413 tr_peerIoSetEncryption( handshake->io, isEncrypted ? PEER_ENCRYPTION_RC4 414 : PEER_ENCRYPTION_NONE ); 427 415 if( !isEncrypted ) 428 416 { … … 454 442 uint8_t buf[SHA_DIGEST_LENGTH]; 455 443 tr_sha1( req2, "req2", 4, 456 tr_cryptoGetTorrentHash( 457 handshake->crypto ),SHA_DIGEST_LENGTH, NULL );444 tr_cryptoGetTorrentHash( handshake->crypto ), 445 SHA_DIGEST_LENGTH, NULL ); 458 446 tr_sha1( req3, "req3", 4, secret, KEY_LEN, NULL ); 459 447 for( i = 0; i < SHA_DIGEST_LENGTH; ++i ) … … 576 564 uint8_t * tmp; 577 565 578 dbgmsg( handshake, "pad d: need %d, got %d", (int)needlen, 579 (int)EVBUFFER_LENGTH( 580 inbuf ) ); 566 dbgmsg( handshake, "pad d: need %zu, got %zu", 567 needlen, EVBUFFER_LENGTH( inbuf ) ); 581 568 if( EVBUFFER_LENGTH( inbuf ) < needlen ) 582 569 return READ_LATER; … … 608 595 uint8_t hash[SHA_DIGEST_LENGTH]; 609 596 610 dbgmsg( handshake, "payload: need %d, got %d", 611 (int)INCOMING_HANDSHAKE_LEN, (int)EVBUFFER_LENGTH( 612 inbuf ) ); 597 dbgmsg( handshake, "payload: need %d, got %zu", 598 (int)INCOMING_HANDSHAKE_LEN, EVBUFFER_LENGTH( inbuf ) ); 613 599 614 600 if( EVBUFFER_LENGTH( inbuf ) < INCOMING_HANDSHAKE_LEN ) … … 667 653 668 654 /** 669 *** Extension negotiation655 *** Extensions 670 656 **/ 671 657 672 if( HANDSHAKE_HAS_LTEP( reserved ) ) 673 { 674 tr_peerIoEnableLTEP( handshake->io, 1 ); 675 dbgmsg( handshake, "using ltep" ); 676 } 677 if( HANDSHAKE_HAS_FASTEXT( reserved ) ) 678 { 679 tr_peerIoEnableFEXT( handshake->io, 1 ); 680 dbgmsg( handshake, "using fext" ); 681 } 658 tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) ); 659 660 tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) ); 682 661 683 662 /* torrent hash */ … … 685 664 if( tr_peerIoIsIncoming( handshake->io ) ) 686 665 { 687 if( !tr_torrentExists( handshake-> handle, hash ) )666 if( !tr_torrentExists( handshake->session, hash ) ) 688 667 { 689 668 dbgmsg( handshake, "peer is trying to connect to us for a torrent we don't have." ); … … 737 716 738 717 /* peer id */ 739 tr_peerIoReadBytes( handshake->io, inbuf, handshake->peer_id, 740 PEER_ID_LEN ); 718 tr_peerIoReadBytes( handshake->io, inbuf, handshake->peer_id, PEER_ID_LEN ); 741 719 tr_peerIoSetPeersId( handshake->io, handshake->peer_id ); 742 720 handshake->havePeerID = TRUE; 743 721 tr_clientForId( client, sizeof( client ), handshake->peer_id ); 744 722 dbgmsg( handshake, "peer-id is [%s] ... isIncoming is %d", client, 745 tr_peerIoIsIncoming( 746 handshake->io ) ); 723 tr_peerIoIsIncoming( handshake->io ) ); 747 724 748 725 /* if we've somehow connected to ourselves, don't keep the connection */ 749 tor = tr_torrentFindFromHash( handshake-> handle, tr_peerIoGetTorrentHash( handshake->io ) );726 tor = tr_torrentFindFromHash( handshake->session, tr_peerIoGetTorrentHash( handshake->io ) ); 750 727 peer_id = tor && tor->peer_id ? tor->peer_id : tr_getPeerId( ); 751 728 peerIsGood = memcmp( handshake->peer_id, peer_id, PEER_ID_LEN ) != 0; … … 763 740 int len; 764 741 765 dbgmsg( handshake, "in readYa... need %d, have %d", (int)KEY_LEN, 766 (int)EVBUFFER_LENGTH( 767 inbuf ) ); 742 dbgmsg( handshake, "in readYa... need %d, have %zu", 743 (int)KEY_LEN, EVBUFFER_LENGTH( inbuf ) ); 768 744 if( EVBUFFER_LENGTH( inbuf ) < KEY_LEN ) 769 745 return READ_LATER; … … 796 772 uint8_t * pch; 797 773 798 dbgmsg( 799 handshake, 800 "looking to get past pad a... & resync on hash('req',S) ... have %d bytes", 801 (int)EVBUFFER_LENGTH( inbuf ) ); 774 dbgmsg( handshake, "looking to get past pad a... & resync on hash('req',S) ... have %zu bytes", 775 EVBUFFER_LENGTH( inbuf ) ); 802 776 /** 803 777 *** Resynchronizing on HASH('req1',S) … … 809 783 if( pch == NULL ) 810 784 { 811 dbgmsg( handshake, "no luck so far.. draining %d bytes", 812 (int)EVBUFFER_LENGTH( 813 inbuf ) ); 785 dbgmsg( handshake, "no luck so far.. draining %zu bytes", 786 EVBUFFER_LENGTH( inbuf ) ); 814 787 evbuffer_drain( inbuf, EVBUFFER_LENGTH( inbuf ) ); 815 788 return READ_LATER; … … 871 844 obfuscatedTorrentHash[i] = req2[i] ^ req3[i]; 872 845 if( ( tor = 873 tr_torrentFindFromObfuscatedHash( handshake-> handle,846 tr_torrentFindFromObfuscatedHash( handshake->session, 874 847 obfuscatedTorrentHash ) ) ) 875 848 { 876 dbgmsg( 877 handshake, 878 "got INCOMING connection's encrypted handshake for torrent [%s]", 879 tor->info.name ); 849 dbgmsg( handshake, "got INCOMING connection's encrypted handshake for torrent [%s]", 850 tor->info.name ); 880 851 tr_peerIoSetTorrentHash( handshake->io, tor->info.hash ); 881 852 if( !tr_torrentAllowsPex( tor ) 882 && tr_peerMgrPeerIsSeed( handshake-> handle->peerMgr,853 && tr_peerMgrPeerIsSeed( handshake->session->peerMgr, 883 854 tor->info.hash, 884 855 tr_peerIoGetAddress( handshake->io, NULL ) ) ) … … 938 909 uint32_t crypto_select; 939 910 940 dbgmsg( handshake, "reading IA... have %d, need %d", 941 (int)EVBUFFER_LENGTH( 942 inbuf ), (int)needlen ); 911 dbgmsg( handshake, "reading IA... have %zu, need %zu", 912 EVBUFFER_LENGTH( inbuf ), needlen ); 943 913 if( EVBUFFER_LENGTH( inbuf ) < needlen ) 944 914 return READ_LATER; 945 915 946 916 /** 947 *** B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload 948 ***Stream) 917 *** B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream) 949 918 **/ 950 919 … … 975 944 976 945 dbgmsg( handshake, "sending pad d" ); 977 /* ENCRYPT(VC, crypto_provide, len(Pad C), PadC946 /* ENCRYPT(VC, crypto_provide, len(PadD), PadD 978 947 * PadD is reserved for future extensions to the handshake... 979 948 * standard practice at this time is for it to be zero-length */ … … 1013 982 const size_t needlen = HANDSHAKE_SIZE; 1014 983 1015 dbgmsg( handshake, "reading payload stream... have % d, need %d",1016 (int)EVBUFFER_LENGTH( inbuf ), (int)needlen );984 dbgmsg( handshake, "reading payload stream... have %zu, need %zu", 985 EVBUFFER_LENGTH( inbuf ), needlen ); 1017 986 if( EVBUFFER_LENGTH( inbuf ) < needlen ) 1018 987 return READ_LATER; … … 1035 1004 1036 1005 static ReadState 1037 canRead( struct tr_ iobuf * iobuf, void * arg, size_t * piece )1038 { 1039 tr_handshake *handshake = arg;1040 struct evbuffer * inbuf = tr_ iobuf_input( iobuf);1006 canRead( struct tr_peerIo * io, void * arg, size_t * piece ) 1007 { 1008 tr_handshake * handshake = arg; 1009 struct evbuffer * inbuf = tr_peerIoGetReadBuffer( io ); 1041 1010 ReadState ret; 1042 intreadyForMore = TRUE;1011 tr_bool readyForMore = TRUE; 1043 1012 1044 1013 /* no piece data in handshake */ … … 1122 1091 } 1123 1092 1093 void 1094 tr_handshakeFree( tr_handshake * handshake ) 1095 { 1096 if( handshake->io ) 1097 tr_peerIoFree( handshake->io ); 1098 1099 tr_free( handshake ); 1100 } 1101 1124 1102 static int 1125 1103 tr_handshakeDone( tr_handshake * handshake, 1126 1104 int isOK ) 1127 1105 { 1128 intsuccess;1106 tr_bool success; 1129 1107 1130 1108 dbgmsg( handshake, "handshakeDone: %s", isOK ? "connected" : "aborting" ); … … 1133 1111 success = fireDoneFunc( handshake, isOK ); 1134 1112 1135 tr_free( handshake );1136 1137 1113 return success ? READ_LATER : READ_ERR; 1138 1114 } … … 1145 1121 1146 1122 static void 1147 gotError( struct tr_iobuf * iobufUNUSED,1148 short 1149 void 1123 gotError( tr_peerIo * io UNUSED, 1124 short what, 1125 void * arg ) 1150 1126 { 1151 1127 tr_handshake * handshake = (tr_handshake *) arg; … … 1194 1170 handshake->doneCB = doneCB; 1195 1171 handshake->doneUserData = doneUserData; 1196 handshake->handle = tr_peerIoGetSession( io ); 1197 tr_peerIoSetTimeoutSecs( io, 15 ); 1172 handshake->session = tr_peerIoGetSession( io ); 1198 1173 1199 1174 tr_peerIoSetIOFuncs( handshake->io, canRead, NULL, gotError, handshake ); … … 1225 1200 } 1226 1201 1227 const struct in_addr * 1228 tr_handshakeGetAddr( const struct tr_handshake * handshake, 1229 uint16_t * port ) 1230 { 1202 struct tr_peerIo* 1203 tr_handshakeStealIO( tr_handshake * handshake ) 1204 { 1205 struct tr_peerIo * io; 1206 1231 1207 assert( handshake ); 1232 1208 assert( handshake->io ); 1233 1209 1210 io = handshake->io; 1211 handshake->io = NULL; 1212 return io; 1213 } 1214 1215 const tr_address * 1216 tr_handshakeGetAddr( const struct tr_handshake * handshake, 1217 tr_port * port ) 1218 { 1219 assert( handshake ); 1220 assert( handshake->io ); 1221 1234 1222 return tr_peerIoGetAddress( handshake->io, port ); 1235 1223 } -
branches/1.4x/libtransmission/handshake.h
r7175 r7455 1 1 /* 2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 19 19 20 20 #include "transmission.h" 21 #include "net.h" 21 22 22 struct in_addr;23 23 struct tr_peerIo; 24 24 typedef struct tr_handshake tr_handshake; 25 25 26 26 /* returns true on success, false on error */ 27 typedef int( *handshakeDoneCB )( struct tr_handshake * handshake,28 struct tr_peerIo * io,29 int isConnected,30 const uint8_t * peerId,31 void * userData );27 typedef tr_bool ( *handshakeDoneCB )( struct tr_handshake * handshake, 28 struct tr_peerIo * io, 29 int isConnected, 30 const uint8_t * peerId, 31 void * userData ); 32 32 33 33 tr_handshake * tr_handshakeNew( struct tr_peerIo * io, … … 36 36 void * doneUserData ); 37 37 38 const struct in_addr * tr_handshakeGetAddr(39 const struct tr_handshake * handshake,40 uint16_t 41 * setme_port);38 const tr_address * tr_handshakeGetAddr( const struct tr_handshake * handshake, 39 tr_port * port ); 40 41 void tr_handshakeFree( tr_handshake * handshake ); 42 42 43 43 void tr_handshakeAbort( tr_handshake * handshake ); … … 45 45 struct tr_peerIo* tr_handshakeGetIO( tr_handshake * handshake ); 46 46 47 struct tr_peerIo* tr_handshakeStealIO( tr_handshake * handshake ); 48 49 47 50 #endif -
branches/1.4x/libtransmission/net.c
r7176 r7455 64 64 } 65 65 66 tr_bool 67 tr_isAddress( const tr_address * a ) 68 { 69 return a != NULL; /* this is implemented better in 1.50 */ 70 } 71 72 66 73 /*********************************************************************** 67 74 * DNS resolution … … 243 250 } 244 251 252 int 253 tr_compareAddresses( const struct in_addr * a, const struct in_addr * b ) 254 { 255 if( a->s_addr != b->s_addr ) 256 return a->s_addr < b->s_addr ? -1 : 1; 257 258 return 0; 259 } -
branches/1.4x/libtransmission/net.h
r7176 r7455 65 65 struct tr_session; 66 66 67 typedef struct in_addr tr_address; 68 69 tr_bool tr_isAddress( const tr_address * a ); 70 67 71 /*********************************************************************** 68 72 * DNS resolution … … 95 99 int len ); 96 100 101 int tr_compareAddresses( const struct in_addr * a, 102 const struct in_addr * b ); 103 97 104 void tr_netInit( void ); 98 105 -
branches/1.4x/libtransmission/peer-common.h
r7176 r7455 23 23 24 24 #include "transmission.h" 25 #include "publish.h"26 25 27 26 typedef enum … … 43 42 TR_PEER_CLIENT_GOT_BLOCK, 44 43 TR_PEER_CLIENT_GOT_DATA, 44 TR_PEER_CLIENT_GOT_ALLOWED_FAST, 45 TR_PEER_CLIENT_GOT_SUGGEST, 45 46 TR_PEER_PEER_GOT_DATA, 46 47 TR_PEER_PEER_PROGRESS, 47 48 TR_PEER_ERROR, 48 49 TR_PEER_CANCEL, 50 TR_PEER_UPLOAD_ONLY, 49 51 TR_PEER_NEED_REQ 50 52 } … … 54 56 { 55 57 PeerEventType eventType; 56 uint32_t pieceIndex; /* for GOT_BLOCK, CANCEL */58 uint32_t pieceIndex; /* for GOT_BLOCK, CANCEL, ALLOWED, SUGGEST */ 57 59 uint32_t offset; /* for GOT_BLOCK */ 58 60 uint32_t length; /* for GOT_BLOCK + GOT_DATA */ 59 61 float progress; /* for PEER_PROGRESS */ 60 62 int err; /* errno for GOT_ERROR */ 61 int wasPieceData; /* for GOT_DATA */ 63 tr_bool wasPieceData; /* for GOT_DATA */ 64 tr_bool uploadOnly; /* for UPLOAD_ONLY */ 62 65 } 63 66 tr_peer_event; -
branches/1.4x/libtransmission/peer-io.c
r7403 r7455 1 1 /* 2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 20 20 #include <winsock2.h> 21 21 #else 22 #include <netinet/in.h> /* struct in_addr */23 22 #include <arpa/inet.h> /* inet_ntoa */ 24 23 #endif … … 29 28 #include "bandwidth.h" 30 29 #include "crypto.h" 31 #include "iobuf.h"32 30 #include "list.h" 33 31 #include "net.h" … … 37 35 38 36 #define MAGIC_NUMBER 206745 39 #define IO_TIMEOUT_SECS 840 37 41 38 static size_t … … 81 78 struct tr_peerIo 82 79 { 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; 80 tr_bool isEncrypted; 81 tr_bool isIncoming; 82 tr_bool peerIdIsSet; 83 tr_bool extendedProtocolSupported; 84 tr_bool fastExtensionSupported; 85 86 int magicNumber; 87 88 uint8_t encryptionMode; 89 tr_port port; 90 int socket; 91 92 uint8_t peerId[20]; 93 time_t timeCreated; 94 95 tr_session * session; 96 97 tr_address addr; 98 tr_list * output_datatypes; /* struct tr_datatype */ 99 100 tr_can_read_cb canRead; 101 tr_did_write_cb didWrite; 102 tr_net_error_cb gotError; 103 void * userData; 104 105 size_t bufferSize[2]; 106 107 tr_bandwidth * bandwidth; 108 tr_crypto * crypto; 109 110 struct evbuffer * inbuf; 111 struct evbuffer * outbuf; 112 113 struct event event_read; 114 struct event event_write; 114 115 }; 115 116 … … 119 120 120 121 static void 121 didWriteWrapper( struct tr_iobuf * iobuf, 122 size_t bytes_transferred, 123 void * vio ) 124 { 125 tr_peerIo * io = vio; 126 122 didWriteWrapper( tr_peerIo * io, size_t bytes_transferred ) 123 { 127 124 while( bytes_transferred ) 128 125 { … … 144 141 tr_free( tr_list_pop_front( &io->output_datatypes ) ); 145 142 } 146 147 if( EVBUFFER_LENGTH( tr_iobuf_output( iobuf ) ) )148 tr_iobuf_enable( io->iobuf, EV_WRITE );149 143 } 150 144 151 145 static void 152 canReadWrapper( struct tr_iobuf * iobuf, 153 size_t bytes_transferred UNUSED, 154 void * vio ) 155 { 156 int done = 0; 157 int err = 0; 158 tr_peerIo * io = vio; 146 canReadWrapper( tr_peerIo * io ) 147 { 148 tr_bool done = 0; 149 tr_bool err = 0; 159 150 tr_session * session = io->session; 160 151 … … 169 160 { 170 161 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 } 162 const size_t oldLen = EVBUFFER_LENGTH( io->inbuf ); 163 const int ret = io->canRead( io, io->userData, &piece ); 164 165 const size_t used = oldLen - EVBUFFER_LENGTH( io->inbuf ); 166 167 if( piece ) 168 tr_bandwidthUsed( io->bandwidth, TR_DOWN, piece, TRUE ); 169 170 if( used != piece ) 171 tr_bandwidthUsed( io->bandwidth, TR_DOWN, used - piece, FALSE ); 182 172 183 173 switch( ret ) 184 174 { 185 175 case READ_NOW: 186 if( EVBUFFER_LENGTH( tr_iobuf_input( iobuf )))176 if( EVBUFFER_LENGTH( io->inbuf ) ) 187 177 continue; 188 178 done = 1; … … 203 193 } 204 194 195 #define _isBool(b) (((b)==0 || (b)==1)) 196 197 tr_bool 198 tr_isPeerIo( const tr_peerIo * io ) 199 { 200 return ( io != NULL ) 201 && ( io->magicNumber == MAGIC_NUMBER ) 202 && ( _isBool( io->isEncrypted ) ) 203 && ( _isBool( io->isIncoming ) ) 204 && ( _isBool( io->peerIdIsSet ) ) 205 && ( _isBool( io->extendedProtocolSupported ) ) 206 && ( _isBool( io->fastExtensionSupported ) ); 207 } 208 205 209 static void 206 gotErrorWrapper( struct tr_iobuf * iobuf, 207 short what, 208 void * userData ) 209 { 210 tr_peerIo * c = userData; 211 212 if( c->gotError ) 213 c->gotError( iobuf, what, c->userData ); 210 event_read_cb( int fd, short event UNUSED, void * vio ) 211 { 212 int res; 213 short what = EVBUFFER_READ; 214 tr_peerIo * io = vio; 215 const size_t howmuch = tr_bandwidthClamp( io->bandwidth, TR_DOWN, io->session->so_rcvbuf ); 216 const tr_direction dir = TR_DOWN; 217 218 assert( tr_isPeerIo( io ) ); 219 220 dbgmsg( io, "libevent says this peer is ready to read" ); 221 222 /* if we don't have any bandwidth left, stop reading */ 223 if( howmuch < 1 ) { 224 tr_peerIoSetEnabled( io, dir, FALSE ); 225 return; 226 } 227 228 res = evbuffer_read( io->inbuf, fd, howmuch ); 229 if( res == -1 ) { 230 if( errno == EAGAIN || errno == EINTR ) 231 goto reschedule; 232 /* error case */ 233 what |= EVBUFFER_ERROR; 234 } else if( res == 0 ) { 235 /* eof case */ 236 what |= EVBUFFER_EOF; 237 } 238 239 if( res <= 0 ) 240 goto error; 241 242 tr_peerIoSetEnabled( io, dir, TRUE ); 243 244 /* Invoke the user callback - must always be called last */ 245 canReadWrapper( io ); 246 247 return; 248 249 reschedule: 250 tr_peerIoSetEnabled( io, dir, TRUE ); 251 return; 252 253 error: 254 if( io->gotError != NULL ) 255 io->gotError( io, what, io->userData ); 256 } 257 258 static int 259 tr_evbuffer_write( tr_peerIo * io, int fd, size_t howmuch ) 260 { 261 struct evbuffer * buffer = io->outbuf; 262 int n = MIN( EVBUFFER_LENGTH( buffer ), howmuch ); 263 264 #ifdef WIN32 265 n = send(fd, buffer->buffer, n, 0 ); 266 #else 267 n = write(fd, buffer->buffer, n ); 268 #endif 269 dbgmsg( io, "wrote %d to peer (%s)", n, (n==-1?strerror(errno):"") ); 270 271 if( n == -1 ) 272 return -1; 273 if (n == 0) 274 return 0; 275 evbuffer_drain( buffer, n ); 276 277 return n; 278 } 279 280 static void 281 event_write_cb( int fd, short event UNUSED, void * vio ) 282 { 283 int res = 0; 284 short what = EVBUFFER_WRITE; 285 tr_peerIo * io = vio; 286 size_t howmuch; 287 const tr_direction dir = TR_UP; 288 289 assert( tr_isPeerIo( io ) ); 290 291 dbgmsg( io, "libevent says this peer is ready to write" ); 292 293 howmuch = MIN( (size_t)io->session->so_sndbuf, EVBUFFER_LENGTH( io->outbuf ) ); 294 howmuch = tr_bandwidthClamp( io->bandwidth, dir, howmuch ); 295 296 /* if we don't have any bandwidth left, stop writing */ 297 if( howmuch < 1 ) { 298 tr_peerIoSetEnabled( io, dir, FALSE ); 299 return; 300 } 301 302 res = tr_evbuffer_write( io, fd, howmuch ); 303 if (res == -1) { 304 #ifndef WIN32 305 /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not 306 * *set errno. thus this error checking is not portable*/ 307 if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) 308 goto reschedule; 309 /* error case */ 310 what |= EVBUFFER_ERROR; 311 312 #else 313 goto reschedule; 314 #endif 315 316 } else if (res == 0) { 317 /* eof case */ 318 what |= EVBUFFER_EOF; 319 } 320 if (res <= 0) 321 goto error; 322 323 if( EVBUFFER_LENGTH( io->outbuf ) ) 324 tr_peerIoSetEnabled( io, dir, TRUE ); 325 326 didWriteWrapper( io, res ); 327 return; 328 329 reschedule: 330 if( EVBUFFER_LENGTH( io->outbuf ) ) 331 tr_peerIoSetEnabled( io, dir, TRUE ); 332 return; 333 334 error: 335 if( io->gotError != NULL ) 336 io->gotError( io, what, io->userData ); 214 337 } 215 338 … … 218 341 **/ 219 342 220 static void221 bufevNew( tr_peerIo * io )222 {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 343 235 344 static int 236 is PeerIo( const tr_peerIo * io)237 { 238 return ( io != NULL ) && ( io->magicNumber == MAGIC_NUMBER);345 isFlag( int flag ) 346 { 347 return( ( flag == 0 ) || ( flag == 1 ) ); 239 348 } 240 349 241 350 static tr_peerIo* 242 tr_peerIoNew( tr_session *session,243 const struct in_addr * in_addr,244 uint16_tport,245 const uint8_t *torrentHash,246 int 247 int 351 tr_peerIoNew( tr_session * session, 352 const tr_address * addr, 353 tr_port port, 354 const uint8_t * torrentHash, 355 int isIncoming, 356 int socket ) 248 357 { 249 358 tr_peerIo * io; … … 256 365 io->crypto = tr_cryptoNew( torrentHash, isIncoming ); 257 366 io->session = session; 258 io-> in_addr = *in_addr;367 io->addr = *addr; 259 368 io->port = port; 260 369 io->socket = socket; 261 370 io->isIncoming = isIncoming != 0; 262 io->timeout = IO_TIMEOUT_SECS;263 371 io->timeCreated = time( NULL ); 372 io->inbuf = evbuffer_new( ); 373 io->outbuf = evbuffer_new( ); 374 event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io ); 375 event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io ); 376 #if 0 264 377 bufevNew( io ); 378 #endif 265 379 tr_peerIoSetBandwidth( io, session->bandwidth ); 266 380 return io; … … 268 382 269 383 tr_peerIo* 270 tr_peerIoNewIncoming( tr_session *session,271 const struct in_addr * in_addr,272 uint16_tport,273 int 384 tr_peerIoNewIncoming( tr_session * session, 385 const tr_address * addr, 386 tr_port port, 387 int socket ) 274 388 { 275 389 assert( session ); 276 assert( in_addr );390 assert( addr ); 277 391 assert( socket >= 0 ); 278 392 279 return tr_peerIoNew( session, in_addr, port, 280 NULL, 1, 281 socket ); 393 return tr_peerIoNew( session, addr, port, NULL, 1, socket ); 282 394 } 283 395 284 396 tr_peerIo* 285 tr_peerIoNewOutgoing( tr_session *session,286 const struct in_addr * in_addr,287 intport,288 const uint8_t *torrentHash )397 tr_peerIoNewOutgoing( tr_session * session, 398 const tr_address * addr, 399 tr_port port, 400 const uint8_t * torrentHash ) 289 401 { 290 402 int socket; 291 403 292 404 assert( session ); 293 assert( in_addr ); 294 assert( port >= 0 ); 405 assert( addr ); 295 406 assert( torrentHash ); 296 407 297 socket = tr_netOpenTCP( session, in_addr, port );408 socket = tr_netOpenTCP( session, addr, port ); 298 409 299 410 return socket < 0 300 411 ? NULL 301 : tr_peerIoNew( session, in_addr, port, torrentHash, 0, socket );412 : tr_peerIoNew( session, addr, port, torrentHash, 0, socket ); 302 413 } 303 414 … … 307 418 tr_peerIo * io = vio; 308 419 420 event_del( &io->event_read ); 421 event_del( &io->event_write ); 309 422 tr_peerIoSetBandwidth( io, NULL ); 310 tr_iobuf_free( io->iobuf ); 423 evbuffer_free( io->outbuf ); 424 evbuffer_free( io->inbuf ); 311 425 tr_netClose( io->socket ); 312 426 tr_cryptoFree( io->crypto ); … … 332 446 tr_peerIoGetSession( tr_peerIo * io ) 333 447 { 334 assert( isPeerIo( io ) );448 assert( tr_isPeerIo( io ) ); 335 449 assert( io->session ); 336 450 … … 338 452 } 339 453 340 const struct in_addr*454 const tr_address* 341 455 tr_peerIoGetAddress( const tr_peerIo * io, 342 uint16_t* port )343 { 344 assert( isPeerIo( io ) );456 tr_port * port ) 457 { 458 assert( tr_isPeerIo( io ) ); 345 459 346 460 if( port ) 347 461 *port = io->port; 348 462 349 return &io-> in_addr;463 return &io->addr; 350 464 } 351 465 352 466 const char* 353 tr_peerIoAddrStr( const struct in_addr * addr, 354 uint16_t port ) 467 tr_peerIoAddrStr( const tr_address * addr, tr_port port ) 355 468 { 356 469 static char buf[512]; 357 358 tr_snprintf( buf, sizeof( buf ), "%s:%u", inet_ntoa( *addr ), 359 ntohs( port ) ); 470 tr_snprintf( buf, sizeof( buf ), "%s:%u", inet_ntoa( *addr ), ntohs( port ) ); 360 471 return buf; 361 472 } … … 364 475 tr_peerIoGetAddrStr( const tr_peerIo * io ) 365 476 { 366 return tr_peerIoAddrStr( &io->in_addr, io->port ); 367 } 368 369 static void 370 tr_peerIoTryRead( tr_peerIo * io ) 371 { 372 if( EVBUFFER_LENGTH( tr_iobuf_input( io->iobuf ))) 373 (*canReadWrapper)( io->iobuf, ~0, io ); 374 } 375 376 void 377 tr_peerIoSetIOFuncs( tr_peerIo * io, 378 tr_can_read_cb readcb, 379 tr_did_write_cb writecb, 380 tr_net_error_cb errcb, 381 void * userData ) 477 return tr_peerIoAddrStr( &io->addr, io->port ); 478 } 479 480 void 481 tr_peerIoSetIOFuncs( tr_peerIo * io, 482 tr_can_read_cb readcb, 483 tr_did_write_cb writecb, 484 tr_net_error_cb errcb, 485 void * userData ) 382 486 { 383 487 io->canRead = readcb; … … 385 489 io->gotError = errcb; 386 490 io->userData = userData; 387 388 tr_peerIoTryRead( io ); 389 } 390 391 int 491 } 492 493 tr_bool 392 494 tr_peerIoIsIncoming( const tr_peerIo * c ) 393 495 { 394 return c->isIncoming ? 1 :0;496 return c->isIncoming != 0; 395 497 } 396 498 … … 403 505 tr_netClose( io->socket ); 404 506 405 io->socket = tr_netOpenTCP( io->session, &io-> in_addr, io->port );507 io->socket = tr_netOpenTCP( io->session, &io->addr, io->port ); 406 508 407 509 if( io->socket >= 0 ) … … 411 513 412 514 tr_netSetTOS( io->socket, io->session->peerSocketTOS ); 413 tr_iobuf_free( io->iobuf ); 515 #if 0 414 516 bufevNew( io ); 517 #endif 415 518 416 519 tr_peerIoSetBandwidth( io, bandwidth ); … … 419 522 420 523 return -1; 421 }422 423 void424 tr_peerIoSetTimeoutSecs( tr_peerIo * io,425 int secs )426 {427 io->timeout = secs;428 tr_iobuf_settimeout( io->iobuf, io->timeout, io->timeout );429 tr_iobuf_enable( io->iobuf, EV_READ | EV_WRITE );430 524 } 431 525 … … 438 532 const uint8_t * hash ) 439 533 { 440 assert( isPeerIo( io ) );534 assert( tr_isPeerIo( io ) ); 441 535 442 536 tr_cryptoSetTorrentHash( io->crypto, hash ); … … 446 540 tr_peerIoGetTorrentHash( tr_peerIo * io ) 447 541 { 448 assert( isPeerIo( io ) );542 assert( tr_isPeerIo( io ) ); 449 543 assert( io->crypto ); 450 544 … … 455 549 tr_peerIoHasTorrentHash( const tr_peerIo * io ) 456 550 { 457 assert( isPeerIo( io ) );551 assert( tr_isPeerIo( io ) ); 458 552 assert( io->crypto ); 459 553 … … 469 563 const uint8_t * peer_id ) 470 564 { 471 assert( isPeerIo( io ) );565 assert( tr_isPeerIo( io ) ); 472 566 473 567 if( ( io->peerIdIsSet = peer_id != NULL ) ) … … 480 574 tr_peerIoGetPeersId( const tr_peerIo * io ) 481 575 { 482 assert( isPeerIo( io ) );576 assert( tr_isPeerIo( io ) ); 483 577 assert( io->peerIdIsSet ); 484 578 … … 491 585 492 586 void 493 tr_peerIoEnableLTEP( tr_peerIo * io, 494 int flag ) 495 { 496 assert( isPeerIo( io ) ); 497 assert( flag == 0 || flag == 1 ); 498 587 tr_peerIoEnableFEXT( tr_peerIo * io, 588 tr_bool flag ) 589 { 590 assert( tr_isPeerIo( io ) ); 591 assert( isFlag( flag ) ); 592 593 dbgmsg( io, "setting FEXT support flag to %d", (flag?1:0) ); 594 io->fastExtensionSupported = flag; 595 } 596 597 tr_bool 598 tr_peerIoSupportsFEXT( const tr_peerIo * io ) 599 { 600 assert( tr_isPeerIo( io ) ); 601 602 return io->fastExtensionSupported; 603 } 604 605 /** 606 *** 607 **/ 608 609 void 610 tr_peerIoEnableLTEP( tr_peerIo * io, 611 tr_bool flag ) 612 { 613 assert( tr_isPeerIo( io ) ); 614 assert( isFlag( flag ) ); 615 616 dbgmsg( io, "setting LTEP support flag to %d", (flag?1:0) ); 499 617 io->extendedProtocolSupported = flag; 500 618 } 501 619 502 void 503 tr_peerIoEnableFEXT( tr_peerIo * io, 504 int flag ) 505 { 506 assert( isPeerIo( io ) ); 507 assert( flag == 0 || flag == 1 ); 508 509 io->fastPeersSupported = flag; 510 } 511 512 int 620 tr_bool 513 621 tr_peerIoSupportsLTEP( const tr_peerIo * io ) 514 622 { 515 assert( isPeerIo( io ) );623 assert( tr_isPeerIo( io ) ); 516 624 517 625 return io->extendedProtocolSupported; 518 }519 520 int521 tr_peerIoSupportsFEXT( const tr_peerIo * io )522 {523 assert( isPeerIo( io ) );524 525 return io->fastPeersSupported;526 626 } 527 627 … … 540 640 const double currentSpeed = tr_bandwidthGetPieceSpeed( io->bandwidth, TR_UP ); 541 641 const double period = 20; /* arbitrary */ 542 return MAX( maxBlockSize*5.5, currentSpeed*1024*period ); 642 const double numBlocks = 5.5; /* the 5 is arbitrary; the .5 is to leave room for messages */ 643 return MAX( maxBlockSize*numBlocks, currentSpeed*1024*period ); 543 644 } 544 645 … … 547 648 { 548 649 const size_t desiredLen = getDesiredOutputBufferSize( io ); 549 const size_t currentLen = EVBUFFER_LENGTH( tr_iobuf_output( io->iobuf ));650 const size_t currentLen = EVBUFFER_LENGTH( io->outbuf ); 550 651 size_t freeSpace = 0; 551 652 … … 560 661 tr_bandwidth * bandwidth ) 561 662 { 562 assert( isPeerIo( io ) );663 assert( tr_isPeerIo( io ) ); 563 664 564 665 if( io->bandwidth ) 565 tr_bandwidthRemove Buffer( io->bandwidth, io->iobuf);666 tr_bandwidthRemovePeer( io->bandwidth, io ); 566 667 567 668 io->bandwidth = bandwidth; 568 tr_iobuf_set_bandwidth( io->iobuf, bandwidth );569 669 570 670 if( io->bandwidth ) 571 tr_bandwidthAddBuffer( io->bandwidth, io->iobuf ); 572 573 tr_iobuf_enable( io->iobuf, EV_READ | EV_WRITE ); 671 tr_bandwidthAddPeer( io->bandwidth, io ); 574 672 } 575 673 … … 588 686 int encryptionMode ) 589 687 { 590 assert( isPeerIo( io ) );688 assert( tr_isPeerIo( io ) ); 591 689 assert( encryptionMode == PEER_ENCRYPTION_NONE 592 690 || encryptionMode == PEER_ENCRYPTION_RC4 ); … … 620 718 tr_list_append( &io->output_datatypes, datatype ); 621 719 622 evbuffer_add( tr_iobuf_output( io->iobuf ), writeme, writemeLen ); 623 tr_iobuf_enable( io->iobuf, EV_WRITE ); 720 evbuffer_add( io->outbuf, writeme, writemeLen ); 624 721 } 625 722 … … 736 833 uint16_t tmp; 737 834 835 assert( tr_isPeerIo( io ) ); 836 738 837 tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint16_t ) ); 739 838 *setme = ntohs( tmp ); … … 747 846 uint32_t tmp; 748 847 848 assert( tr_isPeerIo( io ) ); 849 749 850 tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint32_t ) ); 750 851 *setme = ntohl( tmp ); … … 756 857 size_t byteCount ) 757 858 { 758 uint8_t * tmp = tr_new( uint8_t, byteCount ); 759 859 uint8_t * tmp; 860 861 assert( tr_isPeerIo( io ) ); 862 863 tmp = tr_new( uint8_t, byteCount ); 760 864 tr_peerIoReadBytes( io, inbuf, tmp, byteCount ); 761 865 tr_free( tmp ); … … 767 871 return time( NULL ) - io->timeCreated; 768 872 } 873 874 /*** 875 **** 876 ***/ 877 878 static int 879 tr_peerIoTryRead( tr_peerIo * io, size_t howmuch ) 880 { 881 int res; 882 883 assert( tr_isPeerIo( io ) ); 884 885 howmuch = tr_bandwidthClamp( io->bandwidth, TR_DOWN, howmuch ); 886 887 res = howmuch ? evbuffer_read( io->inbuf, io->socket, howmuch ) : 0; 888 889 dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(errno):"") ); 890 891 if( EVBUFFER_LENGTH( io->inbuf ) ) 892 canReadWrapper( io ); 893 894 if( ( res <= 0 ) && ( io->gotError ) && ( errno != EAGAIN ) && ( errno != EINTR ) && ( errno != EINPROGRESS ) ) 895 { 896 short what = EVBUFFER_READ | EVBUFFER_ERROR; 897 if( res == 0 ) 898 what |= EVBUFFER_EOF; 899 io->gotError( io, what, io->userData ); 900 } 901 902 return res; 903 } 904 905 static int 906 tr_peerIoTryWrite( tr_peerIo * io, size_t howmuch ) 907 { 908 int n; 909 910 assert( tr_isPeerIo( io ) ); 911 912 howmuch = tr_bandwidthClamp( io->bandwidth, TR_UP, howmuch ); 913 914 n = tr_evbuffer_write( io, io->socket, (int)howmuch ); 915 916 if( n > 0 ) 917 didWriteWrapper( io, n ); 918 919 if( ( n < 0 ) && ( io->gotError ) && ( errno != EPIPE ) && ( errno != EAGAIN ) && ( errno != EINTR ) && ( errno != EINPROGRESS ) ) { 920 short what = EVBUFFER_WRITE | EVBUFFER_ERROR; 921 io->gotError( io, what, io->userData ); 922 } 923 924 return n; 925 } 926 927 int 928 tr_peerIoFlush( tr_peerIo * io, tr_direction dir, size_t limit ) 929 { 930 int ret; 931 932 assert( tr_isPeerIo( io ) ); 933 assert( tr_isDirection( dir ) ); 934 935 if( dir==TR_DOWN ) 936 ret = tr_peerIoTryRead( io, limit ); 937 else 938 ret = tr_peerIoTryWrite( io, limit ); 939 940 return ret; 941 } 942 943 struct evbuffer * 944 tr_peerIoGetReadBuffer( tr_peerIo * io ) 945 { 946 assert( tr_isPeerIo( io ) ); 947 948 return io->inbuf; 949 } 950 951 tr_bool 952 tr_peerIoHasBandwidthLeft( const tr_peerIo * io, tr_direction dir ) 953 { 954 assert( tr_isPeerIo( io ) ); 955 assert( tr_isDirection( dir ) ); 956 957 return tr_bandwidthClamp( io->bandwidth, dir, 1024 ) > 0; 958 } 959 960 /*** 961 **** 962 ****/ 963 964 static void 965 event_enable( tr_peerIo * io, short event ) 966 { 967 assert( tr_isPeerIo( io ) ); 968 969 if( event & EV_READ ) 970 event_add( &io->event_read, NULL ); 971 972 if( event & EV_WRITE ) 973 event_add( &io->event_write, NULL ); 974 } 975 976 static void 977 event_disable( struct tr_peerIo * io, short event ) 978 { 979 assert( tr_isPeerIo( io ) ); 980 981 if( event & EV_READ ) 982 event_del( &io->event_read ); 983 984 if( event & EV_WRITE ) 985 event_del( &io->event_write ); 986 } 987 988 989 void 990 tr_peerIoSetEnabled( tr_peerIo * io, 991 tr_direction dir, 992 tr_bool isEnabled ) 993 { 994 short event; 995 996 assert( tr_isPeerIo( io ) ); 997 assert( tr_isDirection( dir ) ); 998 999 event = dir == TR_UP ? EV_WRITE : EV_READ; 1000 1001 if( isEnabled ) 1002 event_enable( io, event ); 1003 else 1004 event_disable( io, event ); 1005 } -
branches/1.4x/libtransmission/peer-io.h
r7176 r7455 1 1 /* 2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@ rebelbase.com>2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@transmissionbt.com> 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the … … 18 18 #define TR_PEER_IO_H 19 19 20 /** 21 ***22 ** /23 24 struct in_addr; 20 #include "net.h" /* tr_address */ 21 /** 22 *** 23 **/ 24 25 25 struct evbuffer; 26 26 struct tr_bandwidth; 27 27 struct tr_crypto; 28 struct tr_iobuf;29 28 typedef struct tr_peerIo tr_peerIo; 30 29 … … 33 32 **/ 34 33 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, 41 const struct in_addr * addr, 42 uint16_t port, 43 int socket ); 44 45 void tr_peerIoFree( tr_peerIo * io ); 46 47 tr_session* tr_peerIoGetSession( tr_peerIo * io ); 48 49 /** 50 *** 51 **/ 52 53 void tr_peerIoEnableLTEP( tr_peerIo * io, 54 int flag ); 55 56 void tr_peerIoEnableFEXT( tr_peerIo * io, 57 int flag ); 58 59 int tr_peerIoSupportsLTEP( const tr_peerIo * io ); 60 61 int tr_peerIoSupportsFEXT( const tr_peerIo * io ); 62 63 /** 64 *** 65 **/ 66 67 const char* tr_peerIoAddrStr( const struct in_addr * addr, 68 uint16_t port ); 69 70 const char* tr_peerIoGetAddrStr( const tr_peerIo * io ); 71 72 const struct in_addr*tr_peerIoGetAddress( const tr_peerIo * io, 73 uint16_t * port ); 34 tr_peerIo* tr_peerIoNewOutgoing( tr_session * session, 35 const tr_address * addr, 36 tr_port port, 37 const uint8_t * torrentHash ); 38 39 tr_peerIo* tr_peerIoNewIncoming( tr_session * session, 40 const tr_address * addr, 41 tr_port port, 42 int socket ); 43 44 void tr_peerIoFree ( tr_peerIo * io ); 45 46 tr_bool tr_isPeerIo ( const tr_peerIo * io ); 47 48 49 /** 50 *** 51 **/ 52 53 void tr_peerIoEnableLTEP( tr_peerIo * io, tr_bool flag ); 54 55 tr_bool tr_peerIoSupportsLTEP( const tr_peerIo * io ); 56 57 void tr_peerIoEnableFEXT( tr_peerIo * io, tr_bool flag ); 58 59 tr_bool tr_peerIoSupportsFEXT( const tr_peerIo * io ); 60 61 /** 62 *** 63 **/ 64 65 tr_session* tr_peerIoGetSession ( tr_peerIo * io ); 66 67 const char* tr_peerIoAddrStr( const tr_address * addr, 68 tr_port port ); 69 70 const char* tr_peerIoGetAddrStr( const tr_peerIo * io ); 71 72 const tr_address * tr_peerIoGetAddress( const tr_peerIo * io, 73 tr_port * port ); 74 74 75 75 const uint8_t* tr_peerIoGetTorrentHash( tr_peerIo * io ); … … 82 82 int tr_peerIoReconnect( tr_peerIo * io ); 83 83 84 int tr_peerIoIsIncoming( const tr_peerIo * io ); 85 86 void tr_peerIoSetTimeoutSecs( tr_peerIo * io, 87 int secs ); 84 tr_bool tr_peerIoIsIncoming( const tr_peerIo * io ); 88 85 89 86 int tr_peerIoGetAge( const tr_peerIo * io ); … … 111 108 ReadState; 112 109 113 typedef ReadState ( *tr_can_read_cb )( struct tr_iobuf * iobuf,110 typedef ReadState ( *tr_can_read_cb )( tr_peerIo * io, 114 111 void * user_data, 115 112 size_t * setme_piece_byte_count ); … … 120 117 void * userData ); 121 118 122 typedef void ( *tr_net_error_cb )( struct tr_iobuf * ev,119 typedef void ( *tr_net_error_cb )( tr_peerIo * io, 123 120 short what, 124 121 void * userData ); … … 157 154 EncryptionMode; 158 155 159 void tr_peerIoSetEncryption( tr_peerIo * io, 160 int encryptionMode ); 161 162 int tr_peerIoIsEncrypted( const tr_peerIo * io ); 163 164 void tr_peerIoWriteBytes( tr_peerIo * io, 165 struct evbuffer * outbuf, 166 const void * bytes, 167 size_t byteCount ); 168 169 void tr_peerIoWriteUint8( tr_peerIo * io, 170 struct evbuffer * outbuf, 171 uint8_t writeme ); 172 173 void tr_peerIoWriteUint16( tr_peerIo * io, 174 struct evbuffer * outbuf, 175 uint16_t writeme ); 176 177 void tr_peerIoWriteUint32( tr_peerIo * io, 178 struct evbuffer * outbuf, 179 uint32_t writeme ); 180 181 void tr_peerIoReadBytes( tr_peerIo * io, 182 struct evbuffer * inbuf, 183 void * bytes, 184 size_t byteCount ); 185 186 void tr_peerIoReadUint8( tr_peerIo * io, 187 struct evbuffer * inbuf, 188 uint8_t * setme ); 189 190 void tr_peerIoReadUint16( tr_peerIo * io, 191 struct evbuffer * inbuf, 192 uint16_t * setme ); 193 194 void tr_peerIoReadUint32( tr_peerIo * io, 195 struct evbuffer * inbuf, 196 uint32_t * setme ); 197 198 void tr_peerIoDrain( tr_peerIo * io, 199 struct evbuffer * inbuf, 200 size_t byteCount ); 201 202 /** 203 *** 204 **/ 205 206 size_t tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ); 207 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 ); 156 void tr_peerIoSetEncryption( tr_peerIo * io, 157 int encryptionMode ); 158 159 int tr_peerIoIsEncrypted( const tr_peerIo * io ); 160 161 void tr_peerIoWriteBytes( tr_peerIo * io, 162 struct evbuffer * outbuf, 163 const void * bytes, 164 size_t byteCount ); 165 166 void tr_peerIoWriteUint8( tr_peerIo * io, 167 struct evbuffer * outbuf, 168 uint8_t writeme ); 169 170 void tr_peerIoWriteUint16( tr_peerIo * io, 171 struct evbuffer * outbuf, 172 uint16_t writeme ); 173 174 void tr_peerIoWriteUint32( tr_peerIo * io, 175 struct evbuffer * outbuf, 176 uint32_t writeme ); 177 178 void tr_peerIoReadBytes( tr_peerIo * io, 179 struct evbuffer * inbuf, 180 void * bytes, 181 size_t byteCount ); 182 183 void tr_peerIoReadUint8( tr_peerIo * io, 184 struct evbuffer * inbuf, 185 uint8_t * setme ); 186 187 void tr_peerIoReadUint16( tr_peerIo * io, 188 struct evbuffer * inbuf, 189 uint16_t * setme ); 190 191 void tr_peerIoReadUint32( tr_peerIo * io, 192 struct evbuffer * inbuf, 193 uint32_t * setme ); 194 195 void tr_peerIoDrain( tr_peerIo * io, 196 struct evbuffer * inbuf, 197 size_t byteCount ); 198 199 /** 200 *** 201 **/ 202 203 size_t tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ); 204 205 void tr_peerIoSetBandwidth( tr_peerIo * io, 206 struct tr_bandwidth * bandwidth ); 207 208 void tr_peerIoBandwidthUsed( tr_peerIo * io, 209 tr_direction direction, 210 size_t byteCount, 211 int isPieceData ); 212 213 /** 214 *** 215 **/ 216 217 tr_bool tr_peerIoHasBandwidthLeft( const tr_peerIo * io, 218 tr_direction direction ); 219 220 void tr_peerIoSetEnabled( tr_peerIo * io, 221 tr_direction dir, 222 tr_bool isEnabled ); 223 224 int tr_peerIoFlush( tr_peerIo * io, 225 tr_direction dir, 226 size_t byteLimit ); 227 228 struct evbuffer * tr_peerIoGetReadBuffer( tr_peerIo * io ); 229 215 230 216 231 -
branches/1.4x/libtransmission/peer-mgr-private.h
r7354 r7455 53 53 uint8_t encryption_preference; 54 54 uint16_t port; 55 struct in_addr in_addr;55 struct in_addr addr; 56 56 struct tr_peerIo * io; 57 57 -
branches/1.4x/libtransmission/peer-mgr.c
r7354 r7455 58 58 59 59 /* how frequently to reallocate bandwidth */ 60 BANDWIDTH_PERIOD_MSEC = 250,60 BANDWIDTH_PERIOD_MSEC = 500, 61 61 62 62 /* max # of peers to ask fer per torrent per reconnect pulse */ … … 90 90 **/ 91 91 92 /* We keep one of these for every peer we know about, whether 93 * it's connected or not, so the struct must be small. 94 * When our current connections underperform, we dip back 95 * into this list for new ones. */ 92 enum 93 { 94 UPLOAD_ONLY_UKNOWN, 95 UPLOAD_ONLY_YES, 96 UPLOAD_ONLY_NO 97 }; 98 99 /** 100 * Peer information that should be kept even before we've connected and 101 * after we've disconnected. These are kept in a pool of peer_atoms to decide 102 * which ones would make good candidates for connecting to, and to watch out 103 * for banned peers. 104 * 105 * @see tr_peer 106 * @see tr_peermsgs 107 */ 96 108 struct peer_atom 97 109 { 98 uint8_t from; 99 uint8_t flags; /* these match the added_f flags */ 100 uint8_t myflags; /* flags that aren't defined in added_f */ 101 uint16_t port; 102 uint16_t numFails; 103 struct in_addr addr; 104 time_t time; /* when the peer's connection status last changed */ 105 time_t piece_data_time; 110 uint8_t from; 111 uint8_t flags; /* these match the added_f flags */ 112 uint8_t myflags; /* flags that aren't defined in added_f */ 113 uint8_t uploadOnly; /* UPLOAD_ONLY_ */ 114 tr_port port; 115 uint16_t numFails; 116 tr_address addr; 117 time_t time; /* when the peer's connection status last changed */ 118 time_t piece_data_time; 106 119 }; 107 120 … … 131 144 tr_ptrArray * torrents; /* Torrent */ 132 145 tr_ptrArray * incomingHandshakes; /* tr_handshake */ 146 tr_ptrArray * finishedHandshakes; /* tr_handshake */ 133 147 tr_timer * bandwidthTimer; 134 148 }; … … 185 199 186 200 static int 187 compareAddresses( const struct in_addr * a, 188 const struct in_addr * b ) 189 { 190 if( a->s_addr != b->s_addr ) 191 return a->s_addr < b->s_addr ? -1 : 1; 192 193 return 0; 194 } 195 196 static int 197 handshakeCompareToAddr( const void * va, 198 const void * vb ) 201 handshakeCompareToAddr( const void * va, const void * vb ) 199 202 { 200 203 const tr_handshake * a = va; 201 204 202 return compareAddresses( tr_handshakeGetAddr( a, NULL ), vb ); 203 } 204 205 static int 206 handshakeCompare( const void * a, 207 const void * b ) 205 return tr_compareAddresses( tr_handshakeGetAddr( a, NULL ), vb ); 206 } 207 208 static int 209 handshakeCompare( const void * a, const void * b ) 208 210 { 209 211 return handshakeCompareToAddr( a, tr_handshakeGetAddr( b, NULL ) ); … … 211 213 212 214 static tr_handshake* 213 getExistingHandshake( tr_ptrArray * handshakes, 214 const struct in_addr * in_addr ) 215 { 216 return tr_ptrArrayFindSorted( handshakes, 217 in_addr, 218 handshakeCompareToAddr ); 219 } 220 221 static int 222 comparePeerAtomToAddress( const void * va, 223 const void * vb ) 215 getExistingHandshake( tr_ptrArray * handshakes, 216 const tr_address * addr ) 217 { 218 return tr_ptrArrayFindSorted( handshakes, addr, handshakeCompareToAddr ); 219 } 220 221 static int 222 comparePeerAtomToAddress( const void * va, const void * vb ) 224 223 { 225 224 const struct peer_atom * a = va; 226 225 227 return compareAddresses( &a->addr, vb ); 228 } 229 230 static int 231 comparePeerAtoms( const void * va, 232 const void * vb ) 226 return tr_compareAddresses( &a->addr, vb ); 227 } 228 229 static int 230 comparePeerAtoms( const void * va, const void * vb ) 233 231 { 234 232 const struct peer_atom * b = vb; … … 271 269 272 270 static int 273 peerCompare( const void * va, 274 const void * vb ) 271 peerCompare( const void * va, const void * vb ) 275 272 { 276 273 const tr_peer * a = va; 277 274 const tr_peer * b = vb; 278 275 279 return compareAddresses( &a->in_addr, &b->in_addr ); 280 } 281 282 static int 283 peerCompareToAddr( const void * va, 284 const void * vb ) 276 return tr_compareAddresses( &a->addr, &b->addr ); 277 } 278 279 static int 280 peerCompareToAddr( const void * va, const void * vb ) 285 281 { 286 282 const tr_peer * a = va; 287 283 288 return compareAddresses( &a->in_addr, vb );284 return tr_compareAddresses( &a->addr, vb ); 289 285 } 290 286 291 287 static tr_peer* 292 getExistingPeer( Torrent *torrent,293 const struct in_addr * in_addr )288 getExistingPeer( Torrent * torrent, 289 const tr_address * addr ) 294 290 { 295 291 assert( torrentIsLocked( torrent ) ); 296 assert( in_addr ); 297 298 return tr_ptrArrayFindSorted( torrent->peers, 299 in_addr, 300 peerCompareToAddr ); 292 assert( addr ); 293 294 return tr_ptrArrayFindSorted( torrent->peers, addr, peerCompareToAddr ); 301 295 } 302 296 303 297 static struct peer_atom* 304 getExistingAtom( const Torrent* t,305 const struct in_addr* addr )298 getExistingAtom( const Torrent * t, 299 const tr_address * addr ) 306 300 { 307 301 assert( torrentIsLocked( t ) ); … … 309 303 } 310 304 311 static int312 peerIsInUse( const Torrent *ct,313 const struct in_addr* addr )305 static tr_bool 306 peerIsInUse( const Torrent * ct, 307 const tr_address * addr ) 314 308 { 315 309 Torrent * t = (Torrent*) ct; … … 318 312 319 313 return getExistingPeer( t, addr ) 320 321 314 || getExistingHandshake( t->outgoingHandshakes, addr ) 315 || getExistingHandshake( t->manager->incomingHandshakes, addr ); 322 316 } 323 317 324 318 static tr_peer* 325 peerConstructor( tr_torrent * tor, const struct in_addr * in_addr )319 peerConstructor( tr_torrent * tor, const tr_address * addr ) 326 320 { 327 321 tr_peer * p; 328 329 322 p = tr_new0( tr_peer, 1 ); 330 memcpy( &p->in_addr, in_addr, sizeof( struct in_addr ) );323 p->addr = *addr; 331 324 p->bandwidth = tr_bandwidthNew( tor->session, tor->bandwidth ); 332 325 return p; … … 334 327 335 328 static tr_peer* 336 getPeer( Torrent *torrent,337 const struct in_addr * in_addr )329 getPeer( Torrent * torrent, 330 const tr_address * addr ) 338 331 { 339 332 tr_peer * peer; … … 341 334 assert( torrentIsLocked( torrent ) ); 342 335 343 peer = getExistingPeer( torrent, in_addr );336 peer = getExistingPeer( torrent, addr ); 344 337 345 338 if( peer == NULL ) 346 339 { 347 peer = peerConstructor( torrent->tor, in_addr );340 peer = peerConstructor( torrent->tor, addr ); 348 341 tr_ptrArrayInsertSorted( torrent->peers, peer, peerCompare ); 349 342 } … … 356 349 { 357 350 assert( peer ); 358 assert( peer->msgs ); 359 360 tr_peerMsgsUnsubscribe( peer->msgs, peer->msgsTag ); 361 tr_peerMsgsFree( peer->msgs ); 351 352 if( peer->msgs != NULL ) 353 { 354 tr_peerMsgsUnsubscribe( peer->msgs, peer->msgsTag ); 355 tr_peerMsgsFree( peer->msgs ); 356 } 362 357 363 358 tr_peerIoFree( peer->io ); … … 381 376 assert( torrentIsLocked( t ) ); 382 377 383 atom = getExistingAtom( t, &peer-> in_addr );378 atom = getExistingAtom( t, &peer->addr ); 384 379 assert( atom ); 385 380 atom->time = time( NULL ); … … 456 451 } 457 452 458 /**459 * For explanation, see http://www.bittorrent.org/fast_extensions.html460 * Also see the "test-allowed-set" unit test461 *462 * @param k number of pieces in set463 * @param sz number of pieces in the torrent464 * @param infohash torrent's SHA1 hash465 * @param ip peer's address466 */467 struct tr_bitfield *468 tr_peerMgrGenerateAllowedSet(469 const uint32_t k,470 const uint32_t sz,471 const uint8_t *472 infohash,473 const struct in_addr * ip )474 {475 uint8_t w[SHA_DIGEST_LENGTH + 4];476 uint8_t x[SHA_DIGEST_LENGTH];477 tr_bitfield * a;478 uint32_t a_size;479 480 *(uint32_t*)w = ntohl( htonl( ip->s_addr ) & 0xffffff00 ); /* (1) */481 memcpy( w + 4, infohash, SHA_DIGEST_LENGTH ); /* (2) */482 tr_sha1( x, w, sizeof( w ), NULL ); /* (3) */483 484 a = tr_bitfieldNew( sz );485 a_size = 0;486 487 while( a_size < k )488 {489 int i;490 for( i = 0; i < 5 && a_size < k; ++i ) /* (4) */491 {492 uint32_t j = i * 4; /* (5) */493 uint32_t y = ntohl( *( uint32_t* )( x + j ) ); /* (6) */494 uint32_t index = y % sz; /* (7) */495 if( !tr_bitfieldHas( a, index ) ) /* (8) */496 {497 tr_bitfieldAdd( a, index ); /* (9) */498 ++a_size;499 }500 }501 tr_sha1( x, x, sizeof( x ), NULL ); /* (3) */502 }503 504 return a;505 }506 453 507 454 static int bandwidthPulse( void * vmgr ); … … 516 463 m->torrents = tr_ptrArrayNew( ); 517 464 m->incomingHandshakes = tr_ptrArrayNew( ); 465 m->finishedHandshakes = tr_ptrArrayNew( ); 518 466 m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC ); 519 467 return m; … … 523 471 tr_peerMgrFree( tr_peerMgr * manager ) 524 472 { 473 tr_handshake * handshake; 474 525 475 managerLock( manager ); 526 476 … … 534 484 tr_ptrArrayFree( manager->incomingHandshakes, NULL ); 535 485 486 while(( handshake = tr_ptrArrayPop( manager->finishedHandshakes ))) 487 tr_handshakeFree( handshake ); 488 489 tr_ptrArrayFree( manager->finishedHandshakes, NULL ); 490 536 491 /* free the torrents. */ 537 492 tr_ptrArrayFree( manager->torrents, torrentDestructor ); … … 542 497 543 498 static tr_peer** 544 getConnectedPeers( Torrent * t, 545 int * setmeCount ) 546 { 547 int i, peerCount, connectionCount; 499 getConnectedPeers( Torrent * t, int * setmeCount ) 500 { 501 int i, peerCount, connectionCount; 548 502 tr_peer **peers; 549 503 tr_peer **ret; … … 578 532 ***/ 579 533 580 int 581 tr_peerMgrPeerIsSeed( const tr_peerMgr *mgr,582 const uint8_t *torrentHash,583 const struct in_addr* addr )584 { 585 intisSeed = FALSE;586 const Torrent * 534 tr_bool 535 tr_peerMgrPeerIsSeed( const tr_peerMgr * mgr, 536 const uint8_t * torrentHash, 537 const tr_address * addr ) 538 { 539 tr_bool isSeed = FALSE; 540 const Torrent * t = NULL; 587 541 const struct peer_atom * atom = NULL; 588 542 … … 648 602 649 603 static int 650 compareRefillPiece( const void * aIn, 651 const void * bIn ) 604 compareRefillPiece( const void * aIn, const void * bIn ) 652 605 { 653 606 const struct tr_refill_piece * a = aIn; … … 678 631 679 632 static tr_piece_index_t * 680 getPreferredPieces( Torrent * t, 681 tr_piece_index_t * pieceCount ) 633 getPreferredPieces( Torrent * t, tr_piece_index_t * pieceCount ) 682 634 { 683 635 const tr_torrent * tor = t->tor; … … 877 829 for( j=0; !handled && j<peerCount; ) 878 830 { 879 const int val = tr_peerMsgsAddRequest( peers[j]->msgs, 880 index, offset, length ); 831 const tr_addreq_t val = tr_peerMsgsAddRequest( peers[j]->msgs, index, offset, length ); 881 832 switch( val ) 882 833 { … … 905 856 for( j=0; !handled && j<webseedCount; ) 906 857 { 907 const tr_addreq_t val = tr_webseedAddRequest( webseeds[j], 908 index, offset, length ); 858 const tr_addreq_t val = tr_webseedAddRequest( webseeds[j], index, offset, length ); 909 859 switch( val ) 910 860 { … … 943 893 assert( torrentIsLocked( t ) ); 944 894 895 tordbg( t, "got a block; cancelling any duplicate requests from peers %"PRIu32":%"PRIu32"->%"PRIu32, index, offset, length ); 945 896 peers = getConnectedPeers( t, &size ); 946 897 for( i=0; i<size; ++i ) … … 954 905 { 955 906 tordbg( t, "increasing peer %s strike count to %d", 956 tr_peerIoAddrStr( &peer-> in_addr,907 tr_peerIoAddrStr( &peer->addr, 957 908 peer->port ), peer->strikes + 1 ); 958 909 959 910 if( ++peer->strikes >= MAX_BAD_PIECES_PER_PEER ) 960 911 { 961 struct peer_atom * atom = getExistingAtom( t, &peer-> in_addr );912 struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 962 913 atom->myflags |= MYFLAG_BANNED; 963 914 peer->doPurge = 1; … … 988 939 989 940 static void 990 peerCallbackFunc( void * vpeer, 991 void * vevent, 992 void * vt ) 993 { 994 tr_peer * peer = vpeer; /* may be NULL if peer is a webseed */ 995 Torrent * t = (Torrent *) vt; 941 peerSuggestedPiece( Torrent * t UNUSED, 942 tr_peer * peer UNUSED, 943 tr_piece_index_t pieceIndex UNUSED, 944 int isFastAllowed UNUSED ) 945 { 946 #if 0 947 assert( t ); 948 assert( peer ); 949 assert( peer->msgs ); 950 951 /* is this a valid piece? */ 952 if( pieceIndex >= t->tor->info.pieceCount ) 953 return; 954 955 /* don't ask for it if we've already got it */ 956 if( tr_cpPieceIsComplete( t->tor->completion, pieceIndex ) ) 957 return; 958 959 /* don't ask for it if they don't have it */ 960 if( !tr_bitfieldHas( peer->have, pieceIndex ) ) 961 return; 962 963 /* don't ask for it if we're choked and it's not fast */ 964 if( !isFastAllowed && peer->clientIsChoked ) 965 return; 966 967 /* request the blocks that we don't have in this piece */ 968 { 969 tr_block_index_t block; 970 const tr_torrent * tor = t->tor; 971 const tr_block_index_t start = tr_torPieceFirstBlock( tor, pieceIndex ); 972 const tr_block_index_t end = start + tr_torPieceCountBlocks( tor, pieceIndex ); 973 974 for( block=start; block<end; ++block ) 975 { 976 if( !tr_cpBlockIsComplete( tor->completion, block ) ) 977 { 978 const uint32_t offset = getBlockOffsetInPiece( tor, block ); 979 const uint32_t length = tr_torBlockCountBytes( tor, block ); 980 tr_peerMsgsAddRequest( peer->msgs, pieceIndex, offset, length ); 981 incrementPieceRequests( t, pieceIndex ); 982 } 983 } 984 } 985 #endif 986 } 987 988 static void 989 peerCallbackFunc( void * vpeer, void * vevent, void * vt ) 990 { 991 tr_peer * peer = vpeer; /* may be NULL if peer is a webseed */ 992 Torrent * t = vt; 996 993 const tr_peer_event * e = vevent; 997 994 … … 1000 997 switch( e->eventType ) 1001 998 { 999 case TR_PEER_UPLOAD_ONLY: 1000 /* update our atom */ 1001 if( peer ) { 1002 struct peer_atom * a = getExistingAtom( t, &peer->addr ); 1003 a->uploadOnly = e->uploadOnly ? UPLOAD_ONLY_YES : UPLOAD_ONLY_NO; 1004 } 1005 break; 1006 1002 1007 case TR_PEER_NEED_REQ: 1003 1008 refillSoon( t ); … … 1024 1029 /* update our atom */ 1025 1030 if( peer ) { 1026 struct peer_atom * a = getExistingAtom( t, &peer-> in_addr );1031 struct peer_atom * a = getExistingAtom( t, &peer->addr ); 1027 1032 if( e->wasPieceData ) 1028 1033 a->piece_data_time = now; … … 1031 1036 break; 1032 1037 } 1038 1039 case TR_PEER_CLIENT_GOT_SUGGEST: 1040 if( peer ) 1041 peerSuggestedPiece( t, peer, e->pieceIndex, FALSE ); 1042 break; 1043 1044 case TR_PEER_CLIENT_GOT_ALLOWED_FAST: 1045 if( peer ) 1046 peerSuggestedPiece( t, peer, e->pieceIndex, TRUE ); 1047 break; 1033 1048 1034 1049 case TR_PEER_CLIENT_GOT_DATA: … … 1036 1051 const time_t now = time( NULL ); 1037 1052 tr_torrent * tor = t->tor; 1038 1039 1053 tor->activityDate = now; 1040 1054 … … 1054 1068 /* update our atom */ 1055 1069 if( peer ) { 1056 struct peer_atom * a = getExistingAtom( t, &peer-> in_addr );1070 struct peer_atom * a = getExistingAtom( t, &peer->addr ); 1057 1071 if( e->wasPieceData ) 1058 1072 a->piece_data_time = now; … … 1066 1080 if( peer ) 1067 1081 { 1068 struct peer_atom * atom = getExistingAtom( t, 1069 &peer->in_addr ); 1070 const int peerIsSeed = e->progress >= 1.0; 1071 if( peerIsSeed ) 1072 { 1073 tordbg( t, "marking peer %s as a seed", 1074 tr_peerIoAddrStr( &atom->addr, 1075 atom->port ) ); 1082 struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 1083 const int peerIsSeed = e->progress >= 1.0; 1084 if( peerIsSeed ) { 1085 tordbg( t, "marking peer %s as a seed", tr_peerIoAddrStr( &atom->addr, atom->port ) ); 1076 1086 atom->flags |= ADDED_F_SEED_FLAG; 1077 } 1078 else 1079 { 1080 tordbg( t, "marking peer %s as a non-seed", 1081 tr_peerIoAddrStr( &atom->addr, 1082 atom->port ) ); 1087 } else { 1088 tordbg( t, "marking peer %s as a non-seed", tr_peerIoAddrStr( &atom->addr, atom->port ) ); 1083 1089 atom->flags &= ~ADDED_F_SEED_FLAG; 1084 1090 } … … 1091 1097 tr_torrent * tor = t->tor; 1092 1098 1093 tr_block_index_t block = _tr_block( tor, e->pieceIndex, 1094 e->offset ); 1099 tr_block_index_t block = _tr_block( tor, e->pieceIndex, e->offset ); 1095 1100 1096 1101 tr_cpBlockAdd( tor->completion, block ); … … 1102 1107 { 1103 1108 const tr_piece_index_t p = e->pieceIndex; 1104 const intok = tr_ioTestPiece( tor, p );1109 const tr_bool ok = tr_ioTestPiece( tor, p ); 1105 1110 1106 1111 if( !ok ) 1107 1112 { 1108 tr_torerr( tor, 1109 _( "Piece %lu, which was just downloaded, failed its checksum test" ), 1110 (unsigned long)p ); 1113 tr_torerr( tor, _( "Piece %lu, which was just downloaded, failed its checksum test" ), 1114 (unsigned long)p ); 1111 1115 } 1112 1116 … … 1119 1123 else 1120 1124 { 1121 int 1125 int i, peerCount; 1122 1126 tr_peer ** peers = getConnectedPeers( t, &peerCount ); 1123 1127 for( i = 0; i < peerCount; ++i ) … … 1136 1140 addStrike( t, peer ); 1137 1141 peer->doPurge = 1; 1142 tordbg( t, "setting doPurge because we got an EINVAL error" ); 1138 1143 } 1139 1144 else if( ( e->err == ERANGE ) … … 1143 1148 /* some protocol error from the peer */ 1144 1149 peer->doPurge = 1; 1150 tordbg( t, "setting doPurge because we got an ERANGE, EMSGSIZE, or ENOTCONN error" ); 1145 1151 } 1146 1152 else /* a local error, such as an IO error */ … … 1162 1168 1163 1169 static void 1164 ensureAtomExists( Torrent *t,1165 const struct in_addr* addr,1166 uint16_tport,1167 uint8_t 1168 uint8_t 1170 ensureAtomExists( Torrent * t, 1171 const tr_address * addr, 1172 tr_port port, 1173 uint8_t flags, 1174 uint8_t from ) 1169 1175 { 1170 1176 if( getExistingAtom( t, addr ) == NULL ) … … 1176 1182 a->flags = flags; 1177 1183 a->from = from; 1178 tordbg( t, "got a new atom: %s", 1179 tr_peerIoAddrStr( &a->addr, a->port ) ); 1184 tordbg( t, "got a new atom: %s", tr_peerIoAddrStr( &a->addr, a->port ) ); 1180 1185 tr_ptrArrayInsertSorted( t->pool, a, comparePeerAtoms ); 1181 1186 } … … 1191 1196 getPeerCount( const Torrent * t ) 1192 1197 { 1193 return tr_ptrArraySize( t->peers ) + tr_ptrArraySize( 1194 t->outgoingHandshakes ); 1198 return tr_ptrArraySize( t->peers ) + tr_ptrArraySize( t->outgoingHandshakes ); 1195 1199 } 1196 1200 1197 1201 /* FIXME: this is kind of a mess. */ 1198 static int1199 myHandshakeDoneCB( tr_handshake *handshake,1200 tr_peerIo *io,1202 static tr_bool 1203 myHandshakeDoneCB( tr_handshake * handshake, 1204 tr_peerIo * io, 1201 1205 int isConnected, 1202 1206 const uint8_t * peer_id, 1203 void *vmanager )1204 { 1205 intok = isConnected;1206 intsuccess = FALSE;1207 uint16_tport;1208 const struct in_addr* addr;1209 tr_peerMgr * manager = (tr_peerMgr*)vmanager;1210 Torrent *t;1211 tr_handshake *ours;1207 void * vmanager ) 1208 { 1209 tr_bool ok = isConnected; 1210 tr_bool success = FALSE; 1211 tr_port port; 1212 const tr_address * addr; 1213 tr_peerMgr * manager = vmanager; 1214 Torrent * t; 1215 tr_handshake * ours; 1212 1216 1213 1217 assert( io ); … … 1243 1247 ++atom->numFails; 1244 1248 } 1245 1246 tr_peerIoFree( io );1247 1249 } 1248 1250 else /* looking good */ … … 1257 1259 { 1258 1260 tordbg( t, "banned peer %s tried to reconnect", 1259 tr_peerIoAddrStr( &atom->addr, 1260 atom->port ) ); 1261 tr_peerIoFree( io ); 1261 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 1262 1262 } 1263 1263 else if( tr_peerIoIsIncoming( io ) … … 1265 1265 1266 1266 { 1267 tr_peerIoFree( io );1268 1267 } 1269 1268 else … … 1273 1272 if( peer ) /* we already have this peer */ 1274 1273 { 1275 tr_peerIoFree( io );1276 1274 } 1277 1275 else … … 1289 1287 1290 1288 peer->port = port; 1291 peer->io = io;1292 peer->msgs =tr_peerMsgsNew( t->tor, peer, peerCallbackFunc, t, &peer->msgsTag );1289 peer->io = tr_handshakeStealIO( handshake ); 1290 tr_peerMsgsNew( t->tor, peer, peerCallbackFunc, t, &peer->msgsTag ); 1293 1291 tr_peerIoSetBandwidth( io, peer->bandwidth ); 1294 1292 … … 1298 1296 } 1299 1297 1298 if( !success ) 1299 tr_ptrArrayAppend( manager->finishedHandshakes, handshake ); 1300 1300 1301 if( t ) 1301 1302 torrentUnlock( t ); … … 1305 1306 1306 1307 void 1307 tr_peerMgrAddIncoming( tr_peerMgr * 1308 struct in_addr* addr,1309 uint16_tport,1310 int 1308 tr_peerMgrAddIncoming( tr_peerMgr * manager, 1309 tr_address * addr, 1310 tr_port port, 1311 int socket ) 1311 1312 { 1312 1313 managerLock( manager ); … … 1314 1315 if( tr_sessionIsAddressBlocked( manager->session, addr ) ) 1315 1316 { 1316 tr_dbg( "Banned IP address \"%s\" tried to connect to us", 1317 inet_ntoa( *addr ) ); 1317 tr_dbg( "Banned IP address \"%s\" tried to connect to us", inet_ntoa( *addr ) ); 1318 1318 tr_netClose( socket ); 1319 1319 } … … 1339 1339 1340 1340 managerUnlock( manager ); 1341 } 1342 1343 static tr_bool 1344 tr_isPex( const tr_pex * pex ) 1345 { 1346 return pex && tr_isAddress( &pex->addr ); 1341 1347 } 1342 1348 … … 1347 1353 const tr_pex * pex ) 1348 1354 { 1349 Torrent * t; 1350 1351 managerLock( manager ); 1352 1353 t = getExistingTorrent( manager, torrentHash ); 1354 if( !tr_sessionIsAddressBlocked( t->manager->session, &pex->in_addr ) ) 1355 ensureAtomExists( t, &pex->in_addr, pex->port, pex->flags, from ); 1356 1357 managerUnlock( manager ); 1355 if( tr_isPex( pex ) ) /* safeguard against corrupt data */ 1356 { 1357 Torrent * t; 1358 managerLock( manager ); 1359 1360 t = getExistingTorrent( manager, torrentHash ); 1361 if( !tr_sessionIsAddressBlocked( t->manager->session, &pex->addr ) ) 1362 ensureAtomExists( t, &pex->addr, pex->port, pex->flags, from ); 1363 1364 managerUnlock( manager ); 1365 } 1358 1366 } 1359 1367 … … 1372 1380 for( i = 0; i < n; ++i ) 1373 1381 { 1374 memcpy( &pex[i]. in_addr, walk, 4 ); walk += 4;1382 memcpy( &pex[i].addr, walk, 4 ); walk += 4; 1375 1383 memcpy( &pex[i].port, walk, 2 ); walk += 2; 1376 1384 if( added_f && ( n == added_f_len ) ) … … 1406 1414 if( tr_bitfieldHas( peer->blame, pieceIndex ) ) 1407 1415 { 1408 tordbg( 1409 t, 1410 "peer %s contributed to corrupt piece (%d); now has %d strikes", 1411 tr_peerIoAddrStr( &peer->in_addr, peer->port ), 1412 pieceIndex, (int)peer->strikes + 1 ); 1416 tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes", 1417 tr_peerIoAddrStr( &peer->addr, peer->port ), 1418 pieceIndex, (int)peer->strikes + 1 ); 1413 1419 addStrike( t, peer ); 1414 1420 } … … 1418 1424 1419 1425 int 1420 tr_pexCompare( const void * va, 1421 const void * vb ) 1426 tr_pexCompare( const void * va, const void * vb ) 1422 1427 { 1423 1428 const tr_pex * a = va; 1424 1429 const tr_pex * b = vb; 1425 int i = 1426 memcmp( &a->in_addr, &b->in_addr, sizeof( struct in_addr ) ); 1427 1428 if( i ) return i; 1429 if( a->port < b->port ) return -1; 1430 if( a->port > b->port ) return 1; 1430 int i; 1431 1432 assert( tr_isPex( a ) ); 1433 assert( tr_isPex( b ) ); 1434 1435 if(( i = tr_compareAddresses( &a->addr, &b->addr ))) 1436 return i; 1437 1438 if( a->port != b->port ) 1439 return a->port < b->port ? -1 : 1; 1440 1431 1441 return 0; 1432 1442 } 1433 1434 int tr_pexCompare( const void * a,1435 const void * b );1436 1443 1437 1444 static int … … 1448 1455 1449 1456 int 1450 tr_peerMgrGetPeers( tr_peerMgr *manager,1451 const uint8_t * torrentHash,1452 tr_pex **setme_pex )1457 tr_peerMgrGetPeers( tr_peerMgr * manager, 1458 const uint8_t * torrentHash, 1459 tr_pex ** setme_pex ) 1453 1460 { 1454 1461 int peerCount = 0; … … 1458 1465 1459 1466 t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash ); 1460 if( !t)1467 if( t == NULL ) 1461 1468 { 1462 1469 *setme_pex = NULL; … … 1469 1476 tr_pex * walk = pex; 1470 1477 1471 for( i = 0; i <peerCount; ++i, ++walk )1478 for( i=0; i<peerCount; ++i, ++walk ) 1472 1479 { 1473 1480 const tr_peer * peer = peers[i]; 1474 walk->in_addr = peer->in_addr; 1481 const struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 1482 1483 assert( tr_isAddress( &peer->addr ) ); 1484 walk->addr = peer->addr; 1475 1485 walk->port = peer->port; 1476 1486 walk->flags = 0; 1477 if( peerPrefersCrypto( peer ) ) walk->flags |= ADDED_F_ENCRYPTION_FLAG; 1478 if( peer->progress >= 1.0 ) walk->flags |= ADDED_F_SEED_FLAG; 1487 if( peerPrefersCrypto( peer ) ) 1488 walk->flags |= ADDED_F_ENCRYPTION_FLAG; 1489 if( ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 ) ) 1490 walk->flags |= ADDED_F_SEED_FLAG; 1479 1491 } 1480 1492 … … 1603 1615 const tr_torrent * tor; 1604 1616 float interval; 1605 int isComplete;1617 tr_bool isSeed; 1606 1618 int peerCount; 1607 1619 const tr_peer ** peers; … … 1612 1624 tor = t->tor; 1613 1625 interval = tor->info.pieceCount / (float)tabCount; 1614 isComplete = tor 1615 && ( tr_cpGetStatus ( tor->completion ) == TR_CP_COMPLETE ); 1626 isSeed = tor && ( tr_cpGetStatus ( tor->completion ) == TR_CP_COMPLETE ); 1616 1627 peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount ); 1617 1628 … … 1622 1633 const int piece = i * interval; 1623 1634 1624 if( is Complete|| tr_cpPieceIsComplete( tor->completion, piece ) )1635 if( isSeed || tr_cpPieceIsComplete( tor->completion, piece ) ) 1625 1636 tab[i] = -1; 1626 else if( peerCount ) 1627 { 1637 else if( peerCount ) { 1628 1638 int j; 1629 1639 for( j = 0; j < peerCount; ++j ) … … 1645 1655 tr_peer ** peers; 1646 1656 tr_bitfield * pieces; 1647 1648 1657 managerLock( manager ); 1649 1658 … … 1663 1672 const uint8_t * torrentHash ) 1664 1673 { 1665 int 1674 int ret; 1666 1675 const Torrent * t; 1667 1668 1676 managerLock( manager ); 1669 1677 1670 1678 t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash ); 1671 ret = t && ( !tr_ptrArrayEmpty( t->peers ) 1672 || !tr_ptrArrayEmpty( t->webseeds ) ); 1679 ret = t && ( !tr_ptrArrayEmpty( t->peers ) || !tr_ptrArrayEmpty( t->webseeds ) ); 1673 1680 1674 1681 managerUnlock( manager ); … … 1678 1685 void 1679 1686 tr_peerMgrTorrentStats( const tr_peerMgr * manager, 1680 const uint8_t *torrentHash,1681 int *setmePeersKnown,1682 int *setmePeersConnected,1683 int *setmeSeedsConnected,1684 int *setmeWebseedsSendingToUs,1685 int *setmePeersSendingToUs,1686 int *setmePeersGettingFromUs,1687 int *setmePeersFrom )1688 { 1689 int 1690 const Torrent * 1691 const tr_peer ** 1687 const uint8_t * torrentHash, 1688 int * setmePeersKnown, 1689 int * setmePeersConnected, 1690 int * setmeSeedsConnected, 1691 int * setmeWebseedsSendingToUs, 1692 int * setmePeersSendingToUs, 1693 int * setmePeersGettingFromUs, 1694 int * setmePeersFrom ) 1695 { 1696 int i, size; 1697 const Torrent * t; 1698 const tr_peer ** peers; 1692 1699 const tr_webseed ** webseeds; 1693 1700 … … 1704 1711 *setmeWebseedsSendingToUs = 0; 1705 1712 1706 for( i = 0; i <TR_PEER_FROM__MAX; ++i )1713 for( i=0; i<TR_PEER_FROM__MAX; ++i ) 1707 1714 setmePeersFrom[i] = 0; 1708 1715 1709 for( i = 0; i <size; ++i )1710 { 1711 const tr_peer * 1712 const struct peer_atom * atom = getExistingAtom( t, &peer-> in_addr );1716 for( i=0; i<size; ++i ) 1717 { 1718 const tr_peer * peer = peers[i]; 1719 const struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 1713 1720 1714 1721 if( peer->io == NULL ) /* not connected */ 1715 1722 continue; 1716 1723 1717 ++ *setmePeersConnected;1724 ++*setmePeersConnected; 1718 1725 1719 1726 ++setmePeersFrom[atom->from]; 1720 1727 1721 1728 if( clientIsDownloadingFrom( peer ) ) 1722 ++ *setmePeersSendingToUs;1729 ++*setmePeersSendingToUs; 1723 1730 1724 1731 if( clientIsUploadingTo( peer ) ) 1725 ++ *setmePeersGettingFromUs;1732 ++*setmePeersGettingFromUs; 1726 1733 1727 1734 if( atom->flags & ADDED_F_SEED_FLAG ) 1728 ++ *setmeSeedsConnected;1735 ++*setmeSeedsConnected; 1729 1736 } 1730 1737 1731 1738 webseeds = (const tr_webseed **) tr_ptrArrayPeek( t->webseeds, &size ); 1732 for( i = 0; i < size; ++i ) 1733 { 1739 for( i=0; i<size; ++i ) 1734 1740 if( tr_webseedIsActive( webseeds[i] ) ) 1735 ++ * setmeWebseedsSendingToUs; 1736 } 1741 ++*setmeWebseedsSendingToUs; 1737 1742 1738 1743 managerUnlock( manager ); … … 1743 1748 const uint8_t * torrentHash ) 1744 1749 { 1745 const Torrent * 1750 const Torrent * t; 1746 1751 const tr_webseed ** webseeds; 1747 int 1748 int 1749 float * 1752 int i; 1753 int webseedCount; 1754 float * ret; 1750 1755 1751 1756 assert( manager ); … … 1758 1763 ret = tr_new0( float, webseedCount ); 1759 1764 1760 for( i = 0; i <webseedCount; ++i )1765 for( i=0; i<webseedCount; ++i ) 1761 1766 if( !tr_webseedGetSpeed( webseeds[i], &ret[i] ) ) 1762 1767 ret[i] = -1.0; … … 1767 1772 1768 1773 double 1769 tr_peerGetPieceSpeed( const tr_peer * peer, 1770 tr_direction direction ) 1774 tr_peerGetPieceSpeed( const tr_peer * peer, tr_direction direction ) 1771 1775 { 1772 1776 assert( peer ); … … 1798 1802 char * pch; 1799 1803 const tr_peer * peer = peers[i]; 1800 const struct peer_atom * atom = getExistingAtom( t, &peer-> in_addr );1804 const struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 1801 1805 tr_peer_stat * stat = ret + i; 1802 1806 1803 tr_netNtop( &peer-> in_addr, stat->addr, sizeof( stat->addr ) );1807 tr_netNtop( &peer->addr, stat->addr, sizeof( stat->addr ) ); 1804 1808 tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ), 1805 1809 sizeof( stat->client ) ); … … 1817 1821 stat->isDownloadingFrom = clientIsDownloadingFrom( peer ); 1818 1822 stat->isUploadingTo = clientIsUploadingTo( peer ); 1823 stat->isSeed = ( atom->uploadOnly == UPLOAD_ONLY_YES ) || ( peer->progress >= 1.0 ); 1819 1824 1820 1825 pch = stat->flagStr; … … 1824 1829 if( stat->isUploadingTo ) *pch++ = 'U'; 1825 1830 else if( stat->peerIsInterested ) *pch++ = 'u'; 1826 if( !stat->clientIsChoked && !stat->clientIsInterested ) *pch++ = 1827 'K'; 1831 if( !stat->clientIsChoked && !stat->clientIsInterested ) *pch++ = 'K'; 1828 1832 if( !stat->peerIsChoked && !stat->peerIsInterested ) *pch++ = '?'; 1829 1833 if( stat->isEncrypted ) *pch++ = 'E'; … … 1899 1903 { 1900 1904 tr_peer * peer = peers[i]; 1905 struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 1906 1901 1907 if( peer->progress >= 1.0 ) /* choke all seeds */ 1908 { 1902 1909 tr_peerMsgsSetChoke( peer->msgs, TRUE ); 1903 else if( chokeAll ) 1910 } 1911 else if( atom->uploadOnly == UPLOAD_ONLY_YES ) /* choke partial seeds */ 1912 { 1904 1913 tr_peerMsgsSetChoke( peer->msgs, TRUE ); 1905 else { 1914 } 1915 else if( chokeAll ) /* choke everyone if we're not uploading */ 1916 { 1917 tr_peerMsgsSetChoke( peer->msgs, TRUE ); 1918 } 1919 else 1920 { 1906 1921 struct ChokeData * n = &choke[size++]; 1907 1922 n->peer = peer; … … 1928 1943 */ 1929 1944 unchokedInterested = 0; 1930 for( i = 0; i < size && unchokedInterested < MAX_UNCHOKED_PEERS; ++i ) 1931 { 1945 for( i=0; i<size && unchokedInterested<MAX_UNCHOKED_PEERS; ++i ) { 1932 1946 choke[i].doUnchoke = 1; 1933 1947 if( choke[i].isInterested ) … … 1938 1952 if( i < size ) 1939 1953 { 1940 int 1954 int n; 1941 1955 struct ChokeData * c; 1942 tr_ptrArray * 1943 1944 for( ; i <size; ++i )1956 tr_ptrArray * randPool = tr_ptrArrayNew( ); 1957 1958 for( ; i<size; ++i ) 1945 1959 { 1946 1960 if( choke[i].isInterested ) 1947 1961 { 1948 1962 const tr_peer * peer = choke[i].peer; 1949 int 1963 int x = 1, y; 1950 1964 if( isNew( peer ) ) x *= 3; 1951 1965 if( isSame( peer ) ) x *= 3; 1952 for( y = 0; y <x; ++y )1966 for( y=0; y<x; ++y ) 1953 1967 tr_ptrArrayAppend( randPool, &choke[i] ); 1954 1968 } 1955 1969 } 1956 1970 1957 if( ( n = tr_ptrArraySize( randPool ) ))1971 if(( n = tr_ptrArraySize( randPool ))) 1958 1972 { 1959 c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n ) 1973 c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n )); 1960 1974 c->doUnchoke = 1; 1961 1975 t->optimistic = c->peer; … … 1965 1979 } 1966 1980 1967 for( i = 0; i <size; ++i )1981 for( i=0; i<size; ++i ) 1968 1982 tr_peerMsgsSetChoke( choke[i].peer->msgs, !choke[i].doUnchoke ); 1969 1983 … … 1997 2011 const tr_torrent * tor = t->tor; 1998 2012 const time_t now = time( NULL ); 1999 const struct peer_atom * atom = getExistingAtom( t, &peer-> in_addr );2013 const struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 2000 2014 2001 2015 /* if it's marked for purging, close it */ … … 2003 2017 { 2004 2018 tordbg( t, "purging peer %s because its doPurge flag is set", 2005 tr_peerIoAddrStr( &atom->addr, 2006 atom->port ) ); 2019 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 2007 2020 return TRUE; 2008 2021 } … … 2017 2030 else if( peer->progress < tr_cpPercentDone( tor->completion ) ) 2018 2031 peerHasEverything = FALSE; 2019 else 2020 { 2021 tr_bitfield * tmp = 2022 tr_bitfieldDup( tr_cpPieceBitfield( tor->completion ) ); 2032 else { 2033 tr_bitfield * tmp = tr_bitfieldDup( tr_cpPieceBitfield( tor->completion ) ); 2023 2034 tr_bitfieldDifference( tmp, peer->have ); 2024 2035 peerHasEverything = tr_bitfieldCountTrueBits( tmp ) == 0; 2025 2036 tr_bitfieldFree( tmp ); 2026 2037 } 2027 if( peerHasEverything 2028 && ( !tr_torrentAllowsPex( tor ) || ( now - atom->time >= 30 ) ))2038 2039 if( peerHasEverything && ( !tr_torrentAllowsPex(tor) || (now-atom->time>=30 ))) 2029 2040 { 2030 2041 tordbg( t, "purging peer %s because we're both seeds", 2031 tr_peerIoAddrStr( &atom->addr, 2032 atom->port ) ); 2042 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 2033 2043 return TRUE; 2034 2044 } … … 2060 2070 2061 2071 static tr_peer ** 2062 getPeersToClose( Torrent * t, 2063 int * setmeSize ) 2064 { 2065 int i, peerCount, outsize; 2066 tr_peer ** peers = (tr_peer**) tr_ptrArrayPeek( t->peers, 2067 &peerCount ); 2072 getPeersToClose( Torrent * t, int * setmeSize ) 2073 { 2074 int i, peerCount, outsize; 2075 tr_peer ** peers = (tr_peer**) tr_ptrArrayPeek( t->peers, &peerCount ); 2068 2076 struct tr_peer ** ret = tr_new( tr_peer *, peerCount ); 2069 2077 … … 2101 2109 return a->time < b->time ? -1 : 1; 2102 2110 2111 /* all other things being equal, prefer peers whose 2112 * information comes from a more reliable source */ 2113 if( a->from != b->from ) 2114 return a->from < b->from ? -1 : 1; 2115 2103 2116 return 0; 2104 2117 } … … 2113 2126 * data, try to reconnect to them sooner rather that later -- we don't 2114 2127 * want network troubles to get in the way of a good peer. */ 2115 if( ( now - atom->piece_data_time ) <= 2116 ( MINIMUM_RECONNECT_INTERVAL_SECS * 2 ) ) 2128 if( ( now - atom->piece_data_time ) <= ( MINIMUM_RECONNECT_INTERVAL_SECS * 2 ) ) 2117 2129 sec = MINIMUM_RECONNECT_INTERVAL_SECS; 2118 2130 … … 2123 2135 /* otherwise, the interval depends on how many times we've tried 2124 2136 * and failed to connect to the peer */ 2125 else switch( atom->numFails ) 2126 { 2127 case 0: 2128 sec = 0; break; 2129 2130 case 1: 2131 sec = 5; break; 2132 2133 case 2: 2134 sec = 2 * 60; break; 2135 2136 case 3: 2137 sec = 15 * 60; break; 2138 2139 case 4: 2140 sec = 30 * 60; break; 2141 2142 case 5: 2143 sec = 60 * 60; break; 2144 2145 default: 2146 sec = 120 * 60; break; 2147 } 2137 else switch( atom->numFails ) { 2138 case 0: sec = 0; break; 2139 case 1: sec = 5; break; 2140 case 2: sec = 2 * 60; break; 2141 case 3: sec = 15 * 60; break; 2142 case 4: sec = 30 * 60; break; 2143 case 5: sec = 60 * 60; break; 2144 default: sec = 120 * 60; break; 2145 } 2148 2146 2149 2147 return sec; … … 2151 2149 2152 2150 static struct peer_atom ** 2153 getPeerCandidates( Torrent * t, 2154 int * setmeSize ) 2151 getPeerCandidates( Torrent * t, int * setmeSize ) 2155 2152 { 2156 2153 int i, atomCount, retCount; … … 2185 2182 2186 2183 /* no need to connect if we're both seeds... */ 2187 if( seed && ( atom->flags & ADDED_F_SEED_FLAG ) ) 2184 if( seed && ( ( atom->flags & ADDED_F_SEED_FLAG ) || 2185 ( atom->uploadOnly == UPLOAD_ONLY_YES ) ) ) 2188 2186 continue; 2189 2187 … … 2192 2190 if( ( now - atom->time ) < interval ) 2193 2191 { 2194 tordbg( 2195 t, 2196 "RECONNECT peer %d (%s) is in its grace period of %d seconds..", 2197 i, tr_peerIoAddrStr( &atom->addr, 2198 atom->port ), interval ); 2192 tordbg( t, "RECONNECT peer %d (%s) is in its grace period of %d seconds..", 2193 i, tr_peerIoAddrStr( &atom->addr, atom->port ), interval ); 2199 2194 continue; 2200 2195 } … … 2235 2230 else 2236 2231 { 2237 int 2232 int i, nCandidates, nBad; 2238 2233 struct peer_atom ** candidates = getPeerCandidates( t, &nCandidates ); 2239 struct tr_peer ** 2234 struct tr_peer ** connections = getPeersToClose( t, &nBad ); 2240 2235 2241 2236 if( nBad || nCandidates ) 2242 tordbg( 2243 t, "reconnect pulse for [%s]: %d bad connections, " 2244 "%d connection candidates, %d atoms, max per pulse is %d", 2245 t->tor->info.name, nBad, nCandidates, 2246 tr_ptrArraySize( t->pool ), 2247 (int)MAX_RECONNECTIONS_PER_PULSE ); 2237 tordbg( t, "reconnect pulse for [%s]: %d bad connections, " 2238 "%d connection candidates, %d atoms, max per pulse is %d", 2239 t->tor->info.name, nBad, nCandidates, 2240 tr_ptrArraySize( t->pool ), 2241 (int)MAX_RECONNECTIONS_PER_PULSE ); 2248 2242 2249 2243 /* disconnect some peers. … … 2251 2245 so reset their `numFails' weight to zero. otherwise we connected 2252 2246 to them fruitlessly, so mark it as another fail */ 2253 for( i = 0; i < nBad; ++i ) 2254 { 2255 tr_peer * peer = connections[i]; 2256 struct peer_atom * atom = getExistingAtom( t, &peer->in_addr ); 2247 for( i = 0; i < nBad; ++i ) { 2248 tr_peer * peer = connections[i]; 2249 struct peer_atom * atom = getExistingAtom( t, &peer->addr ); 2257 2250 if( atom->piece_data_time ) 2258 2251 atom->numFails = 0; 2259 2252 else 2260 2253 ++atom->numFails; 2261 tordbg( t, "removing bad peer %s", 2262 tr_peerIoGetAddrStr( peer->io ) ); 2254 tordbg( t, "removing bad peer %s", tr_peerIoGetAddrStr( peer->io ) ); 2263 2255 removePeer( t, peer ); 2264 2256 } … … 2268 2260 && ( i < MAX_RECONNECTIONS_PER_PULSE ) 2269 2261 && ( getPeerCount( t ) < getMaxPeerCount( t->tor ) ) 2270 && ( newConnectionsThisSecond < MAX_CONNECTIONS_PER_SECOND ); 2271 ++i ) 2262 && ( newConnectionsThisSecond < MAX_CONNECTIONS_PER_SECOND ); ++i ) 2272 2263 { 2273 2264 tr_peerMgr * mgr = t->manager; … … 2278 2269 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 2279 2270 2280 io = 2281 tr_peerIoNewOutgoing( mgr->session, &atom->addr, atom->port, 2282 t->hash ); 2271 io = tr_peerIoNewOutgoing( mgr->session, &atom->addr, atom->port, t->hash ); 2283 2272 if( io == NULL ) 2284 2273 { … … 2287 2276 else 2288 2277 { 2289 tr_handshake * handshake = tr_handshakeNew( 2290 io, 2291 mgr->session-> 2292 encryptionMode, 2293 myHandshakeDoneCB, 2294 mgr ); 2278 tr_handshake * handshake = tr_handshakeNew( io, 2279 mgr->session->encryptionMode, 2280 myHandshakeDoneCB, 2281 mgr ); 2295 2282 2296 2283 assert( tr_peerIoGetTorrentHash( io ) ); … … 2340 2327 bandwidthPulse( void * vmgr ) 2341 2328 { 2329 tr_handshake * handshake; 2342 2330 tr_peerMgr * mgr = vmgr; 2343 2331 managerLock( mgr ); 2344 2332 2333 /* FIXME: this next line probably isn't necessary... */ 2345 2334 pumpAllPeers( mgr ); 2335 2336 /* allocate bandwidth to the peers */ 2346 2337 tr_bandwidthAllocate( mgr->session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC ); 2347 2338 tr_bandwidthAllocate( mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC ); 2348 pumpAllPeers( mgr ); 2339 2340 /* free all the finished handshakes */ 2341 while(( handshake = tr_ptrArrayPop( mgr->finishedHandshakes ))) 2342 tr_handshakeFree( handshake ); 2349 2343 2350 2344 managerUnlock( mgr ); -
branches/1.4x/libtransmission/peer-mgr.h
r7176 r7455 43 43 typedef struct tr_pex 44 44 { 45 struct in_addr in_addr;45 tr_address addr; 46 46 uint16_t port; 47 47 uint8_t flags; … … 55 55 void tr_peerMgrFree( tr_peerMgr * manager ); 56 56 57 inttr_peerMgrPeerIsSeed( const tr_peerMgr * mgr,58 const uint8_t * torrentHash,59 const struct in_addr * addr );57 tr_bool tr_peerMgrPeerIsSeed( const tr_peerMgr * mgr, 58 const uint8_t * torrentHash, 59 const struct in_addr * addr ); 60 60 61 61 void tr_peerMgrAddIncoming( tr_peerMgr * manager, -
branches/1.4x/libtransmission/peer-msgs.c
r7354 r7455 25 25 #include "crypto.h" 26 26 #include "inout.h" 27 #include "iobuf.h"28 27 #ifdef WIN32 29 28 #include "net.h" /* for ECONN */ … … 55 54 BT_CANCEL = 8, 56 55 BT_PORT = 9, 57 BT_SUGGEST = 13, 58 BT_HAVE_ALL = 14, 59 BT_HAVE_NONE = 15, 60 BT_REJECT = 16, 61 BT_ALLOWED_FAST = 17, 56 57 BT_FEXT_SUGGEST = 13, 58 BT_FEXT_HAVE_ALL = 14, 59 BT_FEXT_HAVE_NONE = 15, 60 BT_FEXT_REJECT = 16, 61 BT_FEXT_ALLOWED_FAST = 17, 62 62 63 BT_LTEP = 20, 63 64 … … 65 66 66 67 TR_LTEP_PEX = 1, 68 69 67 70 68 71 MIN_CHOKE_PERIOD_SEC = ( 10 ), … … 72 75 73 76 PEX_INTERVAL = ( 90 * 1000 ), /* msec between sendPex() calls */ 74 PEER_PULSE_INTERVAL = ( 250 ), /* msec between peerPulse() calls75 */76 77 77 78 MAX_QUEUE_SIZE = ( 100 ), 78 79 /* (fast peers) max number of pieces we fast-allow to another peer */80 MAX_FAST_ALLOWED_COUNT = 10,81 82 /* (fast peers) max threshold for allowing fast-pieces requests */83 MAX_FAST_ALLOWED_THRESHOLD = 10,84 79 85 80 /* how long an unsent request can stay queued before it's returned … … 98 93 /* number of pieces to remove from the bitfield when 99 94 * lazy bitfields are turned on */ 100 LAZY_PIECE_COUNT = 26 95 LAZY_PIECE_COUNT = 26, 96 97 /* number of pieces we'll allow in our fast set */ 98 MAX_FAST_SET_SIZE = 3 101 99 }; 102 100 … … 122 120 123 121 static int 124 compareRequest( const void * va, 125 const void * vb ) 122 compareRequest( const void * va, const void * vb ) 126 123 { 127 124 const struct peer_request * a = va; … … 170 167 171 168 static void 172 reqListCopy( struct request_list * dest, 173 const struct request_list * src ) 169 reqListCopy( struct request_list * dest, const struct request_list * src ) 174 170 { 175 171 dest->count = dest->max = src->count; 176 dest->requests = 177 tr_memdup( src->requests, dest->count * sizeof( struct peer_request ) ); 172 dest->requests = tr_memdup( src->requests, dest->count * sizeof( struct peer_request ) ); 178 173 } 179 174 … … 185 180 186 181 memmove( &list->requests[i], 187 &list->requests[i + 1],188 sizeof( struct peer_request ) * ( --list->count - i ) );182 &list->requests[i + 1], 183 sizeof( struct peer_request ) * ( --list->count - i ) ); 189 184 } 190 185 … … 260 255 }; 261 256 257 /** 258 * Low-level communication state information about a connected peer. 259 * 260 * This structure remembers the low-level protocol states that we're 261 * in with this peer, such as active requests, pex messages, and so on. 262 * Its fields are all private to peer-msgs.c. 263 * 264 * Data not directly involved with sending & receiving messages is 265 * stored in tr_peer, where it can be accessed by both peermsgs and 266 * the peer manager. 267 * 268 * @see struct peer_atom 269 * @see tr_peer 270 */ 262 271 struct tr_peermsgs 263 272 { … … 266 275 tr_bool clientSentLtepHandshake; 267 276 tr_bool peerSentLtepHandshake; 277 tr_bool haveFastSet; 268 278 269 279 uint8_t state; 270 280 uint8_t ut_pex_id; 271 281 uint16_t pexCount; 272 uint16_t minActiveRequests;273 282 uint16_t maxActiveRequests; 283 284 size_t fastsetSize; 285 tr_piece_index_t fastset[MAX_FAST_SET_SIZE]; 274 286 275 287 /* how long the outMessages batch should be allowed to grow before … … 278 290 int outMessagesBatchPeriod; 279 291 280 tr_peer * info;292 tr_peer * peer; 281 293 282 294 tr_session * session; 283 295 tr_torrent * torrent; 284 tr_peerIo * io;285 296 286 297 tr_publisher_t * publisher; … … 289 300 290 301 struct request_list peerAskedFor; 291 struct request_list peerAskedForFast;292 302 struct request_list clientAskedFor; 293 303 struct request_list clientWillAskFor; 294 304 295 tr_timer * pexTimer; 305 tr_timer * pexTimer; 306 tr_pex * pex; 296 307 297 308 time_t clientSentPexAt; … … 301 312 time_t outMessagesBatchedAt; 302 313 303 tr_bitfield * peerAllowedPieces;304 305 314 struct tr_incoming incoming; 306 307 tr_pex * pex;308 315 309 316 /* if the peer supports the Extension Protocol in BEP 10 and … … 318 325 319 326 static void 320 myDebug( const char * file, 321 int line, 327 myDebug( const char * file, int line, 322 328 const struct tr_peermsgs * msgs, 323 const char * fmt, 324 ... ) 329 const char * fmt, ... ) 325 330 { 326 331 FILE * fp = tr_getLog( ); … … 336 341 tr_getLogTimeStr( timestr, sizeof( timestr ) ), 337 342 msgs->torrent->info.name, 338 tr_peerIoGetAddrStr( msgs-> io ),339 msgs-> info->client );343 tr_peerIoGetAddrStr( msgs->peer->io ), 344 msgs->peer->client ); 340 345 va_start( args, fmt ); 341 346 evbuffer_add_vprintf( buf, fmt, args ); … … 371 376 372 377 static void 373 protocolSendRequest( tr_peermsgs * msgs, 378 dbgOutMessageLen( tr_peermsgs * msgs ) 379 { 380 dbgmsg( msgs, "outMessage size is now %zu", EVBUFFER_LENGTH( msgs->outMessages ) ); 381 } 382 383 static void 384 protocolSendReject( tr_peermsgs * msgs, const struct peer_request * req ) 385 { 386 tr_peerIo * io = msgs->peer->io; 387 struct evbuffer * out = msgs->outMessages; 388 389 assert( tr_peerIoSupportsFEXT( msgs->peer->io ) ); 390 391 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 3 * sizeof( uint32_t ) ); 392 tr_peerIoWriteUint8 ( io, out, BT_FEXT_REJECT ); 393 tr_peerIoWriteUint32( io, out, req->index ); 394 tr_peerIoWriteUint32( io, out, req->offset ); 395 tr_peerIoWriteUint32( io, out, req->length ); 396 397 dbgmsg( msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length ); 398 dbgOutMessageLen( msgs ); 399 } 400 401 static void 402 protocolSendRequest( tr_peermsgs * msgs, 374 403 const struct peer_request * req ) 375 404 { 376 tr_peerIo * io = msgs->io;405 tr_peerIo * io = msgs->peer->io; 377 406 struct evbuffer * out = msgs->outMessages; 378 407 … … 382 411 tr_peerIoWriteUint32( io, out, req->offset ); 383 412 tr_peerIoWriteUint32( io, out, req->length ); 384 dbgmsg( msgs, "requesting %u:%u->%u... outMessage size is now %d", 385 req->index, req->offset, req->length, (int)EVBUFFER_LENGTH( out ) ); 413 414 dbgmsg( msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length ); 415 dbgOutMessageLen( msgs ); 386 416 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 387 417 } 388 418 389 419 static void 390 protocolSendCancel( tr_peermsgs *msgs,420 protocolSendCancel( tr_peermsgs * msgs, 391 421 const struct peer_request * req ) 392 422 { 393 tr_peerIo * io = msgs->io;423 tr_peerIo * io = msgs->peer->io; 394 424 struct evbuffer * out = msgs->outMessages; 395 425 … … 399 429 tr_peerIoWriteUint32( io, out, req->offset ); 400 430 tr_peerIoWriteUint32( io, out, req->length ); 401 dbgmsg( msgs, "cancelling %u:%u->%u... outMessage size is now %d", 402 req->index, req->offset, req->length, (int)EVBUFFER_LENGTH( out ) ); 431 432 dbgmsg( msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length ); 433 dbgOutMessageLen( msgs ); 403 434 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 404 435 } … … 408 439 uint32_t index ) 409 440 { 410 tr_peerIo * io = msgs->io;441 tr_peerIo * io = msgs->peer->io; 411 442 struct evbuffer * out = msgs->outMessages; 412 443 413 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + sizeof( uint32_t) );444 tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + sizeof(uint32_t) ); 414 445 tr_peerIoWriteUint8 ( io, out, BT_HAVE ); 415 446 tr_peerIoWriteUint32( io, out, index ); 416 dbgmsg( msgs, "sending Have %u.. outMessage size is now %d", 417 index, (int)EVBUFFER_LENGTH( out ) ); 447 448 dbgmsg( msgs, "sending Have %u", index ); 449 dbgOutMessageLen( msgs ); 418 450 pokeBatchPeriod( msgs, LOW_PRIORITY_INTERVAL_SECS ); 419 451 } 452 453 #if 0 454 static void 455 protocolSendAllowedFast( tr_peermsgs * msgs, uint32_t pieceIndex ) 456 { 457 tr_peerIo * io = msgs->peer->io; 458 struct evbuffer * out = msgs->outMessages; 459 460 assert( tr_peerIoSupportsFEXT( msgs->peer->io ) ); 461 462 tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + sizeof(uint32_t) ); 463 tr_peerIoWriteUint8 ( io, out, BT_FEXT_ALLOWED_FAST ); 464 tr_peerIoWriteUint32( io, out, pieceIndex ); 465 466 dbgmsg( msgs, "sending Allowed Fast %u...", pieceIndex ); 467 dbgOutMessageLen( msgs ); 468 } 469 #endif 420 470 421 471 static void … … 423 473 int choke ) 424 474 { 425 tr_peerIo * io = msgs->io;475 tr_peerIo * io = msgs->peer->io; 426 476 struct evbuffer * out = msgs->outMessages; 427 477 428 478 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) ); 429 479 tr_peerIoWriteUint8 ( io, out, choke ? BT_CHOKE : BT_UNCHOKE ); 430 dbgmsg( msgs, "sending %s... outMessage size is now %d", 431 ( choke ? "Choke" : "Unchoke" ), 432 (int)EVBUFFER_LENGTH( out ) ); 480 481 dbgmsg( msgs, "sending %s...", choke ? "Choke" : "Unchoke" ); 482 dbgOutMessageLen( msgs ); 483 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 484 } 485 486 static void 487 protocolSendHaveAll( tr_peermsgs * msgs ) 488 { 489 tr_peerIo * io = msgs->peer->io; 490 struct evbuffer * out = msgs->outMessages; 491 492 assert( tr_peerIoSupportsFEXT( msgs->peer->io ) ); 493 494 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) ); 495 tr_peerIoWriteUint8 ( io, out, BT_FEXT_HAVE_ALL ); 496 497 dbgmsg( msgs, "sending HAVE_ALL..." ); 498 dbgOutMessageLen( msgs ); 499 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 500 } 501 502 static void 503 protocolSendHaveNone( tr_peermsgs * msgs ) 504 { 505 tr_peerIo * io = msgs->peer->io; 506 struct evbuffer * out = msgs->outMessages; 507 508 assert( tr_peerIoSupportsFEXT( msgs->peer->io ) ); 509 510 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) ); 511 tr_peerIoWriteUint8 ( io, out, BT_FEXT_HAVE_NONE ); 512 513 dbgmsg( msgs, "sending HAVE_NONE..." ); 514 dbgOutMessageLen( msgs ); 433 515 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 434 516 } … … 438 520 **/ 439 521 440 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0 }; 441 442 static void 443 publish( tr_peermsgs * msgs, 444 tr_peer_event * e ) 445 { 446 tr_publisherPublish( msgs->publisher, msgs->info, e ); 447 } 448 449 static void 450 fireError( tr_peermsgs * msgs, 451 int err ) 522 static const tr_peer_event blankEvent = { 0, 0, 0, 0, 0.0f, 0, 0, 0 }; 523 524 static void 525 publish( tr_peermsgs * msgs, tr_peer_event * e ) 526 { 527 assert( msgs->peer ); 528 assert( msgs->peer->msgs == msgs ); 529 530 tr_publisherPublish( msgs->publisher, msgs->peer, e ); 531 } 532 533 static void 534 fireError( tr_peermsgs * msgs, int err ) 452 535 { 453 536 tr_peer_event e = blankEvent; 454 455 537 e.eventType = TR_PEER_ERROR; 456 538 e.err = err; … … 459 541 460 542 static void 543 fireUploadOnly( tr_peermsgs * msgs, tr_bool uploadOnly ) 544 { 545 tr_peer_event e = blankEvent; 546 e.eventType = TR_PEER_UPLOAD_ONLY; 547 e.uploadOnly = uploadOnly; 548 publish( msgs, &e ); 549 } 550 551 static void 461 552 fireNeedReq( tr_peermsgs * msgs ) 462 553 { 463 554 tr_peer_event e = blankEvent; 464 465 555 e.eventType = TR_PEER_NEED_REQ; 466 556 publish( msgs, &e ); … … 471 561 { 472 562 tr_peer_event e = blankEvent; 473 474 563 e.eventType = TR_PEER_PEER_PROGRESS; 475 e.progress = msgs-> info->progress;564 e.progress = msgs->peer->progress; 476 565 publish( msgs, &e ); 477 566 } 478 567 479 568 static void 480 fireGotBlock( tr_peermsgs * msgs, 481 const struct peer_request * req ) 569 fireGotBlock( tr_peermsgs * msgs, const struct peer_request * req ) 482 570 { 483 571 tr_peer_event e = blankEvent; 484 485 572 e.eventType = TR_PEER_CLIENT_GOT_BLOCK; 486 573 e.pieceIndex = req->index; … … 500 587 e.eventType = TR_PEER_CLIENT_GOT_DATA; 501 588 e.wasPieceData = wasPieceData; 589 publish( msgs, &e ); 590 } 591 592 static void 593 fireClientGotSuggest( tr_peermsgs * msgs, uint32_t pieceIndex ) 594 { 595 tr_peer_event e = blankEvent; 596 e.eventType = TR_PEER_CLIENT_GOT_SUGGEST; 597 e.pieceIndex = pieceIndex; 598 publish( msgs, &e ); 599 } 600 601 static void 602 fireClientGotAllowedFast( tr_peermsgs * msgs, uint32_t pieceIndex ) 603 { 604 tr_peer_event e = blankEvent; 605 e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST; 606 e.pieceIndex = pieceIndex; 502 607 publish( msgs, &e ); 503 608 } … … 529 634 530 635 /** 636 *** ALLOWED FAST SET 637 *** For explanation, see http://www.bittorrent.org/beps/bep_0006.html 638 **/ 639 640 size_t 641 tr_generateAllowedSet( tr_piece_index_t * setmePieces, 642 size_t desiredSetSize, 643 size_t pieceCount, 644 const uint8_t * infohash, 645 const tr_address * addr ) 646 { 647 size_t setSize = 0; 648 649 assert( setmePieces ); 650 assert( desiredSetSize <= pieceCount ); 651 assert( desiredSetSize ); 652 assert( pieceCount ); 653 assert( infohash ); 654 assert( addr ); 655 656 if( 1 ) 657 { 658 uint8_t w[SHA_DIGEST_LENGTH + 4]; 659 uint8_t x[SHA_DIGEST_LENGTH]; 660 661 *(uint32_t*)w = ntohl( htonl( addr->s_addr ) & 0xffffff00 ); /* (1) */ 662 memcpy( w + 4, infohash, SHA_DIGEST_LENGTH ); /* (2) */ 663 tr_sha1( x, w, sizeof( w ), NULL ); /* (3) */ 664 665 while( setSize<desiredSetSize ) 666 { 667 int i; 668 for( i=0; i<5 && setSize<desiredSetSize; ++i ) /* (4) */ 669 { 670 size_t k; 671 uint32_t j = i * 4; /* (5) */ 672 uint32_t y = ntohl( *( uint32_t* )( x + j ) ); /* (6) */ 673 uint32_t index = y % pieceCount; /* (7) */ 674 675 for( k=0; k<setSize; ++k ) /* (8) */ 676 if( setmePieces[k] == index ) 677 break; 678 679 if( k == setSize ) 680 setmePieces[setSize++] = index; /* (9) */ 681 } 682 683 tr_sha1( x, x, sizeof( x ), NULL ); /* (3) */ 684 } 685 } 686 687 return setSize; 688 } 689 690 static void 691 updateFastSet( tr_peermsgs * msgs UNUSED ) 692 { 693 #if 0 694 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 695 const int peerIsNeedy = msgs->peer->progress < 0.10; 696 697 if( fext && peerIsNeedy && !msgs->haveFastSet ) 698 { 699 size_t i; 700 const struct tr_address * addr = tr_peerIoGetAddress( msgs->peer->io, NULL ); 701 const tr_info * inf = &msgs->torrent->info; 702 const size_t numwant = MIN( MAX_FAST_SET_SIZE, inf->pieceCount ); 703 704 /* build the fast set */ 705 msgs->fastsetSize = tr_generateAllowedSet( msgs->fastset, numwant, inf->pieceCount, inf->hash, addr ); 706 msgs->haveFastSet = 1; 707 708 /* send it to the peer */ 709 for( i=0; i<msgs->fastsetSize; ++i ) 710 protocolSendAllowedFast( msgs, msgs->fastset[i] ); 711 } 712 #endif 713 } 714 715 /** 531 716 *** INTEREST 532 717 **/ 533 718 534 719 static int 535 isPieceInteresting( const tr_peermsgs * peer,720 isPieceInteresting( const tr_peermsgs * msgs, 536 721 tr_piece_index_t piece ) 537 722 { 538 const tr_torrent * torrent = peer->torrent;723 const tr_torrent * torrent = msgs->torrent; 539 724 540 725 return ( !torrent->info.pieces[piece].dnd ) /* we want it */ 541 && ( !tr_cpPieceIsComplete( torrent->completion, piece ) ) /* !have 542 */ 543 && ( tr_bitfieldHas( peer->info->have, piece ) ); /* peer has it */ 726 && ( !tr_cpPieceIsComplete( torrent->completion, piece ) ) /* !have */ 727 && ( tr_bitfieldHas( msgs->peer->have, piece ) ); /* peer has it */ 544 728 } 545 729 … … 562 746 bitfield = tr_cpPieceBitfield( torrent->completion ); 563 747 564 if( !msgs-> info->have )748 if( !msgs->peer->have ) 565 749 return TRUE; 566 750 567 assert( bitfield->byteCount == msgs-> info->have->byteCount );751 assert( bitfield->byteCount == msgs->peer->have->byteCount ); 568 752 569 753 for( i = 0; i < torrent->info.pieceCount; ++i ) … … 583 767 assert( weAreInterested == 0 || weAreInterested == 1 ); 584 768 585 msgs->info->clientIsInterested = weAreInterested; 586 dbgmsg( msgs, "Sending %s", 587 weAreInterested ? "Interested" : "Not Interested" ); 588 tr_peerIoWriteUint32( msgs->io, out, sizeof( uint8_t ) ); 589 tr_peerIoWriteUint8 ( 590 msgs->io, out, weAreInterested ? BT_INTERESTED : BT_NOT_INTERESTED ); 769 msgs->peer->clientIsInterested = weAreInterested; 770 dbgmsg( msgs, "Sending %s", weAreInterested ? "Interested" : "Not Interested" ); 771 tr_peerIoWriteUint32( msgs->peer->io, out, sizeof( uint8_t ) ); 772 tr_peerIoWriteUint8 ( msgs->peer->io, out, weAreInterested ? BT_INTERESTED : BT_NOT_INTERESTED ); 773 591 774 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 592 dbg msg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH( out ));775 dbgOutMessageLen( msgs ); 593 776 } 594 777 … … 598 781 const int i = isPeerInteresting( msgs ); 599 782 600 if( i != msgs-> info->clientIsInterested )783 if( i != msgs->peer->clientIsInterested ) 601 784 sendInterest( msgs, i ); 602 785 if( i ) … … 604 787 } 605 788 606 static void 607 cancelAllRequestsToClientExceptFast( tr_peermsgs * msgs ) 608 { 609 reqListClear( &msgs->peerAskedFor ); 789 static int 790 popNextRequest( tr_peermsgs * msgs, 791 struct peer_request * setme ) 792 { 793 return reqListPop( &msgs->peerAskedFor, setme ); 794 } 795 796 static void 797 cancelAllRequestsToClient( tr_peermsgs * msgs ) 798 { 799 struct peer_request req; 800 const int mustSendCancel = tr_peerIoSupportsFEXT( msgs->peer->io ); 801 802 while( popNextRequest( msgs, &req ) ) 803 if( mustSendCancel ) 804 protocolSendReject( msgs, &req ); 610 805 } 611 806 … … 618 813 619 814 assert( msgs ); 620 assert( msgs-> info);815 assert( msgs->peer ); 621 816 assert( choke == 0 || choke == 1 ); 622 817 623 if( msgs->info->chokeChangedAt > fibrillationTime ) 624 { 625 dbgmsg( msgs, "Not changing choke to %d to avoid fibrillation", 626 choke ); 627 } 628 else if( msgs->info->peerIsChoked != choke ) 629 { 630 msgs->info->peerIsChoked = choke; 818 if( msgs->peer->chokeChangedAt > fibrillationTime ) 819 { 820 dbgmsg( msgs, "Not changing choke to %d to avoid fibrillation", choke ); 821 } 822 else if( msgs->peer->peerIsChoked != choke ) 823 { 824 msgs->peer->peerIsChoked = choke; 631 825 if( choke ) 632 cancelAllRequestsToClient ExceptFast( msgs );826 cancelAllRequestsToClient( msgs ); 633 827 protocolSendChoke( msgs, choke ); 634 msgs-> info->chokeChangedAt = now;828 msgs->peer->chokeChangedAt = now; 635 829 } 636 830 } … … 648 842 /* since we have more pieces now, we might not be interested in this peer */ 649 843 updateInterest( msgs ); 650 }651 652 #if 0653 static void654 sendFastSuggest( tr_peermsgs * msgs,655 uint32_t pieceIndex )656 {657 assert( msgs );658 659 if( tr_peerIoSupportsFEXT( msgs->io ) )660 {661 tr_peerIoWriteUint32( msgs->io, msgs->outMessages,662 sizeof( uint8_t ) + sizeof( uint32_t ) );663 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST );664 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );665 }666 }667 668 static void669 sendFastHave( tr_peermsgs * msgs,670 int all )671 {672 assert( msgs );673 674 if( tr_peerIoSupportsFEXT( msgs->io ) )675 {676 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof( uint8_t ) );677 tr_peerIoWriteUint8( msgs->io, msgs->outMessages,678 ( all ? BT_HAVE_ALL679 : BT_HAVE_NONE ) );680 updateInterest( msgs );681 }682 }683 684 #endif685 686 static void687 sendFastReject( tr_peermsgs * msgs,688 uint32_t pieceIndex,689 uint32_t offset,690 uint32_t length )691 {692 assert( msgs );693 694 if( tr_peerIoSupportsFEXT( msgs->io ) )695 {696 struct evbuffer * out = msgs->outMessages;697 const uint32_t len = sizeof( uint8_t ) + 3 * sizeof( uint32_t );698 dbgmsg( msgs, "sending fast reject %u:%u->%u", pieceIndex, offset,699 length );700 tr_peerIoWriteUint32( msgs->io, out, len );701 tr_peerIoWriteUint8( msgs->io, out, BT_REJECT );702 tr_peerIoWriteUint32( msgs->io, out, pieceIndex );703 tr_peerIoWriteUint32( msgs->io, out, offset );704 tr_peerIoWriteUint32( msgs->io, out, length );705 pokeBatchPeriod( msgs, LOW_PRIORITY_INTERVAL_SECS );706 dbgmsg( msgs, "outMessage size is now %d",707 (int)EVBUFFER_LENGTH( out ) );708 }709 }710 711 static tr_bitfield*712 getPeerAllowedPieces( tr_peermsgs * msgs )713 {714 if( !msgs->peerAllowedPieces && tr_peerIoSupportsFEXT( msgs->io ) )715 {716 msgs->peerAllowedPieces = tr_peerMgrGenerateAllowedSet(717 MAX_FAST_ALLOWED_COUNT,718 msgs->torrent->info.pieceCount,719 msgs->torrent->info.hash,720 tr_peerIoGetAddress( msgs->io, NULL ) );721 }722 723 return msgs->peerAllowedPieces;724 }725 726 static void727 sendFastAllowed( tr_peermsgs * msgs,728 uint32_t pieceIndex )729 {730 assert( msgs );731 732 if( tr_peerIoSupportsFEXT( msgs->io ) )733 {734 struct evbuffer * out = msgs->outMessages;735 dbgmsg( msgs, "sending fast allowed" );736 tr_peerIoWriteUint32( msgs->io, out, sizeof( uint8_t ) +737 sizeof( uint32_t ) );738 tr_peerIoWriteUint8( msgs->io, out, BT_ALLOWED_FAST );739 tr_peerIoWriteUint32( msgs->io, out, pieceIndex );740 pokeBatchPeriod( msgs, LOW_PRIORITY_INTERVAL_SECS );741 dbgmsg( msgs, "outMessage size is now %d",742 (int)EVBUFFER_LENGTH( out ) );743 }744 }745 746 static void747 sendFastAllowedSet( tr_peermsgs * msgs )748 {749 tr_piece_index_t i = 0;750 751 while( i <= msgs->torrent->info.pieceCount )752 {753 if( tr_bitfieldHas( getPeerAllowedPieces( msgs ), i ) )754 sendFastAllowed( msgs, i );755 i++;756 }757 }758 759 static void760 maybeSendFastAllowedSet( tr_peermsgs * msgs )761 {762 if( tr_bitfieldCountTrueBits( msgs->info->have ) <=763 MAX_FAST_ALLOWED_THRESHOLD )764 sendFastAllowedSet( msgs );765 844 } 766 845 … … 787 866 expireOldRequests( tr_peermsgs * msgs, const time_t now ) 788 867 { 789 int 790 time_t 868 int i; 869 time_t oldestAllowed; 791 870 struct request_list tmp = REQUEST_LIST_INIT; 871 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 872 dbgmsg( msgs, "entering `expire old requests' block" ); 792 873 793 874 /* cancel requests that have been queued for too long */ 794 875 oldestAllowed = now - QUEUED_REQUEST_TTL_SECS; 795 876 reqListCopy( &tmp, &msgs->clientWillAskFor ); 796 for( i = 0; i < tmp.count; ++i ) 797 { 877 for( i=0; i<tmp.count; ++i ) { 798 878 const struct peer_request * req = &tmp.requests[i]; 799 879 if( req->time_requested < oldestAllowed ) … … 802 882 reqListClear( &tmp ); 803 883 804 /* cancel requests that were sent too long ago */ 805 oldestAllowed = now - SENT_REQUEST_TTL_SECS; 806 reqListCopy( &tmp, &msgs->clientAskedFor ); 807 for( i = 0; i < tmp.count; ++i ) 808 { 809 const struct peer_request * req = &tmp.requests[i]; 810 if( req->time_requested < oldestAllowed ) 811 tr_peerMsgsCancel( msgs, req->index, req->offset, req->length ); 812 } 813 reqListClear( &tmp ); 884 /* if the peer doesn't support "Reject Request", 885 * cancel requests that were sent too long ago. */ 886 if( !fext ) { 887 oldestAllowed = now - SENT_REQUEST_TTL_SECS; 888 reqListCopy( &tmp, &msgs->clientAskedFor ); 889 for( i=0; i<tmp.count; ++i ) { 890 const struct peer_request * req = &tmp.requests[i]; 891 if( req->time_requested < oldestAllowed ) 892 tr_peerMsgsCancel( msgs, req->index, req->offset, req->length ); 893 } 894 reqListClear( &tmp ); 895 } 896 897 dbgmsg( msgs, "leaving `expire old requests' block" ); 814 898 } 815 899 … … 818 902 { 819 903 const int max = msgs->maxActiveRequests; 820 const int min = msgs->minActiveRequests;821 904 int sent = 0; 822 905 int count = msgs->clientAskedFor.count; 823 906 struct peer_request req; 824 907 825 if( count > min ) 826 return; 827 if( msgs->info->clientIsChoked ) 908 if( msgs->peer->clientIsChoked ) 828 909 return; 829 910 if( !tr_torrentIsPieceTransferAllowed( msgs->torrent, TR_PEER_TO_CLIENT ) ) … … 832 913 while( ( count < max ) && reqListPop( &msgs->clientWillAskFor, &req ) ) 833 914 { 834 const tr_block_index_t block = 835 _tr_block( msgs->torrent, req.index, req.offset ); 915 const tr_block_index_t block = _tr_block( msgs->torrent, req.index, req.offset ); 836 916 837 917 assert( requestIsValid( msgs, &req ) ); 838 assert( tr_bitfieldHas( msgs-> info->have, req.index ) );918 assert( tr_bitfieldHas( msgs->peer->have, req.index ) ); 839 919 840 920 /* don't ask for it if we've already got it... this block may have … … 852 932 853 933 if( sent ) 854 dbgmsg( msgs, 855 "pump sent %d requests, now have %d active and %d queued", 856 sent, 857 msgs->clientAskedFor.count, 858 msgs->clientWillAskFor.count ); 934 dbgmsg( msgs, "pump sent %d requests, now have %d active and %d queued", 935 sent, msgs->clientAskedFor.count, msgs->clientWillAskFor.count ); 859 936 860 937 if( count < max ) … … 886 963 887 964 /* don't send requests to choked clients */ 888 if( msgs->info->clientIsChoked ) 889 { 965 if( msgs->peer->clientIsChoked ) { 890 966 dbgmsg( msgs, "declining request because they're choking us" ); 891 967 return TR_ADDREQ_CLIENT_CHOKED; … … 893 969 894 970 /* peer doesn't have this piece */ 895 if( !tr_bitfieldHas( msgs-> info->have, index ) )971 if( !tr_bitfieldHas( msgs->peer->have, index ) ) 896 972 return TR_ADDREQ_MISSING; 897 973 … … 929 1005 cancelAllRequestsToPeer( tr_peermsgs * msgs, tr_bool sendCancel ) 930 1006 { 931 int 1007 int i; 932 1008 struct request_list a = msgs->clientWillAskFor; 933 1009 struct request_list b = msgs->clientAskedFor; … … 969 1045 /* if it's only in the queue and hasn't been sent yet, free it */ 970 1046 if( reqListRemove( &msgs->clientWillAskFor, &req ) ) { 971 dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32 "\n", pieceIndex, offset, length );1047 dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32, pieceIndex, offset, length ); 972 1048 fireCancelledReq( msgs, &req ); 973 1049 } … … 975 1051 /* if it's already been sent, send a cancel message too */ 976 1052 if( reqListRemove( &msgs->clientAskedFor, &req ) ) { 977 dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32 "\n", pieceIndex, offset, length );1053 dbgmsg( msgs, "cancelling %"PRIu32":%"PRIu32"->%"PRIu32, pieceIndex, offset, length ); 978 1054 protocolSendCancel( msgs, &req ); 979 1055 fireCancelledReq( msgs, &req ); 980 1056 } 981 1057 } 1058 982 1059 983 1060 /** … … 988 1065 sendLtepHandshake( tr_peermsgs * msgs ) 989 1066 { 990 tr_benc 991 char * 992 int 993 int 1067 tr_benc val, *m; 1068 char * buf; 1069 int len; 1070 int pex; 994 1071 struct evbuffer * out = msgs->outMessages; 995 1072 … … 1008 1085 pex = 1; 1009 1086 1010 tr_bencInitDict( &val, 4 ); 1011 tr_bencDictAddInt( &val, "e", 1012 msgs->session->encryptionMode != TR_CLEAR_PREFERRED ); 1087 tr_bencInitDict( &val, 5 ); 1088 tr_bencDictAddInt( &val, "e", msgs->session->encryptionMode != TR_CLEAR_PREFERRED ); 1013 1089 tr_bencDictAddInt( &val, "p", tr_sessionGetPeerPort( msgs->session ) ); 1090 tr_bencDictAddInt( &val, "upload_only", tr_torrentIsSeed( msgs->torrent ) ); 1014 1091 tr_bencDictAddStr( &val, "v", TR_NAME " " USERAGENT_PREFIX ); 1015 1092 m = tr_bencDictAddDict( &val, "m", 1 ); … … 1018 1095 buf = tr_bencSave( &val, &len ); 1019 1096 1020 tr_peerIoWriteUint32( msgs-> io, out, 2 * sizeof( uint8_t ) + len );1021 tr_peerIoWriteUint8 ( msgs-> io, out, BT_LTEP );1022 tr_peerIoWriteUint8 ( msgs-> io, out, LTEP_HANDSHAKE );1023 tr_peerIoWriteBytes ( msgs-> io, out, buf, len );1097 tr_peerIoWriteUint32( msgs->peer->io, out, 2 * sizeof( uint8_t ) + len ); 1098 tr_peerIoWriteUint8 ( msgs->peer->io, out, BT_LTEP ); 1099 tr_peerIoWriteUint8 ( msgs->peer->io, out, LTEP_HANDSHAKE ); 1100 tr_peerIoWriteBytes ( msgs->peer->io, out, buf, len ); 1024 1101 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 1025 dbg msg( msgs, "outMessage size is now %d", (int)EVBUFFER_LENGTH( out ));1102 dbgOutMessageLen( msgs ); 1026 1103 1027 1104 /* cleanup */ … … 1039 1116 uint8_t * tmp = tr_new( uint8_t, len ); 1040 1117 1041 tr_peerIoReadBytes( msgs-> io, inbuf, tmp, len );1118 tr_peerIoReadBytes( msgs->peer->io, inbuf, tmp, len ); 1042 1119 msgs->peerSentLtepHandshake = 1; 1043 1120 1044 if( tr_bencLoad( tmp, len, &val, NULL ) || val.type != TYPE_DICT)1121 if( tr_bencLoad( tmp, len, &val, NULL ) || !tr_bencIsDict( &val ) ) 1045 1122 { 1046 1123 dbgmsg( msgs, "GET extended-handshake, couldn't get dictionary" ); … … 1053 1130 /* does the peer prefer encrypted connections? */ 1054 1131 if( tr_bencDictFindInt( &val, "e", &i ) ) 1055 msgs-> info->encryption_preference = i ? ENCRYPTION_PREFERENCE_YES1056 : ENCRYPTION_PREFERENCE_NO;1132 msgs->peer->encryption_preference = i ? ENCRYPTION_PREFERENCE_YES 1133 : ENCRYPTION_PREFERENCE_NO; 1057 1134 1058 1135 /* check supported messages for utorrent pex */ 1059 1136 msgs->peerSupportsPex = 0; 1060 if( tr_bencDictFindDict( &val, "m", &sub ) ) 1061 { 1062 if( tr_bencDictFindInt( sub, "ut_pex", &i ) ) 1063 { 1137 if( tr_bencDictFindDict( &val, "m", &sub ) ) { 1138 if( tr_bencDictFindInt( sub, "ut_pex", &i ) ) { 1064 1139 msgs->ut_pex_id = (uint8_t) i; 1065 1140 msgs->peerSupportsPex = msgs->ut_pex_id == 0 ? 0 : 1; … … 1068 1143 } 1069 1144 1145 /* look for upload_only (BEP 21) */ 1146 if( tr_bencDictFindInt( &val, "upload_only", &i ) ) 1147 fireUploadOnly( msgs, i!=0 ); 1148 1070 1149 /* get peer's listening port */ 1071 if( tr_bencDictFindInt( &val, "p", &i ) ) 1072 { 1073 msgs->info->port = htons( (uint16_t)i ); 1074 dbgmsg( msgs, "msgs->port is now %hu", msgs->info->port ); 1150 if( tr_bencDictFindInt( &val, "p", &i ) ) { 1151 msgs->peer->port = htons( (uint16_t)i ); 1152 dbgmsg( msgs, "msgs->port is now %hu", msgs->peer->port ); 1075 1153 } 1076 1154 … … 1084 1162 1085 1163 static void 1086 parseUtPex( tr_peermsgs * msgs, 1087 int msglen, 1088 struct evbuffer * inbuf ) 1089 { 1090 int loaded = 0; 1091 uint8_t * tmp = tr_new( uint8_t, msglen ); 1092 tr_benc val; 1164 parseUtPex( tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf ) 1165 { 1166 int loaded = 0; 1167 uint8_t * tmp = tr_new( uint8_t, msglen ); 1168 tr_benc val; 1093 1169 const tr_torrent * tor = msgs->torrent; 1094 const uint8_t * 1095 size_t 1096 1097 tr_peerIoReadBytes( msgs-> io, inbuf, tmp, msglen );1170 const uint8_t * added; 1171 size_t added_len; 1172 1173 tr_peerIoReadBytes( msgs->peer->io, inbuf, tmp, msglen ); 1098 1174 1099 1175 if( tr_torrentAllowsPex( tor ) … … 1129 1205 uint8_t ltep_msgid; 1130 1206 1131 tr_peerIoReadUint8( msgs-> io, inbuf, <ep_msgid );1207 tr_peerIoReadUint8( msgs->peer->io, inbuf, <ep_msgid ); 1132 1208 msglen--; 1133 1209 … … 1136 1212 dbgmsg( msgs, "got ltep handshake" ); 1137 1213 parseLtepHandshake( msgs, msglen, inbuf ); 1138 if( tr_peerIoSupportsLTEP( msgs-> io ) )1214 if( tr_peerIoSupportsLTEP( msgs->peer->io ) ) 1139 1215 { 1140 1216 sendLtepHandshake( msgs ); … … 1165 1241 return READ_LATER; 1166 1242 1167 tr_peerIoReadUint32( msgs-> io, inbuf, &len );1243 tr_peerIoReadUint32( msgs->peer->io, inbuf, &len ); 1168 1244 1169 1245 if( len == 0 ) /* peer sent us a keepalive message */ … … 1192 1268 return READ_LATER; 1193 1269 1194 tr_peerIoReadUint8( msgs-> io, inbuf, &id );1270 tr_peerIoReadUint8( msgs->peer->io, inbuf, &id ); 1195 1271 msgs->incoming.id = id; 1196 1272 … … 1211 1287 updatePeerProgress( tr_peermsgs * msgs ) 1212 1288 { 1213 msgs-> info->progress = tr_bitfieldCountTrueBits( msgs->info->have )1214 / (float)msgs->torrent->info.pieceCount;1215 dbgmsg( msgs, "peer progress is %f", msgs->info->progress );1289 msgs->peer->progress = tr_bitfieldCountTrueBits( msgs->peer->have ) / (float)msgs->torrent->info.pieceCount; 1290 dbgmsg( msgs, "peer progress is %f", msgs->peer->progress ); 1291 updateFastSet( msgs ); 1216 1292 updateInterest( msgs ); 1217 1293 firePeerProgress( msgs ); 1218 1294 } 1219 1295 1220 static int1221 clientCanSendFastBlock( const tr_peermsgs * msgs UNUSED )1222 {1223 /* don't send a fast piece if peer has MAX_FAST_ALLOWED_THRESHOLD pieces */1224 if( tr_bitfieldCountTrueBits( msgs->info->have ) >1225 MAX_FAST_ALLOWED_THRESHOLD )1226 return FALSE;1227 1228 /* ...or if we don't have ourself enough pieces */1229 if( tr_bitfieldCountTrueBits( tr_cpPieceBitfield( msgs->torrent->1230 completion ) ) <1231 MAX_FAST_ALLOWED_THRESHOLD )1232 return FALSE;1233 1234 /* Maybe a bandwidth limit ? */1235 return TRUE;1236 }1237 1238 1296 static void 1239 1297 peerMadeRequest( tr_peermsgs * msgs, 1240 1298 const struct peer_request * req ) 1241 1299 { 1300 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 1242 1301 const int reqIsValid = requestIsValid( msgs, req ); 1243 const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete( 1244 msgs->torrent->completion, req->index ); 1245 const int peerIsChoked = msgs->info->peerIsChoked; 1246 const int peerIsFast = tr_peerIoSupportsFEXT( msgs->io ); 1247 const int pieceIsFast = reqIsValid && tr_bitfieldHas( 1248 getPeerAllowedPieces( msgs ), req->index ); 1249 const int canSendFast = clientCanSendFastBlock( msgs ); 1250 1251 if( !reqIsValid ) /* bad request */ 1252 { 1302 const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete( msgs->torrent->completion, req->index ); 1303 const int peerIsChoked = msgs->peer->peerIsChoked; 1304 1305 int allow = FALSE; 1306 1307 if( !reqIsValid ) 1253 1308 dbgmsg( msgs, "rejecting an invalid request." ); 1254 sendFastReject( msgs, req->index, req->offset, req->length ); 1255 } 1256 else if( !clientHasPiece ) /* we don't have it */ 1257 { 1309 else if( !clientHasPiece ) 1258 1310 dbgmsg( msgs, "rejecting request for a piece we don't have." ); 1259 sendFastReject( msgs, req->index, req->offset, req->length ); 1260 } 1261 else if( peerIsChoked && !peerIsFast ) /* doesn't he know he's choked? */ 1262 { 1263 tr_peerMsgsSetChoke( msgs, 1 ); 1264 sendFastReject( msgs, req->index, req->offset, req->length ); 1265 } 1266 else if( peerIsChoked && peerIsFast && ( !pieceIsFast || !canSendFast ) ) 1267 { 1268 sendFastReject( msgs, req->index, req->offset, req->length ); 1269 } 1270 else /* YAY */ 1271 { 1272 if( peerIsFast && pieceIsFast ) 1273 reqListAppend( &msgs->peerAskedForFast, req ); 1274 else 1275 reqListAppend( &msgs->peerAskedFor, req ); 1276 } 1311 else if( peerIsChoked ) 1312 dbgmsg( msgs, "rejecting request from choked peer" ); 1313 else 1314 allow = TRUE; 1315 1316 if( allow ) 1317 reqListAppend( &msgs->peerAskedFor, req ); 1318 else if( fext ) 1319 protocolSendReject( msgs, req ); 1277 1320 } 1278 1321 1279 1322 static int 1280 messageLengthIsCorrect( const tr_peermsgs * msg, 1281 uint8_t id, 1282 uint32_t len ) 1323 messageLengthIsCorrect( const tr_peermsgs * msg, uint8_t id, uint32_t len ) 1283 1324 { 1284 1325 switch( id ) … … 1288 1329 case BT_INTERESTED: 1289 1330 case BT_NOT_INTERESTED: 1290 case BT_ HAVE_ALL:1291 case BT_ HAVE_NONE:1331 case BT_FEXT_HAVE_ALL: 1332 case BT_FEXT_HAVE_NONE: 1292 1333 return len == 1; 1293 1334 1294 1335 case BT_HAVE: 1295 case BT_ SUGGEST:1296 case BT_ ALLOWED_FAST:1336 case BT_FEXT_SUGGEST: 1337 case BT_FEXT_ALLOWED_FAST: 1297 1338 return len == 5; 1298 1339 … … 1302 1343 case BT_REQUEST: 1303 1344 case BT_CANCEL: 1304 case BT_ REJECT:1345 case BT_FEXT_REJECT: 1305 1346 return len == 13; 1306 1347 … … 1339 1380 return READ_LATER; 1340 1381 1341 tr_peerIoReadUint32( msgs-> io, inbuf, &req->index );1342 tr_peerIoReadUint32( msgs-> io, inbuf, &req->offset );1382 tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->index ); 1383 tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->offset ); 1343 1384 req->length = msgs->incoming.length - 9; 1344 dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, 1345 req->offset, 1346 req->length ); 1385 dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length ); 1347 1386 return READ_NOW; 1348 1387 } 1349 1388 else 1350 1389 { 1351 int 1390 int err; 1352 1391 1353 1392 /* read in another chunk of data */ 1354 const size_t nLeft = req->length - EVBUFFER_LENGTH( 1355 msgs->incoming.block ); 1356 size_t n = MIN( nLeft, inlen ); 1357 uint8_t * buf = tr_new( uint8_t, n ); 1393 const size_t nLeft = req->length - EVBUFFER_LENGTH( msgs->incoming.block ); 1394 size_t n = MIN( nLeft, inlen ); 1395 uint8_t * buf = tr_new( uint8_t, n ); 1358 1396 assert( EVBUFFER_LENGTH( inbuf ) >= n ); 1359 tr_peerIoReadBytes( msgs-> io, inbuf, buf, n );1397 tr_peerIoReadBytes( msgs->peer->io, inbuf, buf, n ); 1360 1398 evbuffer_add( msgs->incoming.block, buf, n ); 1361 1399 fireClientGotData( msgs, n, TRUE ); 1362 1400 *setme_piece_bytes_read += n; 1363 1401 tr_free( buf ); 1364 dbgmsg( msgs, "got % dbytes for block %u:%u->%u ... %d remain",1365 (int)n, req->index, req->offset, req->length,1402 dbgmsg( msgs, "got %zu bytes for block %u:%u->%u ... %d remain", 1403 n, req->index, req->offset, req->length, 1366 1404 (int)( req->length - EVBUFFER_LENGTH( msgs->incoming.block ) ) ); 1367 1405 if( EVBUFFER_LENGTH( msgs->incoming.block ) < req->length ) … … 1369 1407 1370 1408 /* we've got the whole block ... process it */ 1371 err = clientGotBlock( msgs, EVBUFFER_DATA( 1372 msgs->incoming.block ), req ); 1409 err = clientGotBlock( msgs, EVBUFFER_DATA( msgs->incoming.block ), req ); 1373 1410 1374 1411 /* cleanup */ 1375 evbuffer_drain( msgs->incoming.block, 1376 EVBUFFER_LENGTH( msgs->incoming.block ) ); 1412 evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH( msgs->incoming.block ) ); 1377 1413 req->length = 0; 1378 1414 msgs->state = AWAITING_BT_LENGTH; 1379 1415 if( !err ) 1380 1416 return READ_NOW; 1381 else 1382 { 1417 else { 1383 1418 fireError( msgs, err ); 1384 1419 return READ_ERR; … … 1388 1423 1389 1424 static int 1390 readBtMessage( tr_peermsgs * msgs, 1391 struct evbuffer * inbuf, 1392 size_t inlen ) 1425 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) 1393 1426 { 1394 1427 uint32_t ui32; … … 1396 1429 const uint8_t id = msgs->incoming.id; 1397 1430 const size_t startBufLen = EVBUFFER_LENGTH( inbuf ); 1431 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 1398 1432 1399 1433 --msglen; /* id length */ … … 1402 1436 return READ_LATER; 1403 1437 1404 dbgmsg( msgs, "got BT id %d, len %d, buffer size is %d", (int)id, 1405 (int)msglen, 1406 (int)inlen ); 1438 dbgmsg( msgs, "got BT id %d, len %d, buffer size is %zu", (int)id, (int)msglen, inlen ); 1407 1439 1408 1440 if( !messageLengthIsCorrect( msgs, id, msglen + 1 ) ) 1409 1441 { 1410 dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", 1411 (int)id, (int)msglen ); 1442 dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen ); 1412 1443 fireError( msgs, EMSGSIZE ); 1413 1444 return READ_ERR; … … 1418 1449 case BT_CHOKE: 1419 1450 dbgmsg( msgs, "got Choke" ); 1420 msgs->info->clientIsChoked = 1; 1421 cancelAllRequestsToPeer( msgs, FALSE ); 1451 msgs->peer->clientIsChoked = 1; 1452 if( !fext ) 1453 cancelAllRequestsToPeer( msgs, FALSE ); 1422 1454 break; 1423 1455 1424 1456 case BT_UNCHOKE: 1425 1457 dbgmsg( msgs, "got Unchoke" ); 1426 msgs-> info->clientIsChoked = 0;1458 msgs->peer->clientIsChoked = 0; 1427 1459 fireNeedReq( msgs ); 1428 1460 break; … … 1430 1462 case BT_INTERESTED: 1431 1463 dbgmsg( msgs, "got Interested" ); 1432 msgs-> info->peerIsInterested = 1;1464 msgs->peer->peerIsInterested = 1; 1433 1465 break; 1434 1466 1435 1467 case BT_NOT_INTERESTED: 1436 1468 dbgmsg( msgs, "got Not Interested" ); 1437 msgs-> info->peerIsInterested = 0;1469 msgs->peer->peerIsInterested = 0; 1438 1470 break; 1439 1471 1440 1472 case BT_HAVE: 1441 tr_peerIoReadUint32( msgs-> io, inbuf, &ui32 );1473 tr_peerIoReadUint32( msgs->peer->io, inbuf, &ui32 ); 1442 1474 dbgmsg( msgs, "got Have: %u", ui32 ); 1443 if( tr_bitfieldAdd( msgs->info->have, ui32 ) ) 1444 { 1475 if( tr_bitfieldAdd( msgs->peer->have, ui32 ) ) { 1445 1476 fireError( msgs, ERANGE ); 1446 1477 return READ_ERR; … … 1455 1486 dbgmsg( msgs, "got a bitfield" ); 1456 1487 msgs->peerSentBitfield = 1; 1457 tr_peerIoReadBytes( msgs->io, inbuf, msgs->info->have->bits, 1458 msglen ); 1488 tr_peerIoReadBytes( msgs->peer->io, inbuf, msgs->peer->have->bits, msglen ); 1459 1489 updatePeerProgress( msgs ); 1460 maybeSendFastAllowedSet( msgs );1461 1490 fireNeedReq( msgs ); 1462 1491 break; … … 1466 1495 { 1467 1496 struct peer_request r; 1468 tr_peerIoReadUint32( msgs->io, inbuf, &r.index ); 1469 tr_peerIoReadUint32( msgs->io, inbuf, &r.offset ); 1470 tr_peerIoReadUint32( msgs->io, inbuf, &r.length ); 1471 dbgmsg( msgs, "got Request: %u:%u->%u", r.index, r.offset, 1472 r.length ); 1497 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.index ); 1498 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.offset ); 1499 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length ); 1500 dbgmsg( msgs, "got Request: %u:%u->%u", r.index, r.offset, r.length ); 1473 1501 peerMadeRequest( msgs, &r ); 1474 1502 break; … … 1478 1506 { 1479 1507 struct peer_request r; 1480 tr_peerIoReadUint32( msgs->io, inbuf, &r.index ); 1481 tr_peerIoReadUint32( msgs->io, inbuf, &r.offset ); 1482 tr_peerIoReadUint32( msgs->io, inbuf, &r.length ); 1483 dbgmsg( msgs, "got a Cancel %u:%u->%u", r.index, r.offset, 1484 r.length ); 1485 reqListRemove( &msgs->peerAskedForFast, &r ); 1486 reqListRemove( &msgs->peerAskedFor, &r ); 1508 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.index ); 1509 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.offset ); 1510 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length ); 1511 dbgmsg( msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length ); 1512 if( reqListRemove( &msgs->peerAskedFor, &r ) && fext ) 1513 protocolSendReject( msgs, &r ); 1487 1514 break; 1488 1515 } … … 1494 1521 case BT_PORT: 1495 1522 dbgmsg( msgs, "Got a BT_PORT" ); 1496 tr_peerIoReadUint16( msgs-> io, inbuf, &msgs->info->port );1523 tr_peerIoReadUint16( msgs->peer->io, inbuf, &msgs->peer->port ); 1497 1524 break; 1498 1525 1499 case BT_SUGGEST: 1500 { 1501 dbgmsg( msgs, "Got a BT_SUGGEST" ); 1502 tr_peerIoReadUint32( msgs->io, inbuf, &ui32 ); 1503 /* we don't do anything with this yet */ 1526 case BT_FEXT_SUGGEST: 1527 dbgmsg( msgs, "Got a BT_FEXT_SUGGEST" ); 1528 tr_peerIoReadUint32( msgs->peer->io, inbuf, &ui32 ); 1529 if( fext ) 1530 fireClientGotSuggest( msgs, ui32 ); 1531 else { 1532 fireError( msgs, EMSGSIZE ); 1533 return READ_ERR; 1534 } 1504 1535 break; 1505 } 1506 1507 case BT_HAVE_ALL: 1508 dbgmsg( msgs, "Got a BT_HAVE_ALL" ); 1509 tr_bitfieldAddRange( msgs->info->have, 0, 1510 msgs->torrent->info.pieceCount ); 1511 updatePeerProgress( msgs ); 1512 maybeSendFastAllowedSet( msgs ); 1536 1537 case BT_FEXT_ALLOWED_FAST: 1538 dbgmsg( msgs, "Got a BT_FEXT_ALLOWED_FAST" ); 1539 tr_peerIoReadUint32( msgs->peer->io, inbuf, &ui32 ); 1540 if( fext ) 1541 fireClientGotAllowedFast( msgs, ui32 ); 1542 else { 1543 fireError( msgs, EMSGSIZE ); 1544 return READ_ERR; 1545 } 1513 1546 break; 1514 1547 1515 1516 case BT_HAVE_NONE: 1517 dbgmsg( msgs, "Got a BT_HAVE_NONE" ); 1518 tr_bitfieldClear( msgs->info->have ); 1519 updatePeerProgress( msgs ); 1520 maybeSendFastAllowedSet( msgs ); 1548 case BT_FEXT_HAVE_ALL: 1549 dbgmsg( msgs, "Got a BT_FEXT_HAVE_ALL" ); 1550 if( fext ) { 1551 tr_bitfieldAddRange( msgs->peer->have, 0, msgs->torrent->info.pieceCount ); 1552 updatePeerProgress( msgs ); 1553 } else { 1554 fireError( msgs, EMSGSIZE ); 1555 return READ_ERR; 1556 } 1521 1557 break; 1522 1558 1523 case BT_REJECT: 1559 case BT_FEXT_HAVE_NONE: 1560 dbgmsg( msgs, "Got a BT_FEXT_HAVE_NONE" ); 1561 if( fext ) { 1562 tr_bitfieldClear( msgs->peer->have ); 1563 updatePeerProgress( msgs ); 1564 } else { 1565 fireError( msgs, EMSGSIZE ); 1566 return READ_ERR; 1567 } 1568 break; 1569 1570 case BT_FEXT_REJECT: 1524 1571 { 1525 1572 struct peer_request r; 1526 dbgmsg( msgs, "Got a BT_REJECT" ); 1527 tr_peerIoReadUint32( msgs->io, inbuf, &r.index ); 1528 tr_peerIoReadUint32( msgs->io, inbuf, &r.offset ); 1529 tr_peerIoReadUint32( msgs->io, inbuf, &r.length ); 1530 reqListRemove( &msgs->clientAskedFor, &r ); 1531 break; 1532 } 1533 1534 case BT_ALLOWED_FAST: 1535 { 1536 dbgmsg( msgs, "Got a BT_ALLOWED_FAST" ); 1537 tr_peerIoReadUint32( msgs->io, inbuf, &ui32 ); 1538 /* we don't do anything with this yet */ 1573 dbgmsg( msgs, "Got a BT_FEXT_REJECT" ); 1574 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.index ); 1575 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.offset ); 1576 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length ); 1577 if( fext ) 1578 reqListRemove( &msgs->clientAskedFor, &r ); 1579 else { 1580 fireError( msgs, EMSGSIZE ); 1581 return READ_ERR; 1582 } 1539 1583 break; 1540 1584 } … … 1547 1591 default: 1548 1592 dbgmsg( msgs, "peer sent us an UNKNOWN: %d", (int)id ); 1549 tr_peerIoDrain( msgs-> io, inbuf, msglen );1593 tr_peerIoDrain( msgs->peer->io, inbuf, msglen ); 1550 1594 break; 1551 1595 } … … 1559 1603 1560 1604 static void 1561 decrementDownloadedCount( tr_peermsgs * msgs, 1562 uint32_t byteCount ) 1605 decrementDownloadedCount( tr_peermsgs * msgs, uint32_t byteCount ) 1563 1606 { 1564 1607 tr_torrent * tor = msgs->torrent; … … 1568 1611 1569 1612 static void 1570 clientGotUnwantedBlock( tr_peermsgs * msgs, 1571 const struct peer_request * req ) 1613 clientGotUnwantedBlock( tr_peermsgs * msgs, const struct peer_request * req ) 1572 1614 { 1573 1615 decrementDownloadedCount( msgs, req->length ); … … 1575 1617 1576 1618 static void 1577 addPeerToBlamefield( tr_peermsgs * msgs, 1578 uint32_t index ) 1579 { 1580 if( !msgs->info->blame ) 1581 msgs->info->blame = tr_bitfieldNew( msgs->torrent->info.pieceCount ); 1582 tr_bitfieldAdd( msgs->info->blame, index ); 1619 addPeerToBlamefield( tr_peermsgs * msgs, uint32_t index ) 1620 { 1621 if( !msgs->peer->blame ) 1622 msgs->peer->blame = tr_bitfieldNew( msgs->torrent->info.pieceCount ); 1623 tr_bitfieldAdd( msgs->peer->blame, index ); 1583 1624 } 1584 1625 … … 1589 1630 const struct peer_request * req ) 1590 1631 { 1591 int 1592 tr_torrent * 1632 int err; 1633 tr_torrent * tor = msgs->torrent; 1593 1634 const tr_block_index_t block = _tr_block( tor, req->index, req->offset ); 1594 1635 … … 1596 1637 assert( req ); 1597 1638 1598 if( req->length != tr_torBlockCountBytes( msgs->torrent, block ) ) 1599 { 1639 if( req->length != tr_torBlockCountBytes( msgs->torrent, block ) ) { 1600 1640 dbgmsg( msgs, "wrong block size -- expected %u, got %d", 1601 1641 tr_torBlockCountBytes( msgs->torrent, block ), req->length ); … … 1604 1644 1605 1645 /* save the block */ 1606 dbgmsg( msgs, "got block %u:%u->%u", req->index, req->offset, 1607 req->length ); 1646 dbgmsg( msgs, "got block %u:%u->%u", req->index, req->offset, req->length ); 1608 1647 1609 1648 /** … … 1611 1650 **/ 1612 1651 1613 if( !reqListRemove( &msgs->clientAskedFor, req ) ) 1614 { 1652 if( !reqListRemove( &msgs->clientAskedFor, req ) ) { 1615 1653 clientGotUnwantedBlock( msgs, req ); 1616 1654 dbgmsg( msgs, "we didn't ask for this message..." ); … … 1625 1663 **/ 1626 1664 1627 if( tr_cpBlockIsComplete( tor->completion, block ) ) 1628 { 1665 if( tr_cpBlockIsComplete( tor->completion, block ) ) { 1629 1666 dbgmsg( msgs, "we have this block already..." ); 1630 1667 clientGotUnwantedBlock( msgs, req ); … … 1655 1692 1656 1693 static ReadState 1657 canRead( struct tr_iobuf * iobuf, void * vmsgs, size_t * piece )1694 canRead( tr_peerIo * io, void * vmsgs, size_t * piece ) 1658 1695 { 1659 1696 ReadState ret; 1660 1697 tr_peermsgs * msgs = vmsgs; 1661 struct evbuffer * in = tr_ iobuf_input( iobuf);1698 struct evbuffer * in = tr_peerIoGetReadBuffer( io ); 1662 1699 const size_t inlen = EVBUFFER_LENGTH( in ); 1663 1700 … … 1700 1737 { 1701 1738 tr_peermsgs * msgs = vmsgs; 1702 const double rateToClient = tr_peerGetPieceSpeed( msgs->info, TR_PEER_TO_CLIENT ); 1703 const int estimatedBlocksInNext30Seconds = 1704 ( rateToClient * 30 * 1024 ) / msgs->torrent->blockSize; 1705 msgs->minActiveRequests = 8; 1706 msgs->maxActiveRequests = msgs->minActiveRequests + estimatedBlocksInNext30Seconds; 1739 const double rateToClient = tr_peerGetPieceSpeed( msgs->peer, TR_PEER_TO_CLIENT ); 1740 const int seconds = 10; 1741 const int floor = 8; 1742 const int estimatedBlocksInPeriod = ( rateToClient * seconds * 1024 ) / msgs->torrent->blockSize; 1743 1744 msgs->maxActiveRequests = floor + estimatedBlocksInPeriod; 1745 1707 1746 if( msgs->reqq > 0 ) 1708 1747 msgs->maxActiveRequests = MIN( msgs->maxActiveRequests, msgs->reqq ); 1748 1709 1749 return TRUE; 1710 }1711 1712 static int1713 popNextRequest( tr_peermsgs * msgs,1714 struct peer_request * setme )1715 {1716 return reqListPop( &msgs->peerAskedForFast, setme )1717 || reqListPop( &msgs->peerAskedFor, setme );1718 1750 } 1719 1751 … … 1723 1755 size_t bytesWritten = 0; 1724 1756 struct peer_request req; 1725 const int haveMessages = EVBUFFER_LENGTH( msgs->outMessages ) != 0; 1757 const tr_bool haveMessages = EVBUFFER_LENGTH( msgs->outMessages ) != 0; 1758 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 1726 1759 1727 1760 /** … … 1738 1771 const size_t len = EVBUFFER_LENGTH( msgs->outMessages ); 1739 1772 /* flush the protocol messages */ 1740 dbgmsg( msgs, "flushing outMessages... to %p (length is %zu)", msgs-> io, len );1741 tr_peerIoWriteBuf( msgs-> io, msgs->outMessages, FALSE );1773 dbgmsg( msgs, "flushing outMessages... to %p (length is %zu)", msgs->peer->io, len ); 1774 tr_peerIoWriteBuf( msgs->peer->io, msgs->outMessages, FALSE ); 1742 1775 msgs->clientSentAnythingAt = now; 1743 1776 msgs->outMessagesBatchedAt = 0; … … 1750 1783 **/ 1751 1784 1752 if( ( tr_peerIoGetWriteBufferSpace( msgs->io ) >= msgs->torrent->blockSize ) 1753 && popNextRequest( msgs, &req ) 1754 && requestIsValid( msgs, &req ) 1755 && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) ) 1756 { 1757 /* send a block */ 1758 uint8_t * buf = tr_new( uint8_t, req.length ); 1759 const int err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf ); 1760 if( err ) { 1761 fireError( msgs, err ); 1762 bytesWritten = 0; 1763 msgs = NULL; 1764 } else { 1765 tr_peerIo * io = msgs->io; 1766 struct evbuffer * out = evbuffer_new( ); 1767 dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length ); 1768 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) + req.length ); 1769 tr_peerIoWriteUint8 ( io, out, BT_PIECE ); 1770 tr_peerIoWriteUint32( io, out, req.index ); 1771 tr_peerIoWriteUint32( io, out, req.offset ); 1772 tr_peerIoWriteBytes ( io, out, buf, req.length ); 1773 tr_peerIoWriteBuf( io, out, TRUE ); 1774 bytesWritten += EVBUFFER_LENGTH( out ); 1775 evbuffer_free( out ); 1776 msgs->clientSentAnythingAt = now; 1785 if( ( tr_peerIoGetWriteBufferSpace( msgs->peer->io ) >= msgs->torrent->blockSize ) 1786 && popNextRequest( msgs, &req ) ) 1787 { 1788 if( requestIsValid( msgs, &req ) 1789 && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) ) 1790 { 1791 /* send a block */ 1792 uint8_t * buf = tr_new( uint8_t, req.length ); 1793 const int err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf ); 1794 if( err ) { 1795 fireError( msgs, err ); 1796 bytesWritten = 0; 1797 msgs = NULL; 1798 } else { 1799 tr_peerIo * io = msgs->peer->io; 1800 struct evbuffer * out = evbuffer_new( ); 1801 dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length ); 1802 tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) + req.length ); 1803 tr_peerIoWriteUint8 ( io, out, BT_PIECE ); 1804 tr_peerIoWriteUint32( io, out, req.index ); 1805 tr_peerIoWriteUint32( io, out, req.offset ); 1806 tr_peerIoWriteBytes ( io, out, buf, req.length ); 1807 tr_peerIoWriteBuf( io, out, TRUE ); 1808 bytesWritten += EVBUFFER_LENGTH( out ); 1809 evbuffer_free( out ); 1810 msgs->clientSentAnythingAt = now; 1811 } 1812 tr_free( buf ); 1777 1813 } 1778 tr_free( buf ); 1814 else if( fext ) /* peer needs a reject message */ 1815 { 1816 protocolSendReject( msgs, &req ); 1817 } 1779 1818 } 1780 1819 … … 1788 1827 { 1789 1828 dbgmsg( msgs, "sending a keepalive message" ); 1790 tr_peerIoWriteUint32( msgs-> io, msgs->outMessages, 0 );1829 tr_peerIoWriteUint32( msgs->peer->io, msgs->outMessages, 0 ); 1791 1830 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 1792 1831 } … … 1821 1860 1822 1861 static void 1823 gotError( struct tr_iobuf * iobufUNUSED,1824 short 1825 void 1862 gotError( tr_peerIo * io UNUSED, 1863 short what, 1864 void * vmsgs ) 1826 1865 { 1827 1866 if( what & EVBUFFER_TIMEOUT ) … … 1872 1911 } 1873 1912 1874 tr_peerIoWriteUint32( msgs-> io, out,1913 tr_peerIoWriteUint32( msgs->peer->io, out, 1875 1914 sizeof( uint8_t ) + field->byteCount ); 1876 tr_peerIoWriteUint8 ( msgs-> io, out, BT_BITFIELD );1877 tr_peerIoWriteBytes ( msgs-> io, out, field->bits, field->byteCount );1878 dbgmsg( msgs, "sending bitfield... outMessage size is now % d",1879 (int)EVBUFFER_LENGTH( out ) );1915 tr_peerIoWriteUint8 ( msgs->peer->io, out, BT_BITFIELD ); 1916 tr_peerIoWriteBytes ( msgs->peer->io, out, field->bits, field->byteCount ); 1917 dbgmsg( msgs, "sending bitfield... outMessage size is now %zu", 1918 EVBUFFER_LENGTH( out ) ); 1880 1919 pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS ); 1881 1920 … … 1884 1923 1885 1924 tr_bitfieldFree( field ); 1925 } 1926 1927 static void 1928 tellPeerWhatWeHave( tr_peermsgs * msgs ) 1929 { 1930 const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); 1931 1932 if( fext && ( tr_cpGetStatus( msgs->torrent->completion ) == TR_CP_COMPLETE ) ) 1933 { 1934 protocolSendHaveAll( msgs ); 1935 } 1936 else if( fext && ( tr_cpHaveValid( msgs->torrent->completion ) == 0 ) ) 1937 { 1938 protocolSendHaveNone( msgs ); 1939 } 1940 else 1941 { 1942 sendBitfield( msgs ); 1943 } 1886 1944 } 1887 1945 … … 1995 2053 tmp = walk = tr_new( uint8_t, diffs.addedCount * 6 ); 1996 2054 for( i = 0; i < diffs.addedCount; ++i ) { 1997 memcpy( walk, &diffs.added[i]. in_addr, 4 ); walk += 4;2055 memcpy( walk, &diffs.added[i].addr, 4 ); walk += 4; 1998 2056 memcpy( walk, &diffs.added[i].port, 2 ); walk += 2; 1999 2057 } … … 2013 2071 tmp = walk = tr_new( uint8_t, diffs.droppedCount * 6 ); 2014 2072 for( i = 0; i < diffs.droppedCount; ++i ) { 2015 memcpy( walk, &diffs.dropped[i]. in_addr, 4 ); walk += 4;2073 memcpy( walk, &diffs.dropped[i].addr, 4 ); walk += 4; 2016 2074 memcpy( walk, &diffs.dropped[i].port, 2 ); walk += 2; 2017 2075 } … … 2022 2080 /* write the pex message */ 2023 2081 benc = tr_bencSave( &val, &bencLen ); 2024 tr_peerIoWriteUint32( msgs-> io, out, 2 * sizeof( uint8_t ) + bencLen );2025 tr_peerIoWriteUint8 ( msgs-> io, out, BT_LTEP );2026 tr_peerIoWriteUint8 ( msgs-> io, out, msgs->ut_pex_id );2027 tr_peerIoWriteBytes ( msgs-> io, out, benc, bencLen );2082 tr_peerIoWriteUint32( msgs->peer->io, out, 2 * sizeof( uint8_t ) + bencLen ); 2083 tr_peerIoWriteUint8 ( msgs->peer->io, out, BT_LTEP ); 2084 tr_peerIoWriteUint8 ( msgs->peer->io, out, msgs->ut_pex_id ); 2085 tr_peerIoWriteBytes ( msgs->peer->io, out, benc, bencLen ); 2028 2086 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 2029 2087 dbgmsg( msgs, "sending a pex message; outMessage size is now %zu", EVBUFFER_LENGTH( out ) ); … … 2055 2113 tr_peermsgs* 2056 2114 tr_peerMsgsNew( struct tr_torrent * torrent, 2057 struct tr_peer * info,2115 struct tr_peer * peer, 2058 2116 tr_delivery_func func, 2059 void *userData,2060 tr_publisher_tag *setme )2117 void * userData, 2118 tr_publisher_tag * setme ) 2061 2119 { 2062 2120 tr_peermsgs * m; 2063 2121 2064 assert( info);2065 assert( info->io );2122 assert( peer ); 2123 assert( peer->io ); 2066 2124 2067 2125 m = tr_new0( tr_peermsgs, 1 ); 2068 2126 m->publisher = tr_publisherNew( ); 2069 m-> info = info;2127 m->peer = peer; 2070 2128 m->session = torrent->session; 2071 2129 m->torrent = torrent; 2072 m->io = info->io; 2073 m->info->clientIsChoked = 1; 2074 m->info->peerIsChoked = 1; 2075 m->info->clientIsInterested = 0; 2076 m->info->peerIsInterested = 0; 2077 m->info->have = tr_bitfieldNew( torrent->info.pieceCount ); 2130 m->peer->clientIsChoked = 1; 2131 m->peer->peerIsChoked = 1; 2132 m->peer->clientIsInterested = 0; 2133 m->peer->peerIsInterested = 0; 2134 m->peer->have = tr_bitfieldNew( torrent->info.pieceCount ); 2078 2135 m->state = AWAITING_BT_LENGTH; 2079 2136 m->pexTimer = tr_timerNew( m->session, pexPulse, m, PEX_INTERVAL ); … … 2082 2139 m->outMessagesBatchPeriod = LOW_PRIORITY_INTERVAL_SECS; 2083 2140 m->incoming.block = evbuffer_new( ); 2084 m->peerAllowedPieces = NULL;2085 2141 m->peerAskedFor = REQUEST_LIST_INIT; 2086 m->peerAskedForFast = REQUEST_LIST_INIT;2087 2142 m->clientAskedFor = REQUEST_LIST_INIT; 2088 2143 m->clientWillAskFor = REQUEST_LIST_INIT; 2144 peer->msgs = m; 2145 2089 2146 *setme = tr_publisherSubscribe( m->publisher, func, userData ); 2090 2147 2091 if( tr_peerIoSupportsLTEP( m->io ) )2148 if( tr_peerIoSupportsLTEP( peer->io ) ) 2092 2149 sendLtepHandshake( m ); 2093 2150 2094 sendBitfield( m ); 2095 2096 tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of 2097 inactivity */ 2098 tr_peerIoSetIOFuncs( m->io, canRead, didWrite, gotError, m ); 2151 tellPeerWhatWeHave( m ); 2152 2153 tr_peerIoSetIOFuncs( m->peer->io, canRead, didWrite, gotError, m ); 2099 2154 ratePulse( m ); 2100 2155 … … 2111 2166 reqListClear( &msgs->clientWillAskFor ); 2112 2167 reqListClear( &msgs->clientAskedFor ); 2113 reqListClear( &msgs->peerAskedForFast );2114 2168 reqListClear( &msgs->peerAskedFor ); 2115 tr_bitfieldFree( msgs->peerAllowedPieces ); 2169 2116 2170 evbuffer_free( msgs->incoming.block ); 2117 2171