Changeset 3897
- Timestamp:
- Nov 20, 2007, 2:28:11 AM (15 years ago)
- Location:
- branches/0.9x
- Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/0.9x
- Property svn:externals
-
old new 1 third-party/libevent -r474 http://levent.svn.sourceforge.net/svnroot/levent/trunk/libevent1 third-party/libevent http://levent.svn.sourceforge.net/svnroot/levent/branches/patches-1.4
-
- Property svn:externals
-
branches/0.9x/libtransmission/Makefile.am
r3651 r3897 28 28 ratecontrol.c \ 29 29 shared.c \ 30 strlcat.c \31 strlcpy.c \32 30 torrent.c \ 33 31 tracker.c \ -
branches/0.9x/libtransmission/bencode.c
r3683 r3897 29 29 #include <stdlib.h> 30 30 31 #include <event.h> 32 31 33 #include "transmission.h" 32 34 #include "bencode.h" … … 391 393 } 392 394 393 char * tr_bencSaveMalloc( benc_val_t * val, int * len ) 394 { 395 char * buf = NULL; 396 int alloc = 0; 397 398 *len = 0; 399 if( tr_bencSave( val, &buf, len, &alloc ) ) 400 { 401 if( NULL != buf ) 402 { 403 free(buf); 404 } 405 *len = 0; 406 return NULL; 407 } 408 409 return buf; 410 } 411 412 typedef struct 395 struct KeyIndex 413 396 { 414 397 const char * key; 415 398 int index; 416 } 417 KeyIndex; 399 }; 418 400 419 401 static int compareKeyIndex( const void * va, const void * vb ) 420 402 { 421 const KeyIndex * a = (const KeyIndex *)va;422 const KeyIndex * b = (const KeyIndex *)vb;403 const struct KeyIndex * a = va; 404 const struct KeyIndex * b = vb; 423 405 return strcmp( a->key, b->key ); 424 406 } 425 407 426 int tr_bencSave( benc_val_t * val, char ** buf, int * used, int * max ) 427 { 428 int ii; 408 static void 409 saveImpl( struct evbuffer * out, const benc_val_t * val ) 410 { 411 int ii; 429 412 430 413 switch( val->type ) 431 414 { 432 415 case TYPE_INT: 433 if( tr_sprintf( buf, used, max, "i%"PRId64"e", val->val.i ) ) 434 return 1; 416 evbuffer_add_printf( out, "i%"PRId64"e", val->val.i ); 435 417 break; 436 418 437 419 case TYPE_STR: 438 if( tr_sprintf( buf, used, max, "%i:", val->val.s.i ) || 439 tr_concat( buf, used, max, val->val.s.s, val->val.s.i ) ) 440 return 1; 420 evbuffer_add_printf( out, "%i:", val->val.s.i ); 421 evbuffer_add( out, val->val.s.s, val->val.s.i ); 441 422 break; 442 423 443 424 case TYPE_LIST: 444 if( tr_sprintf( buf, used, max, "l" ) ) 445 return 1; 425 evbuffer_add_printf( out, "l" ); 446 426 for( ii = 0; val->val.l.count > ii; ii++ ) 447 if( tr_bencSave( val->val.l.vals + ii, buf, used, max ) ) 448 return 1; 449 if( tr_sprintf( buf, used, max, "e" ) ) 450 return 1; 427 saveImpl( out, val->val.l.vals + ii ); 428 evbuffer_add_printf( out, "e" ); 451 429 break; 452 430 … … 454 432 /* Keys must be strings and appear in sorted order 455 433 (sorted as raw strings, not alphanumerics). */ 456 if( tr_sprintf( buf, used, max, "d" ) ) 457 return 1; 434 evbuffer_add_printf( out, "d" ); 458 435 if( 1 ) { 459 436 int i; 460 KeyIndex * indices = tr_new(KeyIndex, val->val.l.count );437 struct KeyIndex * indices = tr_new( struct KeyIndex, val->val.l.count ); 461 438 for( ii=i=0; i<val->val.l.count; i+=2 ) { 462 439 indices[ii].key = val->val.l.vals[i].val.s.s; … … 464 441 ii++; 465 442 } 466 qsort( indices, ii, sizeof( KeyIndex), compareKeyIndex );443 qsort( indices, ii, sizeof(struct KeyIndex), compareKeyIndex ); 467 444 for( i=0; i<ii; ++i ) { 468 445 const int index = indices[i].index; 469 if( tr_bencSave( val->val.l.vals + index, buf, used, max ) || 470 tr_bencSave( val->val.l.vals + index + 1, buf, used, max ) ) { 471 tr_free( indices ); 472 return 1; 473 } 446 saveImpl( out, val->val.l.vals + index ); 447 saveImpl( out, val->val.l.vals + index + 1 ); 474 448 } 475 449 tr_free( indices ); 476 } 477 if( tr_sprintf( buf, used, max, "e" ) ) 478 return 1; 479 break; 480 } 481 482 return 0; 450 } 451 evbuffer_add_printf( out, "e" ); 452 break; 453 } 454 } 455 456 char* 457 tr_bencSave( const benc_val_t * val, int * len ) 458 { 459 struct evbuffer * buf = evbuffer_new( ); 460 char * ret; 461 saveImpl( buf, val ); 462 if( len != NULL ) 463 *len = EVBUFFER_LENGTH( buf ); 464 ret = tr_strndup( (char*) EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) ); 465 evbuffer_free( buf ); 466 return ret; 483 467 } 484 468 -
branches/0.9x/libtransmission/bencode.h
r3105 r3897 87 87 benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key ); 88 88 89 char * tr_bencSaveMalloc( benc_val_t * val, int * len ); 90 int tr_bencSave( benc_val_t * val, char ** buf, 91 int * used, int * max ); 89 char* tr_bencSave( const benc_val_t * val, int * len ); 92 90 93 91 int tr_bencIsStr ( const benc_val_t * val ); -
branches/0.9x/libtransmission/completion.c
r3662 r3897 49 49 }; 50 50 51 static void 52 tr_cpReset( tr_completion * cp ) 53 { 54 tr_torrent * tor = cp->tor; 55 56 tr_bitfieldClear( cp->pieceBitfield ); 57 tr_bitfieldClear( cp->blockBitfield ); 58 memset( cp->completeBlocks, 0, sizeof(uint16_t) * tor->info.pieceCount ); 59 60 cp->doneDirty = TRUE; 61 cp->doneHave = 0; 62 cp->doneTotal = 0; 63 cp->completeHave = 0; 64 } 65 51 66 tr_completion * tr_cpInit( tr_torrent * tor ) 52 67 { … … 70 85 tr_bitfieldFree( cp->blockBitfield ); 71 86 tr_free( cp ); 72 }73 74 void tr_cpReset( tr_completion * cp )75 {76 tr_torrent * tor = cp->tor;77 78 tr_bitfieldClear( cp->pieceBitfield );79 tr_bitfieldClear( cp->blockBitfield );80 memset( cp->completeBlocks, 0, sizeof(uint16_t) * tor->info.pieceCount );81 82 cp->doneDirty = TRUE;83 cp->doneHave = 0;84 cp->doneTotal = 0;85 cp->completeHave = 0;86 87 } 87 88 … … 311 312 b -= (info->pieceSize - (info->totalSize % info->pieceSize)); 312 313 313 return b;314 return b; 314 315 } 315 316 … … 317 318 tr_cpHaveTotal( const tr_completion * cp ) 318 319 { 319 return cp->completeHave;320 } 320 return cp->completeHave; 321 } -
branches/0.9x/libtransmission/completion.h
r3178 r3897 32 32 tr_completion * tr_cpInit( tr_torrent * ); 33 33 void tr_cpClose( tr_completion * ); 34 void tr_cpReset( tr_completion * );35 34 36 35 /* General */ -
branches/0.9x/libtransmission/fdlimit.c
r3811 r3897 36 36 #include <fcntl.h> /* O_LARGEFILE */ 37 37 38 #include <sys/queue.h> /* libevent needs this */39 #include <sys/types.h> /* libevent needs this */40 38 #include <event.h> 41 #include <evhttp.h>42 39 #include <evutil.h> 43 40 … … 90 87 enum 91 88 { 92 TR_MAX_SOCKETS = 512,93 94 TR_MAX_OPEN_FILES = 16, /* real files, not sockets */95 96 TR_RESERVED_FDS 89 TR_MAX_SOCKETS = 320, 90 91 TR_MAX_OPEN_FILES = 8, /* real files, not sockets */ 92 93 TR_RESERVED_FDS = 16 /* sockets reserved for tracker connections */ 97 94 }; 98 95 … … 135 132 if( write ) { 136 133 char * tmp = tr_strdup( filename ); 137 const int val = tr_mkdirp( dirname(tmp), 07 00);134 const int val = tr_mkdirp( dirname(tmp), 0777 ); 138 135 tr_free( tmp ); 139 136 if( val ) … … 150 147 #endif 151 148 errno = 0; 152 file->fd = open( filename, flags, 06 00);149 file->fd = open( filename, flags, 0666 ); 153 150 if( file->fd < 0 ) { 154 151 if( errno ) { -
branches/0.9x/libtransmission/handshake.c
r3681 r3897 19 19 #include <libgen.h> /* basename */ 20 20 21 #include <sys/types.h> /* event.h needs this */22 21 #include <event.h> 23 22 … … 91 90 unsigned int havePeerID : 1; 92 91 unsigned int haveSentBitTorrentHandshake : 1; 93 unsigned int allowUnencryptedPeers : 1;94 92 tr_peerIo * io; 95 93 tr_crypto * crypto; … … 98 96 uint8_t mySecret[KEY_LEN]; 99 97 uint8_t state; 98 tr_encryption_mode encryptionMode; 100 99 uint16_t pad_c_len; 101 100 uint16_t pad_d_len; … … 326 325 327 326 static uint32_t 328 getCryptoProvide( const tr_handshake * handshake UNUSED ) 329 { 330 uint32_t i = 0; 331 332 i |= CRYPTO_PROVIDE_CRYPTO; /* always allow crypto */ 333 334 #if 0 335 /* by the time we send a crypto_provide, we _know_ 336 * the peer supports encryption. */ 337 if( handshake->allowUnencryptedPeers ) 338 i |= CRYPTO_PROVIDE_PLAINTEXT; 339 #endif 340 341 return i; 327 getCryptoProvide( const tr_handshake * handshake ) 328 { 329 uint32_t provide = 0; 330 331 switch( handshake->encryptionMode ) 332 { 333 case TR_ENCRYPTION_REQUIRED: 334 case TR_ENCRYPTION_PREFERRED: 335 provide |= CRYPTO_PROVIDE_CRYPTO; 336 break; 337 338 case TR_PLAINTEXT_PREFERRED: 339 provide |= CRYPTO_PROVIDE_CRYPTO | CRYPTO_PROVIDE_PLAINTEXT; 340 break; 341 } 342 343 return provide; 344 } 345 346 static uint32_t 347 getCryptoSelect( const tr_handshake * handshake, uint32_t crypto_provide ) 348 { 349 uint32_t choices[4]; 350 int i, nChoices=0; 351 352 switch( handshake->encryptionMode ) 353 { 354 case TR_ENCRYPTION_REQUIRED: 355 choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; 356 break; 357 358 case TR_ENCRYPTION_PREFERRED: 359 choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; 360 choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT; 361 break; 362 363 case TR_PLAINTEXT_PREFERRED: 364 choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT; 365 choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; 366 break; 367 } 368 369 for( i=0; i<nChoices; ++i ) 370 if( crypto_provide & choices[i] ) 371 return choices[i]; 372 373 return 0; 342 374 } 343 375 … … 546 578 tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_NONE ); 547 579 548 if( !handshake->allowUnencryptedPeers)580 if( handshake->encryptionMode == TR_ENCRYPTION_REQUIRED ) 549 581 { 550 582 dbgmsg( handshake, "peer is unencrypted, and we're disallowing that" ); … … 842 874 } 843 875 844 dbgmsg( handshake, "sending crypto_select" );845 876 /* send crypto_select */ 846 { 847 dbgmsg( handshake, "handshake->crypto_provide is %d", (int)handshake->crypto_provide ); 848 if( handshake->crypto_provide & CRYPTO_PROVIDE_CRYPTO ) 849 crypto_select = CRYPTO_PROVIDE_CRYPTO; 850 else if( handshake->allowUnencryptedPeers ) 851 crypto_select = CRYPTO_PROVIDE_PLAINTEXT; 852 else { 853 dbgmsg( handshake, "gronk..." ); 854 evbuffer_free( outbuf ); 855 tr_handshakeDone( handshake, FALSE ); 856 return READ_DONE; 857 } 858 859 dbgmsg( handshake, "we select crypto_select as %d...", (int)crypto_select ); 877 crypto_select = getCryptoSelect( handshake, handshake->crypto_provide ); 878 if( crypto_select ) { 879 dbgmsg( handshake, "selecting crypto mode '%d'", (int)crypto_select ); 860 880 tr_peerIoWriteUint32( handshake->io, outbuf, crypto_select ); 881 } else { 882 dbgmsg( handshake, "peer didn't offer an encryption mode we like." ); 883 evbuffer_free( outbuf ); 884 tr_handshakeDone( handshake, FALSE ); 885 return READ_DONE; 861 886 } 862 887 … … 944 969 { 945 970 dbgmsg( handshake, "handshakeDone: %s", isOK ? "connected" : "aborting" ); 946 tr_peerIoSetIOFuncs( handshake->io, NULL, NULL, NULL , NULL);971 tr_peerIoSetIOFuncs( handshake->io, NULL, NULL, NULL ); 947 972 948 973 fireDoneFunc( handshake, isOK ); … … 966 991 * try a plaintext handshake */ 967 992 if( ( ( handshake->state == AWAITING_YB ) || ( handshake->state == AWAITING_VC ) ) 968 && ( handshake-> allowUnencryptedPeers)993 && ( handshake->encryptionMode != TR_ENCRYPTION_REQUIRED ) 969 994 && ( !tr_peerIoReconnect( handshake->io ) ) ) 970 995 { … … 992 1017 tr_handshake* 993 1018 tr_handshakeNew( tr_peerIo * io, 994 tr_encryption_mode encryption _mode,1019 tr_encryption_mode encryptionMode, 995 1020 handshakeDoneCB doneCB, 996 1021 void * doneUserData ) … … 1001 1026 handshake->io = io; 1002 1027 handshake->crypto = tr_peerIoGetCrypto( io ); 1003 handshake-> allowUnencryptedPeers = encryption_mode!=TR_ENCRYPTION_REQUIRED;1028 handshake->encryptionMode = encryptionMode; 1004 1029 handshake->doneCB = doneCB; 1005 1030 handshake->doneUserData = doneUserData; 1006 1031 handshake->handle = tr_peerIoGetHandle( io ); 1007 1032 1008 tr_peerIoSetIOMode( handshake->io, EV_READ|EV_WRITE, 0 ); 1009 tr_peerIoSetIOFuncs( handshake->io, canRead, NULL, gotError, handshake ); 1033 tr_peerIoSetIOFuncs( handshake->io, canRead, gotError, handshake ); 1010 1034 1011 1035 if( tr_peerIoIsIncoming( handshake->io ) ) 1012 1036 setReadState( handshake, AWAITING_HANDSHAKE ); 1013 else 1037 else if( encryptionMode != TR_PLAINTEXT_PREFERRED ) 1014 1038 sendYa( handshake ); 1039 else { 1040 int msgSize; 1041 uint8_t * msg = buildHandshakeMessage( handshake, &msgSize ); 1042 handshake->haveSentBitTorrentHandshake = 1; 1043 setReadState( handshake, AWAITING_HANDSHAKE ); 1044 tr_peerIoWrite( handshake->io, msg, msgSize ); 1045 tr_free( msg ); 1046 } 1015 1047 1016 1048 return handshake; -
branches/0.9x/libtransmission/inout.c
r3780 r3897 26 26 #include "inout.h" 27 27 #include "list.h" 28 #include "net.h"29 28 #include "platform.h" 30 29 #include "peer-mgr.h" 31 30 #include "utils.h" 32 33 struct tr_io34 {35 tr_torrent * tor;36 };37 31 38 32 /**** … … 78 72 ret = TR_ERROR_IO_OTHER; 79 73 else if( func( fd, buf, buflen ) != buflen ) 80 ret = tr_ioErrorFromErrno ();74 ret = tr_ioErrorFromErrno( ); 81 75 else 82 76 ret = TR_OK; -
branches/0.9x/libtransmission/ipcparse.c
r3808 r3897 31 31 32 32 #include "transmission.h" 33 #include "utils.h" 33 34 34 35 #include "ipcparse.h" … … 141 142 { "autostart", 2, IPC_MSG_AUTOSTART, RB_ENTRY_INITIALIZER() }, 142 143 { "bad-format", 2, IPC_MSG_BAD, RB_ENTRY_INITIALIZER() }, 144 { "encryption", 2, IPC_MSG_CRYPTO, RB_ENTRY_INITIALIZER() }, 143 145 { "directory", 2, IPC_MSG_DIR, RB_ENTRY_INITIALIZER() }, 144 146 { "downlimit", 2, IPC_MSG_DOWNLIMIT, RB_ENTRY_INITIALIZER() }, … … 146 148 { "get-automap", 2, IPC_MSG_GETAUTOMAP, RB_ENTRY_INITIALIZER() }, 147 149 { "get-autostart", 2, IPC_MSG_GETAUTOSTART, RB_ENTRY_INITIALIZER() }, 150 { "get-encryption", 2, IPC_MSG_GETCRYPTO, RB_ENTRY_INITIALIZER() }, 148 151 { "get-directory", 2, IPC_MSG_GETDIR, RB_ENTRY_INITIALIZER() }, 149 152 { "get-downlimit", 2, IPC_MSG_GETDOWNLIMIT, RB_ENTRY_INITIALIZER() }, … … 362 365 363 366 uint8_t * 364 ipc_mkval( benc_val_t * pk, size_t * len ) 365 { 366 char * buf, hex[IPC_MIN_MSG_LEN+1]; 367 int used, max; 368 369 used = IPC_MIN_MSG_LEN; 370 max = IPC_MIN_MSG_LEN; 371 buf = malloc( IPC_MIN_MSG_LEN ); 372 if( NULL == buf ) 373 { 374 return NULL; 375 } 376 377 if( tr_bencSave( pk, &buf, &used, &max ) ) 378 { 379 SAFEFREE( buf ); 380 return NULL; 381 } 382 383 /* ok, this check is pretty laughable */ 384 if( IPC_MAX_MSG_LEN < used ) 385 { 386 free( buf ); 367 ipc_mkval( benc_val_t * pk, size_t * setmeSize ) 368 { 369 int bencSize = 0; 370 char * benc = tr_bencSave( pk, &bencSize ); 371 uint8_t * ret = NULL; 372 373 if( bencSize > IPC_MAX_MSG_LEN ) 387 374 errno = EFBIG; 388 return NULL;389 }390 391 assert( 0 <= used);392 snprintf( hex, sizeof hex, "%0*X",393 IPC_MIN_MSG_LEN, used - IPC_MIN_MSG_LEN );394 memcpy( buf, hex, IPC_MIN_MSG_LEN );395 *len = used; 396 397 return ( uint8_t * )buf;375 else { 376 const size_t size = IPC_MIN_MSG_LEN + bencSize; 377 ret = tr_new( uint8_t, size ); 378 snprintf( (char*)ret, size, "%0*X", IPC_MIN_MSG_LEN, bencSize ); 379 memcpy( ret + IPC_MIN_MSG_LEN, benc, bencSize ); 380 *setmeSize = size; 381 } 382 383 tr_free( benc ); 384 return ret; 398 385 } 399 386 -
branches/0.9x/libtransmission/ipcparse.h
r3566 r3897 43 43 IPC_MSG_AUTOSTART, 44 44 IPC_MSG_BAD, 45 IPC_MSG_CRYPTO, 45 46 IPC_MSG_DIR, 46 47 IPC_MSG_DOWNLIMIT, … … 48 49 IPC_MSG_GETAUTOMAP, 49 50 IPC_MSG_GETAUTOSTART, 51 IPC_MSG_GETCRYPTO, 50 52 IPC_MSG_GETDIR, 51 53 IPC_MSG_GETDOWNLIMIT, -
branches/0.9x/libtransmission/makemeta.c
r3657 r3897 386 386 if ( !builder->abortFlag ) { 387 387 size_t nmemb; 388 char * pch = tr_bencSave Malloc( &top, &n );388 char * pch = tr_bencSave( &top, &n ); 389 389 FILE * fp = fopen( builder->outputFile, "wb+" ); 390 390 nmemb = n; -
branches/0.9x/libtransmission/peer-io.c
r3555 r3897 18 18 #include <arpa/inet.h> /* inet_ntoa */ 19 19 20 #include <sys/types.h> /* event.h needs this */21 20 #include <event.h> 22 21 … … 31 30 #define IO_TIMEOUT_SECS 8 32 31 32 /* arbitrary */ 33 #define TR_RDBUF (1024*8) 34 33 35 /** 34 36 *** … … 49 51 int socket; 50 52 int encryptionMode; 53 int timeout; 51 54 struct bufferevent * bufev; 52 55 uint8_t peerId[20]; … … 59 62 60 63 tr_can_read_cb canRead; 61 tr_did_write_cb didWrite;62 64 tr_net_error_cb gotError; 63 65 void * userData; … … 71 73 72 74 static void 73 didWriteWrapper( struct bufferevent * e, void * userData )74 {75 tr_peerIo * c = (tr_peerIo *) userData;76 if( c->didWrite != NULL )77 (*c->didWrite)( e, c->userData );78 }79 80 static void81 75 canReadWrapper( struct bufferevent * e, void * userData ) 82 76 { 83 77 int done = 0; 84 tr_peerIo * c = (tr_peerIo *)userData;78 tr_peerIo * c = userData; 85 79 tr_handle * handle = c->handle; 86 80 … … 100 94 continue; 101 95 case READ_MORE: 102 tr_peerIoSetIOMode( c, EV_READ, 0 );103 96 case READ_DONE: 104 97 done = 1; … … 112 105 gotErrorWrapper( struct bufferevent * e, short what, void * userData ) 113 106 { 114 tr_peerIo * c = (tr_peerIo *)userData;107 tr_peerIo * c = userData; 115 108 if( c->gotError != NULL ) 116 109 (*c->gotError)( e, what, c->userData ); … … 120 113 *** 121 114 **/ 115 116 void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t); 122 117 123 118 static tr_peerIo* … … 137 132 c->socket = socket; 138 133 c->isIncoming = isIncoming ? 1 : 0; 134 c->timeout = IO_TIMEOUT_SECS; 139 135 c->bufev = bufferevent_new( c->socket, 140 136 canReadWrapper, 141 didWriteWrapper,137 NULL, 142 138 gotErrorWrapper, 143 139 c ); 144 bufferevent_settimeout( c->bufev, IO_TIMEOUT_SECS, IO_TIMEOUT_SECS);140 bufferevent_settimeout( c->bufev, c->timeout, c->timeout ); 145 141 bufferevent_enable( c->bufev, EV_READ|EV_WRITE ); 142 bufferevent_setwatermark( c->bufev, EV_READ, 0, TR_RDBUF ); 143 146 144 return c; 147 145 } … … 195 193 { 196 194 io->canRead = NULL; 197 io->didWrite = NULL;198 195 io->gotError = NULL; 199 196 tr_runInEventThread( io->handle, io_dtor, io ); … … 235 232 } 236 233 234 void 235 tr_peerIoTryRead( tr_peerIo * io ) 236 { 237 if( EVBUFFER_LENGTH( io->bufev->input ) ) 238 canReadWrapper( io->bufev, io ); 239 } 240 237 241 void 238 242 tr_peerIoSetIOFuncs( tr_peerIo * io, 239 243 tr_can_read_cb readcb, 240 tr_did_write_cb writecb,241 244 tr_net_error_cb errcb, 242 245 void * userData ) 243 246 { 244 247 io->canRead = readcb; 245 io->didWrite = writecb;246 248 io->gotError = errcb; 247 249 io->userData = userData; 248 250 249 if( EVBUFFER_LENGTH( io->bufev->input ) ) 250 canReadWrapper( io->bufev, io ); 251 } 252 253 void 254 tr_peerIoSetIOMode( tr_peerIo * c, short enable, short disable ) 255 { 256 tr_setBufferEventMode( c->handle, c->bufev, enable, disable ); 251 tr_peerIoTryRead( io ); 257 252 } 258 253 … … 278 273 279 274 io->bufev = bufferevent_new( io->socket, 280 canReadWrapper, 281 didWriteWrapper, 282 gotErrorWrapper, 275 canReadWrapper, NULL, gotErrorWrapper, 283 276 io ); 284 bufferevent_settimeout( io->bufev, IO_TIMEOUT_SECS, IO_TIMEOUT_SECS);277 bufferevent_settimeout( io->bufev, io->timeout, io->timeout ); 285 278 bufferevent_enable( io->bufev, EV_READ|EV_WRITE ); 279 bufferevent_setwatermark( io->bufev, EV_READ, 0, TR_RDBUF ); 286 280 287 281 return 0; … … 294 288 tr_peerIoSetTimeoutSecs( tr_peerIo * io, int secs ) 295 289 { 296 bufferevent_settimeout( io->bufev, secs, secs ); 290 io->timeout = secs; 291 bufferevent_settimeout( io->bufev, io->timeout, io->timeout ); 297 292 } 298 293 … … 405 400 int writeme_len ) 406 401 { 407 tr_bufferevent_write( io->handle, io->bufev, writeme, writeme_len ); 402 assert( tr_amInEventThread( io->handle ) ); 403 bufferevent_write( io->bufev, writeme, writeme_len ); 408 404 } 409 405 … … 412 408 struct evbuffer * buf ) 413 409 { 414 tr_peerIoWrite( io, EVBUFFER_DATA(buf), EVBUFFER_LENGTH(buf) ); 415 evbuffer_drain( buf, ~0 ); 410 const size_t n = EVBUFFER_LENGTH( buf ); 411 tr_peerIoWrite( io, EVBUFFER_DATA(buf), n ); 412 evbuffer_drain( buf, n ); 416 413 } 417 414 … … 442 439 } 443 440 441 /** 442 *** 443 **/ 444 444 445 void 445 446 tr_peerIoWriteBytes( tr_peerIo * io, 446 447 struct evbuffer * outbuf, 447 448 const void * bytes, 448 intbyteCount )449 size_t byteCount ) 449 450 { 450 451 uint8_t * tmp; … … 469 470 470 471 void 472 tr_peerIoWriteUint8( tr_peerIo * io, 473 struct evbuffer * outbuf, 474 uint8_t writeme ) 475 { 476 tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof(uint8_t) ); 477 } 478 479 void 471 480 tr_peerIoWriteUint16( tr_peerIo * io, 472 481 struct evbuffer * outbuf, … … 478 487 479 488 void 480 tr_peerIoWriteUint8( tr_peerIo * io,481 struct evbuffer * outbuf,482 uint8_t writeme )483 {484 tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof(uint8_t) );485 }486 487 void488 489 tr_peerIoWriteUint32( tr_peerIo * io, 489 490 struct evbuffer * outbuf, … … 494 495 } 495 496 497 /*** 498 **** 499 ***/ 500 496 501 void 497 502 tr_peerIoReadBytes( tr_peerIo * io, 498 503 struct evbuffer * inbuf, 499 504 void * bytes, 500 intbyteCount )501 { 502 assert( (int)EVBUFFER_LENGTH( inbuf ) >= byteCount );505 size_t byteCount ) 506 { 507 assert( EVBUFFER_LENGTH( inbuf ) >= byteCount ); 503 508 504 509 switch( io->encryptionMode ) 505 510 { 506 511 case PEER_ENCRYPTION_NONE: 507 evbuffer_remove( 512 evbuffer_remove( inbuf, bytes, byteCount ); 508 513 break; 509 514 510 515 case PEER_ENCRYPTION_RC4: 511 evbuffer_remove( 516 evbuffer_remove( inbuf, bytes, byteCount ); 512 517 tr_cryptoDecrypt( io->crypto, byteCount, bytes, bytes ); 513 518 break; … … 519 524 520 525 void 526 tr_peerIoReadUint8( tr_peerIo * io, 527 struct evbuffer * inbuf, 528 uint8_t * setme ) 529 { 530 tr_peerIoReadBytes( io, inbuf, setme, sizeof(uint8_t) ); 531 } 532 533 void 521 534 tr_peerIoReadUint16( tr_peerIo * io, 522 535 struct evbuffer * inbuf, … … 529 542 530 543 void 531 tr_peerIoReadUint8( tr_peerIo * io,532 struct evbuffer * inbuf,533 uint8_t * setme )534 {535 tr_peerIoReadBytes( io, inbuf, setme, sizeof(uint8_t) );536 }537 538 void539 544 tr_peerIoReadUint32( tr_peerIo * io, 540 545 struct evbuffer * inbuf, … … 549 554 tr_peerIoDrain( tr_peerIo * io, 550 555 struct evbuffer * inbuf, 551 intbyteCount )556 size_t byteCount ) 552 557 { 553 558 uint8_t * tmp = tr_new( uint8_t, byteCount ); -
branches/0.9x/libtransmission/peer-io.h
r3501 r3897 100 100 typedef enum { READ_MORE, READ_AGAIN, READ_DONE } ReadState; 101 101 typedef ReadState (*tr_can_read_cb)(struct bufferevent*, void* user_data); 102 typedef void (*tr_did_write_cb)(struct bufferevent *, void *);103 102 typedef void (*tr_net_error_cb)(struct bufferevent *, short what, void *); 104 103 105 104 void tr_peerIoSetIOFuncs( tr_peerIo * io, 106 105 tr_can_read_cb readcb, 107 tr_did_write_cb writecb,108 106 tr_net_error_cb errcb, 109 107 void * user_data ); 110 108 111 void tr_peerIoSetIOMode ( tr_peerIo * io, 112 short enable_mode, 113 short disable_mode ); 109 size_t tr_peerIoWriteBytesWaiting( const tr_peerIo * io ); 114 110 115 size_t tr_peerIoWriteBytesWaiting( consttr_peerIo * io );111 void tr_peerIoTryRead( tr_peerIo * io ); 116 112 117 113 void tr_peerIoWrite( tr_peerIo * io, … … 145 141 struct evbuffer * outbuf, 146 142 const void * bytes, 147 intbyteCount );143 size_t byteCount ); 148 144 149 145 void tr_peerIoWriteUint8 ( tr_peerIo * io, … … 162 158 struct evbuffer * inbuf, 163 159 void * bytes, 164 intbyteCount );160 size_t byteCount ); 165 161 166 162 void tr_peerIoReadUint8 ( tr_peerIo * io, … … 178 174 void tr_peerIoDrain ( tr_peerIo * io, 179 175 struct evbuffer * inbuf, 180 intbyteCount );176 size_t byteCount ); 181 177 182 178 -
branches/0.9x/libtransmission/peer-mgr-private.h
r3553 r3897 29 29 }; 30 30 31 /** 32 *** The "SWIFT" system is described by Karthik Tamilmani, 33 *** Vinay Pai, and Alexander Mohr of Stony Brook University 34 *** in their paper "SWIFT: A System With Incentives For Trading" 35 *** http://citeseer.ist.psu.edu/tamilmani04swift.html 36 *** 37 *** More SWIFT constants are defined in peer-mgr.c 38 **/ 39 40 /** 41 * Use SWIFT? 42 */ 43 static const int SWIFT_ENABLED = 1; 44 45 /** 46 * For every byte the peer uploads to us, 47 * allow them to download this many bytes from us 48 */ 49 static const double SWIFT_REPAYMENT_RATIO = 1.33; 50 51 31 52 typedef struct tr_peer 32 53 { … … 37 58 unsigned int doPurge : 1; 38 59 60 tr_peer_status status; 39 61 40 62 /* number of bad pieces they've contributed to */ … … 66 88 double rateToClient; 67 89 double rateToPeer; 90 91 int64_t credit; 68 92 } 69 93 tr_peer; -
branches/0.9x/libtransmission/peer-mgr.c
r3807 r3897 20 20 #include <arpa/inet.h> /* inet_ntoa */ 21 21 22 #include <sys/queue.h> /* libevent needs this */23 #include <sys/types.h> /* libevent needs this */24 22 #include <event.h> 25 23 … … 38 36 #include "ratecontrol.h" 39 37 #include "shared.h" 38 #include "trcompat.h" /* strlcpy */ 40 39 #include "trevent.h" 41 40 #include "utils.h" 42 41 42 /** 43 *** The "SWIFT" system is described by Karthik Tamilmani, 44 *** Vinay Pai, and Alexander Mohr of Stony Brook University 45 *** in their paper "SWIFT: A System With Incentives For Trading" 46 *** http://citeseer.ist.psu.edu/tamilmani04swift.html 47 *** 48 *** More SWIFT constants are defined in peer-mgr-private.h 49 **/ 50 51 /** 52 * Allow new peers to download this many bytes from 53 * us when getting started. This can prevent gridlock 54 * with other peers using tit-for-tat algorithms 55 */ 56 static const int SWIFT_INITIAL_CREDIT = 64 * 1024; /* 64 KiB */ 57 58 /** 59 * We expend a fraction of our torrent's total upload speed 60 * on largesse by uniformly distributing free credit to 61 * all of our peers. This too helps prevent gridlock. 62 */ 63 static const double SWIFT_LARGESSE = 0.10; /* 10% of our UL */ 64 65 /** 66 * How frequently to extend largesse-based credit 67 */ 68 static const int SWIFT_PERIOD_MSEC = 5000; 69 70 43 71 enum 44 72 { … … 47 75 48 76 /* how frequently to decide which peers live and die */ 49 RECONNECT_PERIOD_MSEC = ( 5* 1000),77 RECONNECT_PERIOD_MSEC = (6 * 1000), 50 78 51 79 /* how frequently to refill peers' request lists */ … … 60 88 61 89 /* arbitrary */ 62 MAX_CONNECTED_PEERS_PER_TORRENT = 60,90 MAX_CONNECTED_PEERS_PER_TORRENT = 50, 63 91 64 92 /* when many peers are available, keep idle ones this long */ 65 MIN_UPLOAD_IDLE_SECS = 60,93 MIN_UPLOAD_IDLE_SECS = (60 * 3), 66 94 67 95 /* when few peers are available, keep idle ones this long */ 68 MAX_UPLOAD_IDLE_SECS = 240,96 MAX_UPLOAD_IDLE_SECS = (60 * 10), 69 97 70 98 /* how many peers to unchoke per-torrent. */ 71 99 /* FIXME: make this user-configurable? */ 72 NUM_UNCHOKED_PEERS_PER_TORRENT = 1 2, /* arbitrary */100 NUM_UNCHOKED_PEERS_PER_TORRENT = 10, /* arbitrary */ 73 101 74 102 /* set this too high and there will be a lot of churn. … … 116 144 tr_timer * rechokeTimer; 117 145 tr_timer * refillTimer; 146 tr_timer * swiftTimer; 118 147 tr_torrent * tor; 119 148 tr_bitfield * requested; … … 316 345 tr_peer * p; 317 346 p = tr_new0( tr_peer, 1 ); 347 p->credit = SWIFT_INITIAL_CREDIT; 318 348 p->rcToClient = tr_rcInit( ); 319 349 p->rcToPeer = tr_rcInit( ); … … 399 429 tr_timerFree( &t->rechokeTimer ); 400 430 tr_timerFree( &t->refillTimer ); 431 tr_timerFree( &t->swiftTimer ); 401 432 402 433 tr_bitfieldFree( t->requested ); … … 448 479 tr_bitfield_t * ret; 449 480 481 #if 0 450 482 printf( "%d piece allowed fast set for torrent with %d pieces and hex infohash\n", setCount, pieceCount ); 451 483 printf( "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x for node with IP %s:\n", … … 453 485 infohash[10], infohash[11], infohash[12], infohash[13], infohash[14], infohash[15], infohash[16], infohash[7], infohash[18], infohash[19], 454 486 inet_ntoa( *ip ) ); 487 #endif 455 488 456 489 seed = malloc(4 + SHA_DIGEST_LENGTH); … … 551 584 uint32_t peerCount; 552 585 uint32_t fastAllowed; 586 uint32_t suggested; 553 587 }; 554 588 … … 560 594 561 595 /* if one *might be* fastallowed to us, get it first... 562 * I'm putting it on top so we prioriti se those pieces at596 * I'm putting it on top so we prioritize those pieces at 563 597 * startup, then we'll have them, and we'll be denied access 564 598 * to them */ … … 569 603 if (a->priority != b->priority) 570 604 return a->priority > b->priority ? -1 : 1; 605 606 /* otherwise if one was suggested to us, get it */ 607 if (a->suggested != b->suggested) 608 return a->suggested < b->suggested ? -1 : 1; 571 609 572 610 /* try to fill partial pieces */ … … 641 679 but we're guaranteed to get the same pieces from different peers, 642 680 so we'll build a list and pray one actually have this one */ 643 setme->fastAllowed = tr_peerMsgIsPieceFastAllowed( peer->msgs, i); 681 setme->fastAllowed = tr_peerMsgsIsPieceFastAllowed( peer->msgs, i ); 682 /* Also, if someone SUGGESTed a piece to us, prioritize it over non-suggested others 683 */ 684 setme->suggested = tr_peerMsgsIsPieceSuggested( peer->msgs, i ); 644 685 } 645 686 } … … 731 772 for( i=0; peerCount && i<blockCount; ++i ) 732 773 { 733 const int block = blocks[i];774 const uint64_t block = blocks[i]; 734 775 const uint32_t index = tr_torBlockPiece( tor, block ); 735 776 const uint32_t begin = (block * tor->blockSize) - (index * tor->info.pieceSize); 736 const uint32_t length = tr_torBlockCountBytes( tor, block );777 const uint32_t length = tr_torBlockCountBytes( tor, (int)block ); 737 778 int j; 738 assert( _tr_block( tor, index, begin ) == block );779 assert( _tr_block( tor, index, begin ) == (int)block ); 739 780 assert( begin < (uint32_t)tr_torPieceCountBytes( tor, (int)index ) ); 740 781 assert( (begin + length) <= (uint32_t)tr_torPieceCountBytes( tor, (int)index ) ); 741 742 782 743 783 /* find a peer who can ask for this block */ … … 807 847 808 848 static void 849 addStrike( Torrent * t, tr_peer * peer ) 850 { 851 tordbg( t, "increasing peer %s strike count to %d", tr_peerIoAddrStr(&peer->in_addr,peer->port), peer->strikes+1 ); 852 853 if( ++peer->strikes >= MAX_BAD_PIECES_PER_PEER ) 854 { 855 struct peer_atom * atom = getExistingAtom( t, &peer->in_addr ); 856 atom->myflags |= MYFLAG_BANNED; 857 peer->doPurge = 1; 858 tordbg( t, "banning peer %s", tr_peerIoAddrStr(&atom->addr,atom->port) ); 859 } 860 } 861 862 static void 809 863 msgsCallbackFunc( void * vpeer, void * vevent, void * vt ) 810 864 { … … 849 903 break; 850 904 905 case TR_PEERMSG_GOT_ASSERT_ERROR: 906 addStrike( t, peer ); 907 peer->doPurge = 1; 908 break; 909 851 910 case TR_PEERMSG_GOT_ERROR: 852 911 peer->doPurge = 1; … … 936 995 tr_peerIoFree( io ); 937 996 } 997 else if( tr_ptrArraySize( t->peers ) >= MAX_CONNECTED_PEERS_PER_TORRENT ) 998 { 999 tr_peerIoFree( io ); 1000 } 938 1001 else 939 1002 { … … 941 1004 942 1005 if( peer != NULL ) /* we already have this peer */ 943 {944 tr_peerIoFree( io );945 }946 else if( tr_ptrArraySize( t->peers ) >= MAX_CONNECTED_PEERS_PER_TORRENT )947 1006 { 948 1007 tr_peerIoFree( io ); … … 1063 1122 for( i=0; i<peerCount; ++i ) 1064 1123 { 1065 struct peer_atom * atom; 1066 tr_peer * peer; 1067 1068 peer = peers[i]; 1069 if( !tr_bitfieldHas( peer->blame, pieceIndex ) ) 1070 continue; 1071 1072 ++peer->strikes; 1073 tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes", 1074 tr_peerIoAddrStr(&peer->in_addr,peer->port), 1075 pieceIndex, (int)peer->strikes ); 1076 if( peer->strikes < MAX_BAD_PIECES_PER_PEER ) 1077 continue; 1078 1079 atom = getExistingAtom( t, &peer->in_addr ); 1080 atom->myflags |= MYFLAG_BANNED; 1081 peer->doPurge = 1; 1082 tordbg( t, "banning peer %s due to corrupt data", tr_peerIoAddrStr(&atom->addr,atom->port) ); 1124 tr_peer * peer = peers[i]; 1125 if( tr_bitfieldHas( peer->blame, pieceIndex ) ) 1126 { 1127 tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes", 1128 tr_peerIoAddrStr(&peer->in_addr,peer->port), 1129 pieceIndex, (int)peer->strikes+1 ); 1130 addStrike( t, peer ); 1131 } 1083 1132 } 1084 1133 } … … 1151 1200 static int reconnectPulse( void * vtorrent ); 1152 1201 static int rechokePulse( void * vtorrent ); 1202 static int swiftPulse( void * vtorrent ); 1153 1203 1154 1204 void … … 1165 1215 assert( ( t->isRunning != 0 ) == ( t->reconnectTimer != NULL ) ); 1166 1216 assert( ( t->isRunning != 0 ) == ( t->rechokeTimer != NULL ) ); 1217 assert( ( t->isRunning != 0 ) == ( t->swiftTimer != NULL ) ); 1167 1218 1168 1219 if( !t->isRunning ) … … 1178 1229 RECHOKE_PERIOD_MSEC ); 1179 1230 1231 t->swiftTimer = tr_timerNew( t->manager->handle, 1232 swiftPulse, t, 1233 SWIFT_PERIOD_MSEC ); 1234 1180 1235 reconnectPulse( t ); 1181 1236 1182 1237 rechokePulse( t ); 1238 1239 swiftPulse( t ); 1183 1240 } 1184 1241 … … 1194 1251 tr_timerFree( &t->rechokeTimer ); 1195 1252 tr_timerFree( &t->reconnectTimer ); 1253 tr_timerFree( &t->swiftTimer ); 1196 1254 1197 1255 /* disconnect the peers. */ … … 1305 1363 for( i=0; i<size; ++i ) 1306 1364 if( peers[i]->io != NULL ) 1307 tr_bitfield And( pieces, peers[i]->have );1365 tr_bitfieldOr( pieces, peers[i]->have ); 1308 1366 1309 1367 managerUnlock( (tr_peerMgr*)manager ); … … 1398 1456 1399 1457 tr_netNtop( &peer->in_addr, stat->addr, sizeof(stat->addr) ); 1458 strlcpy( stat->client, (peer->client ? peer->client : ""), sizeof(stat->client) ); 1400 1459 stat->port = peer->port; 1401 1460 stat->from = atom->from; 1402 stat->client = tr_strdup( peer->client ? peer->client : "" );1403 1461 stat->progress = peer->progress; 1404 1462 stat->isEncrypted = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0; … … 1407 1465 stat->isDownloading = stat->uploadToRate > 0.01; 1408 1466 stat->isUploading = stat->downloadFromRate > 0.01; 1467 stat->status = peer->status; 1409 1468 } 1410 1469 … … 1423 1482 { 1424 1483 tr_peer * peer; 1425 float rate; 1426 int randomKey; 1484 int rate; 1427 1485 int preferred; 1428 1486 int doUnchoke; … … 1435 1493 const struct ChokeData * b = vb; 1436 1494 1495 /* primary key: larger speeds */ 1496 if( a->rate > b->rate ) 1497 return -1; 1498 if ( a->rate < b->rate ) 1499 return 1; 1500 1501 /* secondary key: perferred peers */ 1437 1502 if( a->preferred != b->preferred ) 1438 1503 return a->preferred ? -1 : 1; 1439 1504 1440 if( a->preferred ) 1441 { 1442 if( a->rate > b->rate ) return -1; 1443 if( a->rate < b->rate ) return 1; 1444 return 0; 1445 } 1446 else 1447 { 1448 return a->randomKey - b->randomKey; 1449 } 1505 return 0; 1450 1506 } 1451 1507 … … 1463 1519 1464 1520 static double 1465 getWeightedThroughput( const tr_peer * peer )1466 { 1467 return ( 3 * peer->rateToPeer )1468 + ( 1 * peer->rateToClient);1521 getWeightedThroughput( const tr_peer * peer, int clientIsSeed ) 1522 { 1523 return (int)( 10.0 * ( clientIsSeed ? peer->rateToPeer 1524 : peer->rateToClient ) ); 1469 1525 } 1470 1526 … … 1476 1532 tr_peer ** peers = getConnectedPeers( t, &peerCount ); 1477 1533 struct ChokeData * choke = tr_new0( struct ChokeData, peerCount ); 1534 const int clientIsSeed = tr_torrentIsSeed( t->tor ); 1478 1535 1479 1536 assert( torrentIsLocked( t ) ); … … 1484 1541 tr_peer * peer = peers[i]; 1485 1542 struct ChokeData * node; 1486 if( peer->chokeChangedAt > fibrillationTime ) 1543 if( peer->chokeChangedAt > fibrillationTime ) { 1544 if( !peer->peerIsChoked ) 1545 ++unchoked; 1487 1546 continue; 1547 } 1488 1548 1489 1549 node = &choke[size++]; 1490 1550 node->peer = peer; 1491 1551 node->preferred = peer->peerIsInterested && !clientIsSnubbedBy(peer); 1492 node->randomKey = tr_rand( INT_MAX ); 1493 node->rate = getWeightedThroughput( peer ); 1552 node->rate = getWeightedThroughput( peer, clientIsSeed ); 1494 1553 } 1495 1554 1496 1555 qsort( choke, size, sizeof(struct ChokeData), compareChoke ); 1497 1556 1498 for( i=0; i<size && i<NUM_UNCHOKED_PEERS_PER_TORRENT; ++i ) {1557 for( i=0; i<size && unchoked<NUM_UNCHOKED_PEERS_PER_TORRENT; ++i ) { 1499 1558 choke[i].doUnchoke = 1; 1500 1559 ++unchoked; … … 1502 1561 1503 1562 for( ; i<size; ++i ) { 1563 ++unchoked; 1504 1564 choke[i].doUnchoke = 1; 1505 ++unchoked;1506 1565 if( choke[i].peer->peerIsInterested ) 1507 1566 break; … … 1522 1581 torrentLock( t ); 1523 1582 rechoke( t ); 1583 torrentUnlock( t ); 1584 return TRUE; 1585 } 1586 1587 /*** 1588 **** 1589 ***/ 1590 1591 static int 1592 swiftPulse( void * vtorrent ) 1593 { 1594 Torrent * t = vtorrent; 1595 torrentLock( t ); 1596 1597 if( !tr_torrentIsSeed( t->tor ) ) 1598 { 1599 int i; 1600 int peerCount = 0; 1601 int deadbeatCount = 0; 1602 tr_peer ** peers = getConnectedPeers( t, &peerCount ); 1603 tr_peer ** deadbeats = tr_new( tr_peer*, peerCount ); 1604 1605 const double ul_KiBsec = tr_rcRate( t->tor->upload ); 1606 const double ul_KiB = ul_KiBsec * (SWIFT_PERIOD_MSEC/1000.0); 1607 const double ul_bytes = ul_KiB * 1024; 1608 const double freeCreditTotal = ul_bytes * SWIFT_LARGESSE; 1609 int freeCreditPerPeer; 1610 1611 for( i=0; i<peerCount; ++i ) { 1612 tr_peer * peer = peers[i]; 1613 if( peer->credit <= 0 ) 1614 deadbeats[deadbeatCount++] = peer; 1615 } 1616 1617 freeCreditPerPeer = (int)( freeCreditTotal / deadbeatCount ); 1618 for( i=0; i<deadbeatCount; ++i ) 1619 deadbeats[i]->credit = freeCreditPerPeer; 1620 1621 tordbg( t, "%d deadbeats, " 1622 "who are each being granted %d bytes' credit " 1623 "for a total of %.1f KiB, " 1624 "%d%% of the torrent's ul speed %.1f\n", 1625 deadbeatCount, freeCreditPerPeer, 1626 ul_KiBsec*SWIFT_LARGESSE, (int)(SWIFT_LARGESSE*100), ul_KiBsec ); 1627 1628 tr_free( deadbeats ); 1629 tr_free( peers ); 1630 } 1631 1524 1632 torrentUnlock( t ); 1525 1633 return TRUE; … … 1633 1741 * now to weed it out in case someone sends it to us via pex */ 1634 1742 if( atom->myflags & MYFLAG_BANNED ) { 1743 #if 0 1635 1744 tordbg( t, "RECONNECT peer %d (%s) is banned...", 1636 1745 i, tr_peerIoAddrStr(&atom->addr,atom->port) ); 1746 #endif 1637 1747 continue; 1638 1748 } … … 1640 1750 /* we don't need two connections to the same peer... */ 1641 1751 if( peerIsInUse( t, &atom->addr ) ) { 1752 #if 0 1642 1753 tordbg( t, "RECONNECT peer %d (%s) is in use..", 1643 1754 i, tr_peerIoAddrStr(&atom->addr,atom->port) ); 1755 #endif 1644 1756 continue; 1645 1757 } … … 1647 1759 /* no need to connect if we're both seeds... */ 1648 1760 if( seed && (atom->flags & ADDED_F_SEED_FLAG) ) { 1761 #if 0 1649 1762 tordbg( t, "RECONNECT peer %d (%s) is a seed and so are we..", 1650 1763 i, tr_peerIoAddrStr(&atom->addr,atom->port) ); 1764 #endif 1651 1765 continue; 1652 1766 } … … 1654 1768 /* we're wasting our time trying to connect to this bozo. */ 1655 1769 if( atom->numFails > 10 ) { 1770 #if 0 1656 1771 tordbg( t, "RECONNECT peer %d (%s) gives us nothing but failure.", 1657 1772 i, tr_peerIoAddrStr(&atom->addr,atom->port) ); 1773 #endif 1658 1774 continue; 1659 1775 } … … 1692 1808 else 1693 1809 { 1694 int i, nCandidates, nBad , nAdd;1810 int i, nCandidates, nBad; 1695 1811 struct peer_atom ** candidates = getPeerCandidates( t, &nCandidates ); 1696 1812 struct tr_peer ** connections = getPeersToClose( t, &nBad ); 1697 const int peerCount = tr_ptrArraySize( t->peers );1698 1813 1699 1814 if( nBad || nCandidates ) … … 1719 1834 1720 1835 /* add some new ones */ 1721 nAdd = !peerCount ? MAX_CONNECTED_PEERS_PER_TORRENT 1722 : MAX_RECONNECTIONS_PER_PULSE; 1723 for( i=0; i<nAdd && i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i ) 1836 for( i=0; i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i ) 1724 1837 { 1725 1838 tr_peerMgr * mgr = t->manager; -
branches/0.9x/libtransmission/peer-msgs.c
r3837 r3897 21 21 #include <netinet/in.h> /* struct in_addr */ 22 22 23 #include <sys/queue.h> /* libevent needs this */24 #include <sys/types.h> /* libevent needs this */25 23 #include <event.h> 26 24 … … 71 69 72 70 PEX_INTERVAL = (60 * 1000), /* msec between calls to sendPex() */ 73 PEER_PULSE_INTERVAL = ( 100), /* msec between calls to pulse() */71 PEER_PULSE_INTERVAL = (250), /* msec between calls to pulse() */ 74 72 RATE_PULSE_INTERVAL = (333), /* msec between calls to ratePulse() */ 75 76 /* number of pieces generated for allow-fast, 77 threshold for fast-allowing others */ 78 MAX_ALLOWED_SET_COUNT = 10 73 74 /* Fast Peers Extension constants */ 75 MAX_FAST_ALLOWED_COUNT = 10, /* max. number of pieces we fast-allow to another peer */ 76 MAX_FAST_ALLOWED_THRESHOLD = 10, /* max threshold for allowing fast-pieces requests */ 77 79 78 }; 80 79 … … 82 81 { 83 82 AWAITING_BT_LENGTH, 84 AWAITING_BT_MESSAGE 83 AWAITING_BT_ID, 84 AWAITING_BT_MESSAGE, 85 AWAITING_BT_PIECE 85 86 }; 86 87 … … 105 106 } 106 107 108 /* this is raw, unchanged data from the peer regarding 109 * the current message that it's sending us. */ 110 struct tr_incoming 111 { 112 uint32_t length; /* includes the +1 for id length */ 113 uint8_t id; 114 struct peer_request blockReq; /* metadata for incoming blocks */ 115 struct evbuffer * block; /* piece data for incoming blocks */ 116 }; 117 107 118 struct tr_peermsgs 108 119 { … … 130 141 time_t clientSentAnythingAt; 131 142 132 unsigned int notListening: 1;143 unsigned int peerSentBitfield : 1; 133 144 unsigned int peerSupportsPex : 1; 134 145 unsigned int clientSentLtepHandshake : 1; 135 146 unsigned int peerSentLtepHandshake : 1; 147 unsigned int sendingBlock : 1; 136 148 137 149 tr_bitfield * clientAllowedPieces; 138 150 tr_bitfield * peerAllowedPieces; 139 151 152 tr_bitfield * clientSuggestedPieces; 153 140 154 uint8_t state; 141 155 uint8_t ut_pex_id; 142 156 uint16_t pexCount; 143 uint32_t incomingMessageLength;144 157 uint32_t maxActiveRequests; 145 158 uint32_t minActiveRequests; 159 160 struct tr_incoming incoming; 146 161 147 162 tr_pex * pex; … … 251 266 252 267 static void 268 fireGotAssertError( tr_peermsgs * msgs ) 269 { 270 tr_peermsgs_event e = blankEvent; 271 e.eventType = TR_PEERMSG_GOT_ASSERT_ERROR; 272 publish( msgs, &e ); 273 } 274 275 static void 253 276 fireGotError( tr_peermsgs * msgs ) 254 277 { … … 426 449 uint32_t pieceIndex ) 427 450 { 428 dbgmsg( msgs, "w00t SUGGESTing them piece #%d", pieceIndex ); 429 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) ); 430 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST ); 431 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex ); 451 assert( msgs != NULL ); 432 452 433 updateInterest( msgs ); 453 if( tr_peerIoSupportsFEXT( msgs->io ) ) 454 { 455 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) ); 456 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST ); 457 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex ); 458 } 434 459 } 435 460 #endif … … 437 462 sendFastHave( tr_peermsgs * msgs, int all ) 438 463 { 439 dbgmsg( msgs, "w00t telling them we have %s pieces", (all ? "ALL" : "NONE" ) ); 440 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) ); 441 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, ( all ? BT_HAVE_ALL 442 : BT_HAVE_NONE ) ); 443 updateInterest( msgs ); 464 assert( msgs != NULL ); 465 466 if( tr_peerIoSupportsFEXT( msgs->io ) ) 467 { 468 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) ); 469 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, ( all ? BT_HAVE_ALL 470 : BT_HAVE_NONE ) ); 471 updateInterest( msgs ); 472 } 444 473 } 445 474 … … 467 496 uint32_t pieceIndex) 468 497 { 469 dbgmsg( msgs, "w00t telling them we ALLOW_FAST piece #%d", pieceIndex ); 470 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) ); 471 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_ALLOWED_FAST ); 472 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex ); 498 assert( msgs != NULL ); 499 500 if( tr_peerIoSupportsFEXT( msgs->io ) ) 501 { 502 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) ); 503 tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_ALLOWED_FAST ); 504 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex ); 505 } 473 506 } 474 507 … … 534 567 { 535 568 struct peer_request * r = tr_list_pop_front( &msgs->clientWillAskFor ); 569 assert( requestIsValid( msgs, r ) ); 570 assert( tr_bitfieldHas( msgs->info->have, r->index ) ); 536 571 protocolSendRequest( msgs, r ); 537 572 r->time_requested = msgs->lastReqAddedAt = time( NULL ); … … 550 585 fireNeedReq( msgs ); 551 586 } 587 588 static int 589 pulse( void * vmsgs ); 552 590 553 591 int … … 701 739 tr_bencInitInt( tr_bencDictAdd( &val, "p" ), port ); 702 740 tr_bencInitStr( tr_bencDictAdd( &val, "v" ), v, 0, 1 ); 703 buf = tr_bencSave Malloc( &val, &len );741 buf = tr_bencSave( &val, &len ); 704 742 705 743 tr_peerIoWriteUint32( msgs->io, outbuf, 2*sizeof(uint8_t) + len ); … … 713 751 dbgmsg( msgs, "here is the ltep handshake we sent:" ); 714 752 tr_bencPrint( &val ); 753 dbgmsg( msgs, "here is the ltep handshake we read [%s]:", tr_bencSave( &val, NULL ) ); 715 754 #endif 716 755 … … 739 778 dbgmsg( msgs, "here is the ltep handshake we read:" ); 740 779 tr_bencPrint( &val ); 780 dbgmsg( msgs, "here is the ltep handshake we read [%s]:", tr_bencSave( &val, NULL ) ); 741 781 #endif 742 782 … … 817 857 dbgmsg( msgs, "got ltep handshake" ); 818 858 parseLtepHandshake( msgs, msglen, inbuf ); 819 sendLtepHandshake( msgs ); 820 sendPex( msgs ); 859 if( tr_peerIoSupportsLTEP( msgs->io ) ) 860 { 861 sendLtepHandshake( msgs ); 862 sendPex( msgs ); 863 } 821 864 } 822 865 else if( ltep_msgid == msgs->ut_pex_id ) … … 834 877 835 878 static int 836 readBtLength( tr_peermsgs * msgs, struct evbuffer * inbuf )879 readBtLength( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) 837 880 { 838 881 uint32_t len; 839 const size_t needlen = sizeof(uint32_t); 840 841 if( EVBUFFER_LENGTH(inbuf) < needlen ) 882 883 if( inlen < sizeof(len) ) 842 884 return READ_MORE; 843 885 … … 847 889 dbgmsg( msgs, "got KeepAlive" ); 848 890 else { 849 msgs->incomingMessageLength = len; 891 msgs->incoming.length = len; 892 msgs->state = AWAITING_BT_ID; 893 } 894 895 return READ_AGAIN; 896 } 897 898 static int 899 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ); 900 901 static int 902 readBtId( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) 903 { 904 uint8_t id; 905 906 if( inlen < sizeof(uint8_t) ) 907 return READ_MORE; 908 909 tr_peerIoReadUint8( msgs->io, inbuf, &id ); 910 msgs->incoming.id = id; 911 912 if( id==BT_PIECE ) 913 { 914 msgs->state = AWAITING_BT_PIECE; 915 return READ_AGAIN; 916 } 917 else if( msgs->incoming.length != 1 ) 918 { 850 919 msgs->state = AWAITING_BT_MESSAGE; 851 }852 853 return READ_AGAIN;920 return READ_AGAIN; 921 } 922 else return readBtMessage( msgs, inbuf, inlen-1 ); 854 923 } 855 924 … … 866 935 clientCanSendFastBlock( const tr_peermsgs * msgs UNUSED ) 867 936 { 868 /* FIXME(tiennou): base this on how many blocks we've already sent this 869 * peer, or maybe how many fast blocks per minute we've sent overall, 870 * or maybe how much bandwidth we're already using up w/o fast peers. 871 * I don't know what the Right Thing here is, but 872 * the previous measurement of how many pieces we have is not enough. */ 873 return FALSE; 937 /* We can't send a fast piece if a peer has more than MAX_FAST_ALLOWED_THRESHOLD pieces */ 938 if( tr_bitfieldCountTrueBits( msgs->info->have ) > MAX_FAST_ALLOWED_THRESHOLD ) 939 return FALSE; 940 941 /* ...or if we don't have ourself enough pieces */ 942 if( tr_bitfieldCountTrueBits( tr_cpPieceBitfield( msgs->torrent->completion ) ) < MAX_FAST_ALLOWED_THRESHOLD ) 943 return FALSE; 944 945 /* Maybe a bandwidth limit ? */ 946 return TRUE; 874 947 } 875 948 … … 954 1027 } 955 1028 956 static void1029 static int 957 1030 clientGotBlock( tr_peermsgs * msgs, const uint8_t * block, const struct peer_request * req ); 958 1031 1032 static void 1033 clientGotBytes( tr_peermsgs * msgs, uint32_t byteCount ) 1034 { 1035 tr_torrent * tor = msgs->torrent; 1036 tor->activityDate = tr_date( ); 1037 tor->downloadedCur += byteCount; 1038 msgs->info->pieceDataActivityDate = time( NULL ); 1039 msgs->info->credit += (int)(byteCount * SWIFT_REPAYMENT_RATIO); 1040 tr_rcTransferred( msgs->info->rcToClient, byteCount ); 1041 tr_rcTransferred( tor->download, byteCount ); 1042 tr_rcTransferred( tor->handle->download, byteCount ); 1043 } 1044 1045 959 1046 static int 960 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf ) 961 { 962 uint8_t id; 1047 readBtPiece( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) 1048 { 1049 struct peer_request * req = &msgs->incoming.blockReq; 1050 assert( EVBUFFER_LENGTH(inbuf) >= inlen ); 1051 dbgmsg( msgs, "In readBtPiece" ); 1052 1053 if( !req->length ) 1054 { 1055 if( inlen < 8 ) 1056 return READ_MORE; 1057 1058 tr_peerIoReadUint32( msgs->io, inbuf, &req->index ); 1059 tr_peerIoReadUint32( msgs->io, inbuf, &req->offset ); 1060 req->length = msgs->incoming.length - 9; 1061 dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length ); 1062 return READ_AGAIN; 1063 } 1064 else 1065 { 1066 int err; 1067 1068 /* read in another chunk of data */ 1069 const size_t nLeft = req->length - EVBUFFER_LENGTH(msgs->incoming.block); 1070 size_t n = MIN( nLeft, inlen ); 1071 uint8_t * buf = tr_new( uint8_t, n ); 1072 assert( EVBUFFER_LENGTH(inbuf) >= n ); 1073 tr_peerIoReadBytes( msgs->io, inbuf, buf, n ); 1074 evbuffer_add( msgs->incoming.block, buf, n ); 1075 clientGotBytes( msgs, n ); 1076 tr_free( buf ); 1077 dbgmsg( msgs, "got %d bytes for block %u:%u->%u ... %d remain", 1078 (int)n, req->index, req->offset, req->length, 1079 (int)( req->length - EVBUFFER_LENGTH(msgs->incoming.block) ) ); 1080 if( EVBUFFER_LENGTH(msgs->incoming.block) < req->length ) 1081 return READ_MORE; 1082 1083 /* we've got the whole block ... process it */ 1084 err = clientGotBlock( msgs, EVBUFFER_DATA(msgs->incoming.block), req ); 1085 1086 /* cleanup */ 1087 evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH(msgs->incoming.block) ); 1088 req->length = 0; 1089 msgs->state = AWAITING_BT_LENGTH; 1090 if( !err ) 1091 return READ_AGAIN; 1092 else { 1093 fireGotAssertError( msgs ); 1094 return READ_DONE; 1095 } 1096 } 1097 } 1098 1099 static int 1100 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) 1101 { 963 1102 uint32_t ui32; 964 uint32_t msglen = msgs->incomingMessageLength; 1103 uint32_t msglen = msgs->incoming.length; 1104 const uint8_t id = msgs->incoming.id; 965 1105 const size_t startBufLen = EVBUFFER_LENGTH( inbuf ); 966 1106 967 if( EVBUFFER_LENGTH(inbuf) < msglen ) 1107 --msglen; // id length 1108 1109 if( inlen < msglen ) 968 1110 return READ_MORE; 969 1111 970 tr_peerIoReadUint8( msgs->io, inbuf, &id ); 971 dbgmsg( msgs, "got BT id %d, len %d, buffer size is %d", (int)id, (int)msglen, (int)EVBUFFER_LENGTH(inbuf) ); 972 973 if( !messageLengthIsCorrect( msgs, id, msglen ) ) 1112 dbgmsg( msgs, "got BT id %d, len %d, buffer size is %d", (int)id, (int)msglen, (int)inlen ); 1113 1114 if( !messageLengthIsCorrect( msgs, id, msglen+1 ) ) 974 1115 { 975 1116 dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen ); … … 977 1118 return READ_DONE; 978 1119 } 979 980 --msglen;981 1120 982 1121 switch( id ) … … 1005 1144 msgs->info->peerIsInterested = 0; 1006 1145 break; 1007 1146 1008 1147 case BT_HAVE: 1009 1148 tr_peerIoReadUint32( msgs->io, inbuf, &ui32 ); 1010 1149 dbgmsg( msgs, "got Have: %u", ui32 ); 1011 1150 tr_bitfieldAdd( msgs->info->have, ui32 ); 1151 /* If this is a fast-allowed piece for this peer, mark it as normal now */ 1152 if( msgs->clientAllowedPieces != NULL && tr_bitfieldHas( msgs->clientAllowedPieces, ui32 ) ) 1153 tr_bitfieldRem( msgs->clientAllowedPieces, ui32 ); 1012 1154 updatePeerProgress( msgs ); 1013 1155 tr_rcTransferred( msgs->torrent->swarmspeed, msgs->torrent->info.pieceSize ); … … 1017 1159 const int clientIsSeed = tr_torrentIsSeed( msgs->torrent ); 1018 1160 dbgmsg( msgs, "got a bitfield" ); 1161 msgs->peerSentBitfield = 1; 1019 1162 tr_peerIoReadBytes( msgs->io, inbuf, msgs->info->have->bits, msglen ); 1020 1163 updatePeerProgress( msgs ); … … 1045 1188 } 1046 1189 1047 case BT_PIECE: { 1048 uint8_t * block; 1049 struct peer_request req; 1050 tr_peerIoReadUint32( msgs->io, inbuf, &req.index ); 1051 tr_peerIoReadUint32( msgs->io, inbuf, &req.offset ); 1052 req.length = msglen - 8; 1053 block = tr_new( uint8_t, req.length ); 1054 tr_peerIoReadBytes( msgs->io, inbuf, block, req.length ); 1055 dbgmsg( msgs, "got a Block %u:%u->%u", req.index, req.offset, req.length ); 1056 clientGotBlock( msgs, block, &req ); 1057 tr_free( block ); 1190 case BT_PIECE: 1191 assert( 0 ); /* should be handled elsewhere! */ 1058 1192 break; 1059 } 1060 1193 1061 1194 case BT_PORT: 1062 1195 dbgmsg( msgs, "Got a BT_PORT" ); 1063 1196 tr_peerIoReadUint16( msgs->io, inbuf, &msgs->info->port ); 1064 1197 break; 1065 1066 #if 0 1198 1067 1199 case BT_SUGGEST: { 1068 /* FIXME(tiennou) */ 1069 uint32_t index; 1070 tr_peerIoReadUint32( msgs->io, inbuf, &index ); 1200 dbgmsg( msgs, "Got a BT_SUGGEST" ); 1201 tr_peerIoReadUint32( msgs->io, inbuf, &ui32 ); 1202 const tr_bitfield * bt = tr_cpPieceBitfield( msgs->torrent->completion ); 1203 if( tr_bitfieldHas( bt, ui32 ) ) 1204 tr_bitfieldAdd( msgs->clientSuggestedPieces, ui32 ); 1071 1205 break; 1072 1206 } 1073 1207 1074 1208 case BT_HAVE_ALL: 1075 1209 dbgmsg( msgs, "Got a BT_HAVE_ALL" ); … … 1077 1211 updatePeerProgress( msgs ); 1078 1212 break; 1079 1213 1214 1080 1215 case BT_HAVE_NONE: 1081 1216 dbgmsg( msgs, "Got a BT_HAVE_NONE" ); … … 1083 1218 updatePeerProgress( msgs ); 1084 1219 break; 1085 1220 1086 1221 case BT_REJECT: { 1087 1222 struct peer_request req; … … 1100 1235 break; 1101 1236 } 1102 #endif1103 1237 1104 1238 case BT_LTEP: … … 1113 1247 } 1114 1248 1115 1116 dbgmsg( msgs, "startBufLen was %d, msglen was %d, current inbuf len is %d", (int)startBufLen, (int)(msglen+1), (int)EVBUFFER_LENGTH(inbuf) ); 1117 1118 msgs->incomingMessageLength = -1; 1249 assert( msglen + 1 == msgs->incoming.length ); 1250 assert( EVBUFFER_LENGTH(inbuf) == startBufLen - msglen ); 1251 1119 1252 msgs->state = AWAITING_BT_LENGTH; 1120 1253 return READ_AGAIN; 1121 }1122 1123 static void1124 clientGotBytes( tr_peermsgs * msgs, uint32_t byteCount )1125 {1126 tr_torrent * tor = msgs->torrent;1127 tor->activityDate = tr_date( );1128 tor->downloadedCur += byteCount;1129 msgs->info->pieceDataActivityDate = time( NULL );1130 tr_rcTransferred( msgs->info->rcToClient, byteCount );1131 tr_rcTransferred( tor->download, byteCount );1132 tr_rcTransferred( tor->handle->download, byteCount );1133 1254 } 1134 1255 … … 1140 1261 tor->uploadedCur += byteCount; 1141 1262 msgs->info->pieceDataActivityDate = time( NULL ); 1263 msgs->info->credit -= byteCount; 1142 1264 tr_rcTransferred( msgs->info->rcToPeer, byteCount ); 1143 1265 tr_rcTransferred( tor->upload, byteCount ); … … 1145 1267 } 1146 1268 1147 static int 1148 canDownload( const tr_peermsgs * msgs ) 1149 { 1150 tr_torrent * tor = msgs->torrent; 1269 static size_t 1270 getDownloadMax( const tr_peermsgs * msgs ) 1271 { 1272 static const size_t maxval = ~0; 1273 const tr_torrent * tor = msgs->torrent; 1151 1274 1152 1275 if( tor->downloadLimitMode == TR_SPEEDLIMIT_GLOBAL ) 1153 return !tor->handle->useDownloadLimit || tr_rcCanTransfer( tor->handle->download ); 1276 return tor->handle->useDownloadLimit 1277 ? tr_rcBytesLeft( tor->handle->download ) : maxval; 1154 1278 1155 1279 if( tor->downloadLimitMode == TR_SPEEDLIMIT_SINGLE ) 1156 return tr_rc CanTransfer( tor->download );1157 1158 return TRUE;1280 return tr_rcBytesLeft( tor->download ); 1281 1282 return maxval; 1159 1283 } 1160 1284 … … 1178 1302 gotBadPiece( tr_peermsgs * msgs, uint32_t pieceIndex ) 1179 1303 { 1180 const uint32_t byteCount = tr_torPieceCountBytes( msgs->torrent, (int)pieceIndex ); 1304 const uint32_t byteCount = 1305 tr_torPieceCountBytes( msgs->torrent, (int)pieceIndex ); 1181 1306 reassignBytesToCorrupt( msgs, byteCount ); 1182 1307 } … … 1196 1321 } 1197 1322 1198 static void 1199 clientGotBlock( tr_peermsgs * msgs, const uint8_t * data, const struct peer_request * req ) 1323 static int 1324 clientGotBlock( tr_peermsgs * msgs, 1325 const uint8_t * data, 1326 const struct peer_request * req ) 1200 1327 { 1201 1328 int i; … … 1206 1333 assert( msgs != NULL ); 1207 1334 assert( req != NULL ); 1208 assert( req->length > 0 ); 1209 assert( req->length == (uint32_t)tr_torBlockCountBytes( msgs->torrent, block ) ); 1335 1336 if( req->length != (uint32_t)tr_torBlockCountBytes( msgs->torrent, block ) ) 1337 { 1338 dbgmsg( msgs, "wrong block size -- expected %u, got %d", 1339 tr_torBlockCountBytes( msgs->torrent, block ), req->length ); 1340 return TR_ERROR_ASSERT; 1341 } 1210 1342 1211 1343 /* save the block */ … … 1220 1352 clientGotUnwantedBlock( msgs, req ); 1221 1353 dbgmsg( msgs, "we didn't ask for this message..." ); 1222 return ;1354 return 0; 1223 1355 } 1224 1356 … … 1239 1371 dbgmsg( msgs, "we have this block already..." ); 1240 1372 clientGotUnwantedBlock( msgs, req ); 1241 return ;1373 return 0; 1242 1374 } 1243 1375 … … 1247 1379 1248 1380 msgs->info->peerSentPieceDataAt = time( NULL ); 1249 clientGotBytes( msgs, req->length );1250 1381 i = tr_ioWrite( tor, req->index, req->offset, req->length, data ); 1251 1382 if( i ) 1252 return ;1383 return 0; 1253 1384 1254 1385 tr_cpBlockAdd( tor->completion, block ); … … 1267 1398 { 1268 1399 gotBadPiece( msgs, req->index ); 1269 return ;1400 return 0; 1270 1401 } 1271 1402 1272 1403 fireClientHave( msgs, req->index ); 1273 1404 } 1405 1406 return 0; 1274 1407 } 1275 1408 … … 1280 1413 tr_peermsgs * msgs = (tr_peermsgs *) vmsgs; 1281 1414 struct evbuffer * inbuf = EVBUFFER_INPUT ( evin ); 1282 1283 if( !canDownload( msgs ) ) 1284 { 1285 msgs->notListening = 1; 1286 tr_peerIoSetIOMode ( msgs->io, 0, EV_READ ); 1415 const size_t buflen = EVBUFFER_LENGTH( inbuf ); 1416 const size_t downloadMax = getDownloadMax( msgs ); 1417 const size_t n = MIN( buflen, downloadMax ); 1418 1419 if( !n ) 1420 { 1287 1421 ret = READ_DONE; 1288 1422 } 1289 1423 else switch( msgs->state ) 1290 1424 { 1291 case AWAITING_BT_LENGTH: ret = readBtLength ( msgs, inbuf ); break; 1292 case AWAITING_BT_MESSAGE: ret = readBtMessage ( msgs, inbuf ); break; 1425 case AWAITING_BT_LENGTH: ret = readBtLength ( msgs, inbuf, n ); break; 1426 case AWAITING_BT_ID: ret = readBtId ( msgs, inbuf, n ); break; 1427 case AWAITING_BT_MESSAGE: ret = readBtMessage( msgs, inbuf, n ); break; 1428 case AWAITING_BT_PIECE: ret = readBtPiece ( msgs, inbuf, n ); break; 1293 1429 default: assert( 0 ); 1294 1430 } … … 1308 1444 **/ 1309 1445 1310 static int1311 canWrite( const tr_peermsgs * msgs )1312 {1313 /* don't let our outbuffer get too large */1314 if( tr_peerIoWriteBytesWaiting( msgs->io ) > 4096 )1315 return FALSE;1316 1317 return TRUE;1318 }1319 1320 1446 static size_t 1321 1447 getUploadMax( const tr_peermsgs * msgs ) … … 1323 1449 static const size_t maxval = ~0; 1324 1450 const tr_torrent * tor = msgs->torrent; 1325 1326 if( !canWrite( msgs ) ) 1327 return 0; 1451 const int useSwift = SWIFT_ENABLED && !tr_torrentIsSeed( msgs->torrent ); 1452 const size_t swiftLeft = msgs->info->credit; 1453 size_t speedLeft; 1454 size_t bufLeft; 1455 size_t ret; 1328 1456 1329 1457 if( tor->uploadLimitMode == TR_SPEEDLIMIT_GLOBAL ) 1330 return tor->handle->useUploadLimit 1331 ? tr_rcBytesLeft( tor->handle->upload ) : maxval; 1332 1333 if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE ) 1334 return tr_rcBytesLeft( tor->upload ); 1335 1336 return maxval; 1458 speedLeft = tor->handle->useUploadLimit ? tr_rcBytesLeft( tor->handle->upload ) : maxval; 1459 else if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE ) 1460 speedLeft = tr_rcBytesLeft( tor->upload ); 1461 else 1462 speedLeft = ~0; 1463 1464 bufLeft = 4096 - tr_peerIoWriteBytesWaiting( msgs->io ); 1465 ret = MIN( speedLeft, bufLeft ); 1466 if( useSwift) 1467 ret = MIN( ret, swiftLeft ); 1468 return ret; 1337 1469 } 1338 1470 … … 1358 1490 } 1359 1491 1492 static void 1493 updatePeerStatus( tr_peermsgs * msgs ) 1494 { 1495 tr_peer * peer = msgs->info; 1496 1497 if( !msgs->peerSentBitfield ) 1498 peer->status = TR_PEER_STATUS_HANDSHAKE; 1499 1500 else if( ( time(NULL) - peer->pieceDataActivityDate ) < 3 ) 1501 peer->status = peer->clientIsChoked 1502 ? TR_PEER_STATUS_ACTIVE_AND_CHOKED 1503 : TR_PEER_STATUS_ACTIVE; 1504 1505 else if( peer->peerIsChoked ) 1506 peer->status = TR_PEER_STATUS_PEER_IS_CHOKED; 1507 1508 else if( peer->clientIsChoked ) 1509 peer->status = peer->clientIsInterested 1510 ? TR_PEER_STATUS_CLIENT_IS_INTERESTED 1511 : TR_PEER_STATUS_CLIENT_IS_CHOKED; 1512 1513 else if( msgs->clientAskedFor != NULL ) 1514 peer->status = TR_PEER_STATUS_REQUEST_SENT; 1515 1516 else 1517 peer->status = TR_PEER_STATUS_READY; 1518 } 1519 1360 1520 static int 1361 1521 pulse( void * vmsgs ) … … 1364 1524 tr_peermsgs * msgs = vmsgs; 1365 1525 struct peer_request * r; 1366 size_t len; 1367 1368 /* if we froze out a downloaded block because of speed limits, 1369 start listening to the peer again */ 1370 if( msgs->notListening && canDownload( msgs ) ) 1371 { 1372 msgs->notListening = 0; 1373 tr_peerIoSetIOMode ( msgs->io, EV_READ, 0 ); 1374 } 1375 1526 1527 tr_peerIoTryRead( msgs->io ); 1376 1528 pumpRequestQueue( msgs ); 1377 1378 if( !canWrite( msgs ) ) 1379 { 1380 } 1381 else if(( len = EVBUFFER_LENGTH( msgs->outBlock ) )) 1529 updatePeerStatus( msgs ); 1530 1531 if( msgs->sendingBlock ) 1382 1532 { 1383 1533 const size_t uploadMax = getUploadMax( msgs ); 1534 size_t len = EVBUFFER_LENGTH( msgs->outBlock ); 1384 1535 const size_t outlen = MIN( len, uploadMax ); 1385 tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen ); 1386 evbuffer_drain( msgs->outBlock, outlen ); 1387 msgs->clientSentAnythingAt = now; 1388 peerGotBytes( msgs, outlen ); 1389 len -= outlen; 1390 dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen, (int)len ); 1391 fflush( stdout ); 1392 } 1393 else if(( len = EVBUFFER_LENGTH( msgs->outMessages ) )) 1394 { 1395 tr_peerIoWriteBuf( msgs->io, msgs->outMessages ); 1396 msgs->clientSentAnythingAt = now; 1397 } 1398 else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS ) 1399 { 1400 sendKeepalive( msgs ); 1401 } 1402 1403 if( !EVBUFFER_LENGTH( msgs->outBlock ) 1404 && (( r = popNextRequest( msgs ))) 1405 && requestIsValid( msgs, r ) 1406 && tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) ) 1407 { 1408 uint8_t * buf = tr_new( uint8_t, r->length ); 1409 1410 if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) ) 1536 1537 assert( len ); 1538 1539 if( outlen ) 1411 1540 { 1412 tr_peerIo * io = msgs->io;1413 struct evbuffer * out = msgs->outBlock;1414 1415 dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length ); 1416 tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );1417 tr_peerIoWriteUint8 ( io, out, BT_PIECE );1418 tr_peerIoWriteUint32( io, out, r->index );1419 tr_peerIoWriteUint32( io, out, r->offset ); 1420 tr_peerIoWriteBytes ( io, out, buf, r->length);1541 tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen ); 1542 evbuffer_drain( msgs->outBlock, outlen ); 1543 peerGotBytes( msgs, outlen ); 1544 1545 len -= outlen; 1546 msgs->clientSentAnythingAt = now; 1547 msgs->sendingBlock = len!=0; 1548 1549 dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen, (int)len ); 1421 1550 } 1422 1423 tr_free( buf ); 1424 tr_free( r ); 1425 1426 pulse( msgs ); /* start sending it right away */ 1551 else dbgmsg( msgs, "stalled writing block... uploadMax %lu, outlen %lu", uploadMax, outlen ); 1552 } 1553 1554 if( !msgs->sendingBlock ) 1555 { 1556 if(( EVBUFFER_LENGTH( msgs->outMessages ) )) 1557 { 1558 dbgmsg( msgs, "flushing outMessages..." ); 1559 tr_peerIoWriteBuf( msgs->io, msgs->outMessages ); 1560 msgs->clientSentAnythingAt = now; 1561 } 1562 else if( !EVBUFFER_LENGTH( msgs->outBlock ) 1563 && (( r = popNextRequest( msgs ))) 1564 && requestIsValid( msgs, r ) 1565 && tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) ) 1566 { 1567 uint8_t * buf = tr_new( uint8_t, r->length ); 1568 1569 if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) ) 1570 { 1571 tr_peerIo * io = msgs->io; 1572 struct evbuffer * out = msgs->outBlock; 1573 1574 dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length ); 1575 tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length ); 1576 tr_peerIoWriteUint8 ( io, out, BT_PIECE ); 1577 tr_peerIoWriteUint32( io, out, r->index ); 1578 tr_peerIoWriteUint32( io, out, r->offset ); 1579 tr_peerIoWriteBytes ( io, out, buf, r->length ); 1580 msgs->sendingBlock = 1; 1581 } 1582 1583 tr_free( buf ); 1584 tr_free( r ); 1585 } 1586 else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS ) 1587 { 1588 sendKeepalive( msgs ); 1589 } 1427 1590 } 1428 1591 … … 1431 1594 1432 1595 static void 1433 didWrite( struct bufferevent * evin UNUSED, void * vmsgs )1434 {1435 pulse( vmsgs );1436 }1437 1438 static void1439 1596 gotError( struct bufferevent * evbuf UNUSED, short what, void * vmsgs ) 1440 1597 { 1441 dbgmsg( vmsgs, "libevent got an error! what=%d, errno=%d (%s)", 1442 (int)what, errno, strerror(errno) ); 1443 fireGotError( vmsgs ); 1598 if( what & EVBUFFER_TIMEOUT ) 1599 dbgmsg( vmsgs, "libevent got a timeout, what=%hd", what ); 1600 1601 if( what & ( EVBUFFER_EOF | EVBUFFER_ERROR ) ) { 1602 dbgmsg( vmsgs, "libevent got an error! what=%hd, errno=%d (%s)", 1603 what, errno, strerror(errno) ); 1604 fireGotError( vmsgs ); 1605 } 1444 1606 } 1445 1607 … … 1579 1741 1580 1742 /* write the pex message */ 1581 benc = tr_bencSave Malloc( &val, &bencLen );1743 benc = tr_bencSave( &val, &bencLen ); 1582 1744 tr_peerIoWriteUint32( msgs->io, msgs->outMessages, 2*sizeof(uint8_t) + bencLen ); 1583 1745 tr_peerIoWriteUint8 ( msgs->io, msgs->outMessages, BT_LTEP ); … … 1625 1787 m->torrent = torrent; 1626 1788 m->io = info->io; 1789 m->info->status = TR_PEER_STATUS_HANDSHAKE; 1627 1790 m->info->clientIsChoked = 1; 1628 1791 m->info->peerIsChoked = 1; … … 1630 1793 m->info->peerIsInterested = 0; 1631 1794 m->info->have = tr_bitfieldNew( torrent->info.pieceCount ); 1795 m->state = AWAITING_BT_LENGTH; 1632 1796 m->pulseTimer = tr_timerNew( m->handle, pulse, m, PEER_PULSE_INTERVAL ); 1633 1797 m->rateTimer = tr_timerNew( m->handle, ratePulse, m, RATE_PULSE_INTERVAL ); 1634 1798 m->pexTimer = tr_timerNew( m->handle, pexPulse, m, PEX_INTERVAL ); 1635 1799 m->outMessages = evbuffer_new( ); 1800 m->incoming.block = evbuffer_new( ); 1636 1801 m->outBlock = evbuffer_new( ); 1637 1802 m->peerAllowedPieces = NULL; 1638 1803 m->clientAllowedPieces = NULL; 1804 m->clientSuggestedPieces = NULL; 1639 1805 *setme = tr_publisherSubscribe( m->publisher, func, userData ); 1640 1806 … … 1646 1812 const struct in_addr *peerAddr = tr_peerIoGetAddress( m->io, NULL ); 1647 1813 1648 m->peerAllowedPieces = tr_peerMgrGenerateAllowedSet( MAX_ ALLOWED_SET_COUNT,1814 m->peerAllowedPieces = tr_peerMgrGenerateAllowedSet( MAX_FAST_ALLOWED_COUNT, 1649 1815 m->torrent->info.pieceCount, 1650 1816 m->torrent->info.hash, … … 1652 1818 } 1653 1819 m->clientAllowedPieces = tr_bitfieldNew( m->torrent->info.pieceCount ); 1820 1821 m->clientSuggestedPieces = tr_bitfieldNew( m->torrent->info.pieceCount ); 1654 1822 } 1655 1823 1656 1824 tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of inactivity */ 1657 tr_peerIoSetIOFuncs( m->io, canRead, didWrite, gotError, m ); 1658 tr_peerIoSetIOMode( m->io, EV_READ|EV_WRITE, 0 ); 1825 tr_peerIoSetIOFuncs( m->io, canRead, gotError, m ); 1659 1826 ratePulse( m ); 1660 1827 … … 1677 1844 peerProgress = m->torrent->info.pieceCount * m->info->progress; 1678 1845 1679 if ( peerProgress < MAX_ ALLOWED_SET_COUNT )1846 if ( peerProgress < MAX_FAST_ALLOWED_COUNT ) 1680 1847 sendFastAllowedSet( m ); 1681 1848 } … … 1697 1864 tr_list_free( &msgs->peerAskedForFast, tr_free ); 1698 1865 tr_list_free( &msgs->peerAskedFor, tr_free ); 1866 tr_bitfieldFree( msgs->peerAllowedPieces ); 1867 tr_bitfieldFree( msgs->clientAllowedPieces ); 1868 tr_bitfieldFree( msgs->clientSuggestedPieces ); 1869 evbuffer_free( msgs->incoming.block ); 1699 1870 evbuffer_free( msgs->outMessages ); 1700 1871 evbuffer_free( msgs->outBlock ); 1701 1872 tr_free( msgs->pex ); 1702 msgs->pexCount = 0; 1873 1874 memset( msgs, ~0, sizeof( tr_peermsgs ) ); 1703 1875 tr_free( msgs ); 1704 1876 } … … 1721 1893 1722 1894 int 1723 tr_peerMsg IsPieceFastAllowed( const tr_peermsgs * peer,1724 uint32_t index )1895 tr_peerMsgsIsPieceFastAllowed( const tr_peermsgs * peer, 1896 uint32_t index ) 1725 1897 { 1726 1898 return tr_bitfieldHas( peer->clientAllowedPieces, index ); 1727 1899 } 1900 1901 int 1902 tr_peerMsgsIsPieceSuggested( const tr_peermsgs * peer, 1903 uint32_t index ) 1904 { 1905 return tr_bitfieldHas( peer->clientSuggestedPieces, index ); 1906 } 1907 -
branches/0.9x/libtransmission/peer-msgs.h
r3447 r3897 66 66 TR_PEERMSG_PEER_PROGRESS, 67 67 TR_PEERMSG_GOT_ERROR, 68 TR_PEERMSG_GOT_ASSERT_ERROR, 68 69 TR_PEERMSG_CANCEL, 69 70 TR_PEERMSG_NEED_REQ … … 88 89 tr_publisher_tag tag ); 89 90 90 int tr_peerMsgIsPieceFastAllowed( const tr_peermsgs * peer, 91 uint32_t index ); 91 int tr_peerMsgsIsPieceFastAllowed( const tr_peermsgs * peer, 92 uint32_t index ); 93 94 int tr_peerMsgsIsPieceSuggested( const tr_peermsgs * peer, 95 uint32_t index ); 92 96 93 97 #endif -
branches/0.9x/libtransmission/platform.c
r3553 r3897 232 232 } 233 233 234 int235 tr_lockTryLock( tr_lock * l ) /* success on zero! */236 {237 #ifdef __BEOS__238 return acquire_sem_etc( l->lock, 1, B_RELATIVE_TIMEOUT, 0 );239 #elif defined(WIN32)240 return !TryEnterCriticalSection( &l->lock );241 #else242 return pthread_mutex_trylock( &l->lock );243 #endif244 }245 246 234 void 247 235 tr_lockLock( tr_lock * l ) 248 236 { 249 tr_thread_id currentThread = tr_getCurrentThread( ); 237 const tr_thread_id currentThread = tr_getCurrentThread( ); 238 250 239 if( l->lockThread == currentThread ) 251 240 { … … 261 250 pthread_mutex_lock( &l->lock ); 262 251 #endif 263 l->lockThread = tr_getCurrentThread( );252 l->lockThread = currentThread; 264 253 l->depth = 1; 265 254 } -
branches/0.9x/libtransmission/platform.h
r3254 r3897 39 39 tr_lock * tr_lockNew ( void ); 40 40 void tr_lockFree ( tr_lock * ); 41 int tr_lockTryLock ( tr_lock * );42 41 void tr_lockLock ( tr_lock * ); 43 42 void tr_lockUnlock ( tr_lock * ); -
branches/0.9x/libtransmission/torrent.c
r3649 r3897 881 881 882 882 void 883 tr_torrentPeersFree( tr_peer_stat * peers, int peerCount ) 884 { 885 int i; 886 for( i=0; i<peerCount; ++i ) 887 tr_free( (char*) peers[i].client ); 883 tr_torrentPeersFree( tr_peer_stat * peers, int peerCount UNUSED ) 884 { 888 885 tr_free( peers ); 889 886 } … … 1006 1003 1007 1004 static void 1008 checkAndStartCB( tr_torrent * tor ) 1009 { 1005 checkAndStartImpl( void * vtor ) 1006 { 1007 tr_torrent * tor = vtor; 1008 1010 1009 tr_globalLock( tor->handle ); 1011 1010 … … 1021 1020 tr_globalUnlock( tor->handle ); 1022 1021 } 1023 1022 1023 static void 1024 checkAndStartCB( tr_torrent * tor ) 1025 { 1026 tr_runInEventThread( tor->handle, checkAndStartImpl, tor ); 1027 } 1028 1024 1029 void 1025 1030 tr_torrentStart( tr_torrent * tor ) … … 1039 1044 } 1040 1045 1046 static void 1047 torrentRecheckDoneImpl( void * vtor ) 1048 { 1049 tr_torrentRecheckCompleteness( vtor ); 1050 } 1051 static void 1052 torrentRecheckDoneCB( tr_torrent * tor ) 1053 { 1054 tr_runInEventThread( tor->handle, torrentRecheckDoneImpl, tor ); 1055 } 1041 1056 void 1042 1057 tr_torrentRecheck( tr_torrent * tor ) … … 1048 1063 tr_bitfieldAddRange( tor->uncheckedPieces, 0, tor->info.pieceCount ); 1049 1064 1050 tr_ioRecheckAdd( tor, t r_torrentRecheckCompleteness);1065 tr_ioRecheckAdd( tor, torrentRecheckDoneCB ); 1051 1066 1052 1067 tr_globalUnlock( tor->handle ); … … 1090 1105 tr_globalLock( tor->handle ); 1091 1106 1107 tr_torrentClearStatusCallback( tor ); 1092 1108 tr_runInEventThread( tor->handle, closeTorrent, tor ); 1093 1109 -
branches/0.9x/libtransmission/transmission.c
r3711 r3897 91 91 { 92 92 assert( handle != NULL ); 93 assert( mode==TR_ENCRYPTION_PREFERRED || mode==TR_ENCRYPTION_REQUIRED ); 93 assert( mode==TR_ENCRYPTION_PREFERRED 94 || mode==TR_ENCRYPTION_REQUIRED 95 || mode==TR_PLAINTEXT_PREFERRED ); 94 96 95 97 handle->encryptionMode = mode; … … 109 111 { 110 112 tr_handle * h; 111 int i;112 113 113 114 #ifndef WIN32 … … 139 140 140 141 h->peerMgr = tr_peerMgrNew( h ); 141 142 /* Azureus identity */143 for( i=0; i < TR_AZ_ID_LEN; ++i )144 h->azId[i] = tr_rand( 0xff );145 142 146 143 /* Initialize rate and file descripts controls */ … … 299 296 { 300 297 tr_handle * h = vh; 298 tr_torrent * t; 299 300 for( t=h->torrentList; t!=NULL; t=t->next ) 301 tr_torrentClose( t ); 302 301 303 tr_peerMgrFree( h->peerMgr ); 302 304 303 305 tr_rcClose( h->upload ); 304 306 tr_rcClose( h->download ); 307 308 tr_natTraversalEnable( h, 0 ); 309 while( tr_handleStatus( h )->natTraversalStatus != TR_NAT_TRAVERSAL_DISABLED ) 310 tr_wait( 100 ); 305 311 306 312 tr_sharedClose( h->shared ); … … 333 339 free( h->tag ); 334 340 free( h ); 341 } 342 343 void 344 tr_getSessionStats( const tr_handle * handle, 345 tr_session_stats * setme ) 346 { 347 assert( handle != NULL ); 348 assert( setme != NULL ); 349 350 /* FIXME */ 351 setme->downloadedGigs = 4; 352 setme->downloadedBytes = 8; 353 setme->uploadedGigs = 15; 354 setme->uploadedBytes = 16; 355 setme->ratio = 23; 356 setme->filesAdded = 42; 357 setme->sessionCount = 666; 358 setme->secondsActive = 2112; 359 } 360 361 void 362 tr_getCumulativeSessionStats( const tr_handle * handle, 363 tr_session_stats * setme ) 364 { 365 tr_getSessionStats( handle, setme ); 335 366 } 336 367 -
branches/0.9x/libtransmission/transmission.h
r3665 r3897 97 97 * tr_init 98 98 *********************************************************************** 99 * Initializes a libtransmission instance . Returns a obscure handle to100 * be passed to allfunctions below. The tag argument is a short string99 * Initializes a libtransmission instance and returns an opaque handle 100 * to be passed to functions below. The tag argument is a short string 101 101 * unique to the program invoking tr_init(), it is currently used as 102 102 * part of saved torrent files' names to prevent one frontend from … … 109 109 tr_handle * tr_init( const char * tag ); 110 110 111 typedef struct tr_tracker_info tr_tracker_info; 111 /* shut down a libtransmission instance created by tr_init(). */ 112 void tr_close( tr_handle * ); 113 112 114 113 115 /** … … 115 117 **/ 116 118 119 typedef struct tr_session_stats 120 { 121 uint64_t downloadedGigs; /* total down / GiB */ 122 uint64_t downloadedBytes; /* total down % GiB */ 123 uint64_t uploadedGigs; /* total up / GiB */ 124 uint64_t uploadedBytes; /* total up % GiB */ 125 double ratio; /* total up / total down */ 126 uint64_t filesAdded; /* number of files added */ 127 uint64_t sessionCount; /* program started N times */ 128 uint64_t secondsActive; /* how long Transmisson's been running */ 129 } 130 tr_session_stats; 131 132 /* stats from the current and past sessions. */ 133 void tr_getCumulativeSessionStats( const tr_handle * handle, 134 tr_session_stats * setme ); 135 136 /* stats from the current session. */ 137 void tr_getSessionStats( const tr_handle * handle, 138 tr_session_stats * setme ); 139 140 141 /** 142 *** 143 **/ 144 117 145 typedef enum 118 146 { 147 TR_PLAINTEXT_PREFERRED, 119 148 TR_ENCRYPTION_PREFERRED, 120 149 TR_ENCRYPTION_REQUIRED … … 291 320 **********************************************************************/ 292 321 void tr_torrentRates( tr_handle *, float *, float * ); 293 294 /***********************************************************************295 * tr_close296 ***********************************************************************297 * Frees memory allocated by tr_init.298 **********************************************************************/299 void tr_close( tr_handle * );300 322 301 323 … … 411 433 const tr_info * tr_torrentInfo( const tr_torrent * ); 412 434 413 #if 0414 /***********************************************************************415 * tr_torrentScrape416 ***********************************************************************417 * Asks the tracker for the count of seeders and leechers. Returns 0418 * and fills 's' and 'l' if successful. Otherwise returns 1 if the419 * tracker doesn't support the scrape protocol, is unreachable or420 * replied with some error. tr_torrentScrape may block up to 20 seconds421 * before returning.422 **********************************************************************/423 int tr_torrentScrape( tr_torrent *, int * s, int * l, int * d );424 #endif425 426 435 void tr_torrentSetFolder( tr_torrent *, const char * ); 427 436 const char * tr_torrentGetFolder( const tr_torrent * ); … … 567 576 tr_piece; 568 577 578 typedef struct tr_tracker_info 579 { 580 char * address; 581 int port; 582 char * announce; 583 char * scrape; 584 } 585 tr_tracker_info; 586 569 587 struct tr_info 570 588 { … … 696 714 }; 697 715 716 typedef enum 717 { 718 TR_PEER_STATUS_HANDSHAKE, 719 TR_PEER_STATUS_PEER_IS_CHOKED, 720 TR_PEER_STATUS_CLIENT_IS_CHOKED, 721 TR_PEER_STATUS_CLIENT_IS_INTERESTED, 722 TR_PEER_STATUS_READY, 723 TR_PEER_STATUS_ACTIVE_AND_CHOKED, 724 TR_PEER_STATUS_REQUEST_SENT, 725 TR_PEER_STATUS_ACTIVE 726 } 727 tr_peer_status; 728 698 729 struct tr_peer_stat 699 730 { 700 char 701 c onst char * client;731 char addr[INET_ADDRSTRLEN]; 732 char client[80]; 702 733 703 734 unsigned int isEncrypted : 1; 704 735 unsigned int isDownloading : 1; 705 736 unsigned int isUploading : 1; 737 738 tr_peer_status status; 706 739 707 740 uint8_t from; … … 719 752 char * message; 720 753 struct tr_msg_list * next; 721 };722 723 struct tr_tracker_info724 {725 char * address;726 int port;727 char * announce;728 char * scrape;729 754 }; 730 755 -
branches/0.9x/libtransmission/trevent.c
r3797 r3897 65 65 { 66 66 TR_EV_EVHTTP_MAKE_REQUEST, 67 TR_EV_BUFFEREVENT_SET,68 TR_EV_BUFFEREVENT_WRITE,69 67 TR_EV_TIMER_ADD, 70 TR_EV_TIMER_DEL,71 68 TR_EV_EXEC 72 69 }; … … 134 131 break; 135 132 136 case TR_EV_TIMER_DEL:137 event_del( &cmd->timer->event );138 tr_free( cmd->timer );139 --eh->timerCount;140 break;141 142 133 case TR_EV_EVHTTP_MAKE_REQUEST: 143 134 evhttp_make_request( cmd->evcon, cmd->req, cmd->evtype, cmd->uri ); 144 135 tr_free( cmd->uri ); 145 break;146 147 case TR_EV_BUFFEREVENT_SET:148 bufferevent_enable( cmd->bufev, cmd->enable );149 bufferevent_disable( cmd->bufev, cmd->disable );150 break;151 152 case TR_EV_BUFFEREVENT_WRITE:153 bufferevent_write( cmd->bufev, cmd->buf, cmd->buflen );154 tr_free( cmd->buf );155 136 break; 156 137 … … 255 236 tr_lockUnlock( eh->lock ); 256 237 } 238 239 int 240 tr_amInEventThread( struct tr_handle * handle ) 241 { 242 return tr_amInThread( handle->events->thread ); 243 } 244 257 245 258 246 void … … 277 265 } 278 266 279 void280 tr_bufferevent_write( tr_handle * handle,281 struct bufferevent * bufev,282 const void * buf,283 size_t buflen )284 {285 if( tr_amInThread( handle->events->thread ) )286 bufferevent_write( bufev, (void*)buf, buflen );287 else {288 struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 );289 cmd->mode = TR_EV_BUFFEREVENT_WRITE;290 cmd->bufev = bufev;291 cmd->buf = tr_strndup( buf, buflen );292 cmd->buflen = buflen;293 pushList( handle->events, cmd );294 }295 }296 297 void298 tr_setBufferEventMode( struct tr_handle * handle,299 struct bufferevent * bufev,300 short mode_enable,301 short mode_disable )302 {303 if( tr_amInThread( handle->events->thread ) ) {304 bufferevent_enable( bufev, mode_enable );305 bufferevent_disable( bufev, mode_disable );306 } else {307 struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 );308 cmd->mode = TR_EV_BUFFEREVENT_SET;309 cmd->bufev = bufev;310 cmd->enable = mode_enable;311 cmd->disable = mode_disable;312 pushList( handle->events, cmd );313 }314 }315 316 267 /** 317 268 *** … … 363 314 /* destroy the timer directly or via the command queue */ 364 315 if( timer!=NULL && !timer->inCallback ) { 365 if( tr_amInThread( timer->eh->thread ) ) { 366 void * del = tr_list_remove( &timer->eh->commands, timer, timerCompareFunc ); 367 --timer->eh->timerCount; 368 event_del( &timer->event ); 369 tr_free( timer ); 370 tr_free( del ); 371 } else { 372 struct tr_event_command * cmd = tr_new0( struct tr_event_command, 1 ); 373 cmd->mode = TR_EV_TIMER_DEL; 374 cmd->timer = timer; 375 pushList( timer->eh, cmd ); 376 } 316 void * del; 317 assert( tr_amInEventThread( timer->eh->h ) ); 318 del = tr_list_remove( &timer->eh->commands, timer, timerCompareFunc ); 319 --timer->eh->timerCount; 320 event_del( &timer->event ); 321 tr_free( timer ); 322 tr_free( del ); 377 323 } 378 324 } -
branches/0.9x/libtransmission/trevent.h
r3457 r3897 38 38 char * uri); 39 39 40 void tr_bufferevent_write( struct tr_handle * tr_handle,41 struct bufferevent * bufferEvent,42 const void * buf,43 size_t buflen );44 45 46 void tr_setBufferEventMode( struct tr_handle * tr_handle,47 struct bufferevent * bufferEvent,48 short mode_enable,49 short mode_disable );50 51 40 /** 52 41 *** … … 70 59 void tr_timerFree( tr_timer ** timer ); 71 60 61 62 int tr_amInEventThread( struct tr_handle * handle ); 63 72 64 void tr_runInEventThread( struct tr_handle * handle, 73 65 void func( void* ), -
branches/0.9x/libtransmission/utils.c
r3665 r3897 893 893 #endif 894 894 } 895 896 /*** 897 **** 898 ***/ 899 900 901 #ifndef HAVE_STRLCPY 902 903 /* 904 * Copy src to string dst of size siz. At most siz-1 characters 905 * will be copied. Always NUL terminates (unless siz == 0). 906 * Returns strlen(src); if retval >= siz, truncation occurred. 907 */ 908 size_t 909 strlcpy(char *dst, const char *src, size_t siz) 910 { 911 char *d = dst; 912 const char *s = src; 913 size_t n = siz; 914 915 /* Copy as many bytes as will fit */ 916 if (n != 0) { 917 while (--n != 0) { 918 if ((*d++ = *s++) == '\0') 919 break; 920 } 921 } 922 923 /* Not enough room in dst, add NUL and traverse rest of src */ 924 if (n == 0) { 925 if (siz != 0) 926 *d = '\0'; /* NUL-terminate dst */ 927 while (*s++) 928 ; 929 } 930 931 return(s - src - 1); /* count does not include NUL */ 932 } 933 934 #endif /* HAVE_STRLCPY */ 935 936 937 #ifndef HAVE_STRLCAT 938 939 /* 940 * Appends src to string dst of size siz (unlike strncat, siz is the 941 * full size of dst, not space left). At most siz-1 characters 942 * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 943 * Returns strlen(src) + MIN(siz, strlen(initial dst)). 944 * If retval >= siz, truncation occurred. 945 */ 946 size_t 947 strlcat(char *dst, const char *src, size_t siz) 948 { 949 char *d = dst; 950 const char *s = src; 951 size_t n = siz; 952 size_t dlen; 953 954 /* Find the end of dst and adjust bytes left but don't go past end */ 955 while (n-- != 0 && *d != '\0') 956 d++; 957 dlen = d - dst; 958 n = siz - dlen; 959 960 if (n == 0) 961 return(dlen + strlen(s)); 962 while (*s != '\0') { 963 if (n != 1) { 964 *d++ = *s; 965 n--; 966 } 967 s++; 968 } 969 *d = '\0'; 970 971 return(dlen + (s - src)); /* count does not include NUL */ 972 } 973 974 #endif /* HAVE_STRLCAT */
Note: See TracChangeset
for help on using the changeset viewer.