539
assertValidPiece( Torrent * t, tr_piece_index_t piece )
543
assert( piece < t->tor->info.pieceCount );
547
getPieceRequests( Torrent * t, tr_piece_index_t piece )
549
assertValidPiece( t, piece );
551
return t->pendingRequestCount ? t->pendingRequestCount[piece] : 0;
555
incrementPieceRequests( Torrent * t, tr_piece_index_t piece )
557
assertValidPiece( t, piece );
559
if( t->pendingRequestCount == NULL )
560
t->pendingRequestCount = tr_new0( int, t->tor->info.pieceCount );
561
t->pendingRequestCount[piece]++;
565
decrementPieceRequests( Torrent * t, tr_piece_index_t piece )
567
assertValidPiece( t, piece );
569
if( t->pendingRequestCount )
570
t->pendingRequestCount[piece]--;
573
struct tr_refill_piece
575
tr_priority_t priority;
579
int pendingRequestCount;
580
int missingBlockCount;
584
compareRefillPiece( const void * aIn, const void * bIn )
586
const struct tr_refill_piece * a = aIn;
587
const struct tr_refill_piece * b = bIn;
589
/* if one piece has a higher priority, it goes first */
590
if( a->priority != b->priority )
591
return a->priority > b->priority ? -1 : 1;
593
/* have a per-priority endgame */
594
if( a->pendingRequestCount != b->pendingRequestCount )
595
return a->pendingRequestCount < b->pendingRequestCount ? -1 : 1;
597
/* fewer missing pieces goes first */
598
if( a->missingBlockCount != b->missingBlockCount )
599
return a->missingBlockCount < b->missingBlockCount ? -1 : 1;
601
/* otherwise if one has fewer peers, it goes first */
602
if( a->peerCount != b->peerCount )
603
return a->peerCount < b->peerCount ? -1 : 1;
605
/* otherwise go with our random seed */
606
if( a->random != b->random )
607
return a->random < b->random ? -1 : 1;
612
static tr_piece_index_t *
613
getPreferredPieces( Torrent * t, tr_piece_index_t * pieceCount )
615
const tr_torrent * tor = t->tor;
616
const tr_info * inf = &tor->info;
618
tr_piece_index_t poolSize = 0;
619
tr_piece_index_t * pool = tr_new( tr_piece_index_t , inf->pieceCount );
621
const tr_peer ** peers;
623
assert( torrentIsLocked( t ) );
625
peers = (const tr_peer**) tr_ptrArrayBase( &t->peers );
626
peerCount = tr_ptrArraySize( &t->peers );
628
/* make a list of the pieces that we want but don't have */
629
for( i = 0; i < inf->pieceCount; ++i )
630
if( !tor->info.pieces[i].dnd
631
&& !tr_cpPieceIsComplete( &tor->completion, i ) )
632
pool[poolSize++] = i;
634
/* sort the pool by which to request next */
638
struct tr_refill_piece * p = tr_new( struct tr_refill_piece, poolSize );
640
for( j = 0; j < poolSize; ++j )
643
const tr_piece_index_t piece = pool[j];
644
struct tr_refill_piece * setme = p + j;
646
setme->piece = piece;
647
setme->priority = inf->pieces[piece].priority;
648
setme->peerCount = 0;
649
setme->random = tr_cryptoWeakRandInt( INT_MAX );
650
setme->pendingRequestCount = getPieceRequests( t, piece );
651
setme->missingBlockCount
652
= tr_cpMissingBlocksInPiece( &tor->completion, piece );
654
for( k = 0; k < peerCount; ++k )
543
*** There are two data structures associated with managing block requests:
545
*** 1. Torrent::requests, an array of "struct block_request" which keeps
546
*** track of which blocks have been requested, and when, and by which peers.
547
*** This is list is used for (a) cancelling requests that have been pending
548
*** for too long and (b) avoiding duplicate requests before endgame.
550
*** 2. Torrent::pieces, an array of "struct weighted_piece" which lists the
551
*** pieces that we want to request. It's used to decide which pieces to
552
*** return next when tr_peerMgrGetBlockRequests() is called.
556
*** struct block_request
567
compareReqByBlock( const void * va, const void * vb )
569
const struct block_request * a = va;
570
const struct block_request * b = vb;
571
if( a->block < b->block ) return -1;
572
if( a->block > b->block ) return 1;
577
compareReqByTime( const void * va, const void * vb )
579
const struct block_request * a = va;
580
const struct block_request * b = vb;
581
if( a->sentAt < b->sentAt ) return -1;
582
if( a->sentAt > b->sentAt ) return 1;
587
requestListSort( Torrent * t, int mode )
589
assert( mode==REQ_SORTED_BY_BLOCK || mode==REQ_SORTED_BY_TIME );
591
if( t->requestsSort != mode )
593
int(*compar)(const void *, const void *);
595
t->requestsSort = mode;
598
case REQ_SORTED_BY_BLOCK: compar = compareReqByBlock; break;
599
case REQ_SORTED_BY_TIME: compar = compareReqByTime; break;
600
default: assert( 0 && "unhandled" );
603
qsort( t->requests, t->requestCount,
604
sizeof( struct block_request ), compar );
609
requestListAdd( Torrent * t, const time_t now, tr_block_index_t block, tr_peer * peer )
611
struct block_request key;
613
/* ensure enough room is available... */
614
if( t->requestCount + 1 >= t->requestAlloc )
616
const int CHUNK_SIZE = 128;
617
t->requestAlloc += CHUNK_SIZE;
618
t->requests = tr_renew( struct block_request,
619
t->requests, t->requestAlloc );
622
/* populate the record we're inserting */
627
/* insert the request to our array... */
628
switch( t->requestsSort )
631
case REQ_SORTED_BY_TIME:
632
t->requests[t->requestCount++] = key;
635
case REQ_SORTED_BY_BLOCK: {
637
const int pos = tr_lowerBound( &key, t->requests, t->requestCount,
638
sizeof( struct block_request ),
639
compareReqByBlock, &exact );
641
memmove( t->requests + pos + 1,
643
sizeof( struct block_request ) * ( t->requestCount++ - pos ) );
644
t->requests[pos] = key;
650
static struct block_request *
651
requestListLookup( Torrent * t, tr_block_index_t block )
653
struct block_request key;
656
requestListSort( t, REQ_SORTED_BY_BLOCK );
658
return bsearch( &key, t->requests, t->requestCount,
659
sizeof( struct block_request ),
664
requestListRemove( Torrent * t, tr_block_index_t block )
666
const struct block_request * b = requestListLookup( t, block );
669
const int pos = b - t->requests;
670
assert( pos < t->requestCount );
671
memmove( t->requests + pos,
672
t->requests + pos + 1,
673
sizeof( struct block_request ) * ( --t->requestCount - pos ) );
678
*** struct weighted_piece
684
PIECES_SORTED_BY_INDEX,
685
PIECES_SORTED_BY_WEIGHT
688
const tr_torrent * weightTorrent;
690
/* we try to create a "weight" s.t. high-priority pieces come before others,
691
* and that partially-complete pieces come before empty ones. */
693
comparePieceByWeight( const void * va, const void * vb )
695
const struct weighted_piece * a = va;
696
const struct weighted_piece * b = vb;
697
int ia, ib, missing, pending;
698
const tr_torrent * tor = weightTorrent;
700
/* primary key: weight */
701
missing = tr_cpMissingBlocksInPiece( &tor->completion, a->index );
702
pending = a->requestCount;
703
ia = missing > pending ? missing - pending : (int)(tor->blockCountInPiece + pending);
704
missing = tr_cpMissingBlocksInPiece( &tor->completion, b->index );
705
pending = b->requestCount;
706
ib = missing > pending ? missing - pending : (int)(tor->blockCountInPiece + pending);
707
if( ia < ib ) return -1;
708
if( ia > ib ) return 1;
710
/* secondary key: higher priorities go first */
711
ia = tor->info.pieces[a->index].priority;
712
ib = tor->info.pieces[b->index].priority;
713
if( ia > ib ) return -1;
714
if( ia < ib ) return 1;
716
/* tertiary key: random */
717
return a->salt - b->salt;
721
comparePieceByIndex( const void * va, const void * vb )
723
const struct weighted_piece * a = va;
724
const struct weighted_piece * b = vb;
725
if( a->index < b->index ) return -1;
726
if( a->index > b->index ) return 1;
731
pieceListSort( Torrent * t, int mode )
733
int(*compar)(const void *, const void *);
735
assert( mode==PIECES_SORTED_BY_INDEX
736
|| mode==PIECES_SORTED_BY_WEIGHT );
738
if( t->piecesSort != mode )
740
t->piecesSort = mode;
743
case PIECES_SORTED_BY_WEIGHT: compar = comparePieceByWeight; break;
744
case PIECES_SORTED_BY_INDEX: compar = comparePieceByIndex; break;
745
default: assert( 0 && "unhandled" ); break;
748
weightTorrent = t->tor;
749
qsort( t->pieces, t->pieceCount,
750
sizeof( struct weighted_piece ), compar );
753
/* Also, as long as we've got the pieces sorted by weight,
754
* let's also update t.isInEndgame */
755
if( t->piecesSort == PIECES_SORTED_BY_WEIGHT )
757
tr_bool endgame = TRUE;
759
if( ( t->pieces != NULL ) && ( t->pieceCount > 0 ) )
761
const tr_completion * cp = &t->tor->completion;
762
const struct weighted_piece * p = t->pieces;
763
const int pending = p->requestCount;
764
const int missing = tr_cpMissingBlocksInPiece( cp, p->index );
765
endgame = pending >= missing;
768
t->isInEndgame = endgame;
772
static struct weighted_piece *
773
pieceListLookup( Torrent * t, tr_piece_index_t index )
775
struct weighted_piece key;
778
pieceListSort( t, PIECES_SORTED_BY_INDEX );
780
return bsearch( &key, t->pieces, t->pieceCount,
781
sizeof( struct weighted_piece ),
782
comparePieceByIndex );
786
pieceListRebuild( Torrent * t )
788
if( !tr_torrentIsSeed( t->tor ) )
791
tr_piece_index_t * pool;
792
tr_piece_index_t poolCount = 0;
793
const tr_torrent * tor = t->tor;
794
const tr_info * inf = tr_torrentInfo( tor );
795
struct weighted_piece * pieces;
798
/* build the new list */
799
pool = tr_new( tr_piece_index_t, inf->pieceCount );
800
for( i=0; i<inf->pieceCount; ++i )
801
if( !inf->pieces[i].dnd )
802
if( !tr_cpPieceIsComplete( &tor->completion, i ) )
803
pool[poolCount++] = i;
804
pieceCount = poolCount;
805
pieces = tr_new0( struct weighted_piece, pieceCount );
806
for( i=0; i<poolCount; ++i ) {
807
struct weighted_piece * piece = pieces + i;
808
piece->index = pool[i];
809
piece->requestCount = 0;
810
piece->salt = tr_cryptoWeakRandInt( 255 );
813
/* if we already had a list of pieces, merge it into
814
* the new list so we don't lose its requestCounts */
815
if( t->pieces != NULL )
817
struct weighted_piece * o = t->pieces;
818
struct weighted_piece * oend = o + t->pieceCount;
819
struct weighted_piece * n = pieces;
820
struct weighted_piece * nend = n + pieceCount;
822
pieceListSort( t, PIECES_SORTED_BY_INDEX );
824
while( o!=oend && n!=nend ) {
825
if( o->index < n->index )
827
else if( o->index > n->index )
833
tr_free( t->pieces );
837
t->pieceCount = pieceCount;
838
t->piecesSort = PIECES_SORTED_BY_INDEX;
846
pieceListRemovePiece( Torrent * t, tr_piece_index_t piece )
848
struct weighted_piece * p = pieceListLookup( t, piece );
852
const int pos = p - t->pieces;
854
memmove( t->pieces + pos,
856
sizeof( struct weighted_piece ) * ( --t->pieceCount - pos ) );
858
if( t->pieceCount == 0 )
860
tr_free( t->pieces );
867
pieceListRemoveRequest( Torrent * t, tr_block_index_t block )
869
struct weighted_piece * p;
870
const tr_piece_index_t index = tr_torBlockPiece( t->tor, block );
872
if(( p = pieceListLookup( t, index )))
873
if( p->requestCount > 0 )
876
/* note: this invalidates the weighted.piece.weight field,
877
* but that's OK since the call to pieceListLookup ensured
878
* that we were sorted by index anyway.. next time we resort
879
* by weight, pieceListSort() will update the weights */
887
tr_peerMgrRebuildRequests( tr_torrent * tor )
889
assert( tr_isTorrent( tor ) );
891
pieceListRebuild( tor->torrentPeers );
895
tr_peerMgrGetNextRequests( tr_torrent * tor,
898
tr_block_index_t * setme,
904
struct weighted_piece * pieces;
905
const tr_bitset * have = &peer->have;
906
const time_t now = tr_time( );
909
assert( tr_isTorrent( tor ) );
910
assert( numwant > 0 );
912
/* walk through the pieces and find blocks that should be requested */
914
t = tor->torrentPeers;
916
/* prep the pieces list */
917
if( t->pieces == NULL )
918
pieceListRebuild( t );
919
pieceListSort( t, PIECES_SORTED_BY_WEIGHT );
922
for( i=0; i<t->pieceCount && got<numwant; ++i )
924
struct weighted_piece * p = pieces + i;
926
/* if the peer has this piece that we want... */
927
if( tr_bitsetHasFast( have, p->index ) )
929
tr_block_index_t b = tr_torPieceFirstBlock( tor, p->index );
930
const tr_block_index_t e = b + tr_torPieceCountBlocks( tor, p->index );
932
for( ; b!=e && got<numwant; ++b )
656
const tr_peer * peer = peers[k];
657
if( peer->peerIsInterested
658
&& !peer->clientIsChoked
659
&& tr_bitfieldHas( peer->have, piece ) )
934
struct block_request * breq;
936
/* don't request blocks we've already got */
937
if( tr_cpBlockIsCompleteFast( &tor->completion, b ) )
940
/* don't request blocks we've already requested (FIXME) */
941
breq = requestListLookup( t, b );
943
assert( breq->peer != NULL );
944
if( breq->peer == peer ) continue;
945
if( !t->isInEndgame ) continue;
950
/* update our own tables */
952
requestListAdd( t, now, b, peer );
664
qsort( p, poolSize, sizeof( struct tr_refill_piece ),
665
compareRefillPiece );
667
for( j = 0; j < poolSize; ++j )
668
pool[j] = p[j].piece;
673
*pieceCount = poolSize;
677
static struct tr_blockIterator*
678
blockIteratorNew( Torrent * t )
680
struct tr_blockIterator * i = tr_new0( struct tr_blockIterator, 1 );
681
i->expirationDate = time( NULL ) + PIECE_LIST_SHELF_LIFE_SECS;
683
i->pieces = getPreferredPieces( t, &i->pieceCount );
684
i->blocks = tr_new0( tr_block_index_t, t->tor->blockCountInPiece );
685
tordbg( t, "creating new refill queue.. it contains %"PRIu32" pieces", i->pieceCount );
690
blockIteratorNext( struct tr_blockIterator * i, tr_block_index_t * setme )
694
tr_torrent * tor = t->tor;
696
while( ( i->blockIndex == i->blockCount )
697
&& ( i->pieceIndex < i->pieceCount ) )
699
const tr_piece_index_t index = i->pieces[i->pieceIndex++];
700
const tr_block_index_t b = tr_torPieceFirstBlock( tor, index );
701
const tr_block_index_t e = b + tr_torPieceCountBlocks( tor, index );
702
tr_block_index_t block;
704
assert( index < tor->info.pieceCount );
708
for( block=b; block!=e; ++block )
709
if( !tr_cpBlockIsCompleteFast( &tor->completion, block ) )
710
i->blocks[i->blockCount++] = block;
713
assert( i->blockCount <= tor->blockCountInPiece );
715
if(( found = ( i->blockIndex < i->blockCount )))
716
*setme = i->blocks[i->blockIndex++];
722
blockIteratorSkipCurrentPiece( struct tr_blockIterator * i )
724
i->blockIndex = i->blockCount;
728
blockIteratorFree( struct tr_blockIterator ** inout )
730
struct tr_blockIterator * it = *inout;
734
tr_free( it->blocks );
735
tr_free( it->pieces );
743
getPeersUploadingToClient( Torrent * t,
749
tr_peer ** peers = (tr_peer **) tr_ptrArrayPeek( &t->peers, &peerCount );
750
tr_peer ** ret = tr_new( tr_peer *, peerCount );
752
j = 0; /* this is a temporary test to make sure we walk through all the peers */
755
/* Get a list of peers we're downloading from.
756
Pick a different starting point each time so all peers
757
get a chance at being the first in line */
758
const int fencepost = tr_cryptoWeakRandInt( peerCount );
761
if( clientIsDownloadingFrom( peers[i] ) )
762
ret[retCount++] = peers[i];
763
i = ( i + 1 ) % peerCount;
765
} while( i != fencepost );
767
assert( j == peerCount );
768
*setmeCount = retCount;
773
getBlockOffsetInPiece( const tr_torrent * tor, uint64_t b )
775
const uint64_t piecePos = tor->info.pieceSize * tr_torBlockPiece( tor, b );
776
const uint64_t blockPos = tor->blockSize * b;
777
assert( blockPos >= piecePos );
778
return (uint32_t)( blockPos - piecePos );
958
/* In most cases we've just changed the weights of a small number of pieces.
959
* So rather than qsort()ing the entire array, it's faster to sort just the
960
* changed ones, then do a standard merge-two-sorted-arrays pass on the
961
* changed and unchanged pieces. */
964
struct weighted_piece * p;
965
struct weighted_piece * pieces;
966
struct weighted_piece * a = t->pieces;
967
struct weighted_piece * a_end = t->pieces + i;
968
struct weighted_piece * b = a_end;
969
struct weighted_piece * b_end = t->pieces + t->pieceCount;
971
/* resort the pieces that we changed */
972
weightTorrent = t->tor;
973
qsort( a, a_end-a, sizeof( struct weighted_piece ), comparePieceByWeight );
975
/* allocate a new array */
976
p = pieces = tr_new( struct weighted_piece, t->pieceCount );
978
/* merge the two sorted arrays into this new array */
979
weightTorrent = t->tor;
980
while( a!=a_end && b!=b_end )
981
*p++ = comparePieceByWeight( a, b ) < 0 ? *a++ : *b++;
982
while( a!=a_end ) *p++ = *a++;
983
while( b!=b_end ) *p++ = *b++;
986
/* make sure we did it right */
987
assert( p - pieces == t->pieceCount );
988
for( it=pieces; it+1<p; ++it )
989
assert( it->weight <= it[1].weight );
993
tr_free( t->pieces );
1001
tr_peerMgrDidPeerRequest( const tr_torrent * tor,
1002
const tr_peer * peer,
1003
tr_block_index_t block )
1005
const Torrent * t = tor->torrentPeers;
1006
const struct block_request * b = requestListLookup( (Torrent*)t, block );
1007
if( b == NULL ) return FALSE;
1008
if( b->peer == peer ) return TRUE;
1009
if( t->isInEndgame ) return TRUE;
1013
/* cancel requests that are too old */
782
1015
refillUpkeep( void * vmgr )
784
tr_torrent * tor = NULL;
785
tr_peerMgr * mgr = vmgr;
1020
tr_peerMgr * mgr = vmgr;
787
1021
managerLock( mgr );
790
while(( tor = tr_torrentNext( mgr->session, tor ))) {
1024
too_old = now - REQUEST_TTL_SECS;
1027
while(( tor = tr_torrentNext( mgr->session, tor )))
791
1029
Torrent * t = tor->torrentPeers;
792
if( t && t->refillQueue && ( t->refillQueue->expirationDate <= now ) ) {
793
tordbg( t, "refill queue is past its shelf date; discarding." );
794
blockIteratorFree( &t->refillQueue );
1030
const int n = t->requestCount;
1034
int cancelCount = 0;
1035
struct block_request * keep = tr_new( struct block_request, n );
1036
struct block_request * cancel = tr_new( struct block_request, n );
1037
const struct block_request * it;
1038
const struct block_request * end;
1040
for( it=t->requests, end=it+n; it!=end; ++it )
1041
if( it->sentAt <= too_old )
1042
cancel[cancelCount++] = *it;
1044
keep[keepCount++] = *it;
1046
/* prune out the ones we aren't keeping */
1047
tr_free( t->requests );
1049
t->requestCount = keepCount;
1050
t->requestAlloc = n;
1052
/* send cancel messages for all the "cancel" ones */
1053
for( it=cancel, end=it+cancelCount; it!=end; ++it )
1054
if( ( it->peer != NULL ) && ( it->peer->msgs != NULL ) )
1055
tr_peerMsgsCancel( it->peer->msgs, it->block );
1057
/* decrement the pending request counts for the timed-out blocks */
1058
for( it=cancel, end=it+cancelCount; it!=end; ++it )
1059
pieceListRemoveRequest( t, it->block );
2353
2601
int mustCloseCount;
2355
2602
int maxCandidates;
2356
struct tr_peer ** canClose = getPeersToClose( t, TR_CAN_CLOSE, &canCloseCount );
2357
struct tr_peer ** mustClose = getPeersToClose( t, TR_MUST_CLOSE, &mustCloseCount );
2358
struct peer_atom ** candidates = getPeerCandidates( t, &candidateCount );
2360
tordbg( t, "reconnect pulse for [%s]: "
2361
"%d must-close connections, "
2362
"%d can-close connections, "
2363
"%d connection candidates, "
2365
"max per pulse is %d",
2370
tr_ptrArraySize( &t->pool ),
2371
MAX_RECONNECTIONS_PER_PULSE );
2603
struct tr_peer ** mustClose;
2373
2605
/* disconnect the really bad peers */
2606
mustClose = getPeersToClose( t, TR_MUST_CLOSE, now, &mustCloseCount );
2374
2607
for( i=0; i<mustCloseCount; ++i )
2375
2608
closePeer( t, mustClose[i] );
2609
tr_free( mustClose );
2377
2611
/* decide how many peers can we try to add in this pass */
2378
maxCandidates = candidateCount;
2379
maxCandidates = MIN( maxCandidates, MAX_RECONNECTIONS_PER_PULSE );
2612
maxCandidates = MAX_RECONNECTIONS_PER_PULSE;
2613
if( tr_announcerHasBacklog( t->manager->session->announcer ) )
2380
2615
maxCandidates = MIN( maxCandidates, getMaxPeerCount( t->tor ) - getPeerCount( t ) );
2381
2616
maxCandidates = MIN( maxCandidates, MAX_CONNECTIONS_PER_SECOND - newConnectionsThisSecond );
2383
/* maybe disconnect some lesser peers, if we have candidates to replace them with */
2384
for( i=0; ( i<canCloseCount ) && ( i<maxCandidates ); ++i )
2385
closePeer( t, canClose[i] );
2387
tordbg( t, "candidateCount is %d, MAX_RECONNECTIONS_PER_PULSE is %d,"
2388
" getPeerCount(t) is %d, getMaxPeerCount(t) is %d, "
2389
"newConnectionsThisSecond is %d, MAX_CONNECTIONS_PER_SECOND is %d",
2391
MAX_RECONNECTIONS_PER_PULSE,
2393
getMaxPeerCount( t->tor ),
2394
newConnectionsThisSecond, MAX_CONNECTIONS_PER_SECOND );
2396
/* add some new ones */
2397
for( i=0; i<maxCandidates; ++i )
2399
tr_peerMgr * mgr = t->manager;
2400
struct peer_atom * atom = candidates[i];
2403
tordbg( t, "Starting an OUTGOING connection with %s",
2404
tr_peerIoAddrStr( &atom->addr, atom->port ) );
2406
io = tr_peerIoNewOutgoing( mgr->session, mgr->session->bandwidth, &atom->addr, atom->port, t->tor->info.hash );
2410
tordbg( t, "peerIo not created; marking peer %s as unreachable",
2411
tr_peerIoAddrStr( &atom->addr, atom->port ) );
2412
atom->myflags |= MYFLAG_UNREACHABLE;
2416
tr_handshake * handshake = tr_handshakeNew( io,
2417
mgr->session->encryptionMode,
2421
assert( tr_peerIoGetTorrentHash( io ) );
2423
tr_peerIoUnref( io ); /* balanced by the implicit ref in tr_peerIoNewOutgoing() */
2425
++newConnectionsThisSecond;
2427
tr_ptrArrayInsertSorted( &t->outgoingHandshakes, handshake,
2431
atom->time = time( NULL );
2435
tr_free( candidates );
2436
tr_free( mustClose );
2437
tr_free( canClose );
2618
/* select the best candidates, if they are requested */
2619
if( maxCandidates == 0 )
2621
tordbg( t, "reconnect pulse for [%s]: %d must-close connections, "
2622
"NO connection candidates needed, %d atoms, "
2623
"max per pulse is %d",
2624
t->tor->info.name, mustCloseCount,
2625
tr_ptrArraySize( &t->pool ),
2626
MAX_RECONNECTIONS_PER_PULSE );
2628
tordbg( t, "maxCandidates is %d, MAX_RECONNECTIONS_PER_PULSE is %d, "
2629
"getPeerCount(t) is %d, getMaxPeerCount(t) is %d, "
2630
"newConnectionsThisSecond is %d, MAX_CONNECTIONS_PER_SECOND is %d",
2631
maxCandidates, MAX_RECONNECTIONS_PER_PULSE,
2632
getPeerCount( t ), getMaxPeerCount( t->tor ),
2633
newConnectionsThisSecond, MAX_CONNECTIONS_PER_SECOND );
2637
int canCloseCount = 0;
2639
struct peer_atom ** candidates;
2641
candidates = getPeerCandidates( t, now, &candidateCount );
2642
maxCandidates = MIN( maxCandidates, candidateCount );
2644
/* maybe disconnect some lesser peers, if we have candidates to replace them with */
2645
if( maxCandidates != 0 )
2647
struct tr_peer ** canClose = getPeersToClose( t, TR_CAN_CLOSE, now, &canCloseCount );
2648
for( i=0; ( i<canCloseCount ) && ( i<maxCandidates ); ++i )
2649
closePeer( t, canClose[i] );
2650
tr_free( canClose );
2653
tordbg( t, "reconnect pulse for [%s]: %d must-close connections, "
2654
"%d can-close connections, %d connection candidates, "
2655
"%d atoms, max per pulse is %d",
2656
t->tor->info.name, mustCloseCount,
2657
canCloseCount, candidateCount,
2658
tr_ptrArraySize( &t->pool ), MAX_RECONNECTIONS_PER_PULSE );
2660
tordbg( t, "candidateCount is %d, MAX_RECONNECTIONS_PER_PULSE is %d,"
2661
" getPeerCount(t) is %d, getMaxPeerCount(t) is %d, "
2662
"newConnectionsThisSecond is %d, MAX_CONNECTIONS_PER_SECOND is %d",
2663
candidateCount, MAX_RECONNECTIONS_PER_PULSE,
2664
getPeerCount( t ), getMaxPeerCount( t->tor ),
2665
newConnectionsThisSecond, MAX_CONNECTIONS_PER_SECOND );
2667
/* add some new ones */
2668
for( i=0; i<maxCandidates; ++i )
2670
tr_peerMgr * mgr = t->manager;
2671
struct peer_atom * atom = candidates[i];
2674
tordbg( t, "Starting an OUTGOING connection with %s",
2675
tr_atomAddrStr( atom ) );
2677
io = tr_peerIoNewOutgoing( mgr->session,
2678
mgr->session->bandwidth,
2682
t->tor->completeness == TR_SEED );
2686
tordbg( t, "peerIo not created; marking peer %s as unreachable",
2687
tr_atomAddrStr( atom ) );
2688
atom->myflags |= MYFLAG_UNREACHABLE;
2692
tr_handshake * handshake = tr_handshakeNew( io,
2693
mgr->session->encryptionMode,
2697
assert( tr_peerIoGetTorrentHash( io ) );
2699
tr_peerIoUnref( io ); /* balanced by the implicit ref in tr_peerIoNewOutgoing() */
2701
++newConnectionsThisSecond;
2703
tr_ptrArrayInsertSorted( &t->outgoingHandshakes, handshake,
2709
tr_free( candidates );