Transmission 2.33
[tomato.git] / release / src / router / transmission / libtransmission / peer-mgr.c
blob8057ce92e1af92e7eda70df4e8fcb0c8b2e58d3a
1 /*
2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: peer-mgr.c 12539 2011-07-10 15:24:51Z jordan $
13 #include <assert.h>
14 #include <errno.h> /* error codes ERANGE, ... */
15 #include <limits.h> /* INT_MAX */
16 #include <string.h> /* memcpy, memcmp, strstr */
17 #include <stdlib.h> /* qsort */
19 #include <event2/event.h>
20 #include <libutp/utp.h>
22 #include "transmission.h"
23 #include "announcer.h"
24 #include "bandwidth.h"
25 #include "blocklist.h"
26 #include "cache.h"
27 #include "clients.h"
28 #include "completion.h"
29 #include "crypto.h"
30 #include "handshake.h"
31 #include "net.h"
32 #include "peer-io.h"
33 #include "peer-mgr.h"
34 #include "peer-msgs.h"
35 #include "ptrarray.h"
36 #include "session.h"
37 #include "stats.h" /* tr_statsAddUploaded, tr_statsAddDownloaded */
38 #include "torrent.h"
39 #include "utils.h"
40 #include "webseed.h"
42 enum
44 /* how frequently to cull old atoms */
45 ATOM_PERIOD_MSEC = ( 60 * 1000 ),
47 /* how frequently to change which peers are choked */
48 RECHOKE_PERIOD_MSEC = ( 10 * 1000 ),
50 /* an optimistically unchoked peer is immune from rechoking
51 for this many calls to rechokeUploads(). */
52 OPTIMISTIC_UNCHOKE_MULTIPLIER = 4,
54 /* how frequently to reallocate bandwidth */
55 BANDWIDTH_PERIOD_MSEC = 500,
57 /* how frequently to age out old piece request lists */
58 REFILL_UPKEEP_PERIOD_MSEC = ( 10 * 1000 ),
60 /* how frequently to decide which peers live and die */
61 RECONNECT_PERIOD_MSEC = 500,
63 /* when many peers are available, keep idle ones this long */
64 MIN_UPLOAD_IDLE_SECS = ( 60 ),
66 /* when few peers are available, keep idle ones this long */
67 MAX_UPLOAD_IDLE_SECS = ( 60 * 5 ),
69 /* max number of peers to ask for per second overall.
70 * this throttle is to avoid overloading the router */
71 MAX_CONNECTIONS_PER_SECOND = 12,
73 MAX_CONNECTIONS_PER_PULSE = (int)(MAX_CONNECTIONS_PER_SECOND * (RECONNECT_PERIOD_MSEC/1000.0)),
75 /* number of bad pieces a peer is allowed to send before we ban them */
76 MAX_BAD_PIECES_PER_PEER = 5,
78 /* amount of time to keep a list of request pieces lying around
79 before it's considered too old and needs to be rebuilt */
80 PIECE_LIST_SHELF_LIFE_SECS = 60,
82 /* use for bitwise operations w/peer_atom.flags2 */
83 MYFLAG_BANNED = 1,
85 /* use for bitwise operations w/peer_atom.flags2 */
86 /* unreachable for now... but not banned.
87 * if they try to connect to us it's okay */
88 MYFLAG_UNREACHABLE = 2,
90 /* the minimum we'll wait before attempting to reconnect to a peer */
91 MINIMUM_RECONNECT_INTERVAL_SECS = 5,
93 /** how long we'll let requests we've made linger before we cancel them */
94 REQUEST_TTL_SECS = 120,
96 NO_BLOCKS_CANCEL_HISTORY = 120,
98 CANCEL_HISTORY_SEC = 60
101 const tr_peer_event TR_PEER_EVENT_INIT = { 0, 0, NULL, 0, 0, 0, false, 0 };
108 * Peer information that should be kept even before we've connected and
109 * after we've disconnected. These are kept in a pool of peer_atoms to decide
110 * which ones would make good candidates for connecting to, and to watch out
111 * for banned peers.
113 * @see tr_peer
114 * @see tr_peermsgs
116 struct peer_atom
118 uint8_t fromFirst; /* where the peer was first found */
119 uint8_t fromBest; /* the "best" value of where the peer has been found */
120 uint8_t flags; /* these match the added_f flags */
121 uint8_t flags2; /* flags that aren't defined in added_f */
122 int8_t seedProbability; /* how likely is this to be a seed... [0..100] or -1 for unknown */
123 int8_t blocklisted; /* -1 for unknown, true for blocklisted, false for not blocklisted */
125 tr_port port;
126 bool utp_failed; /* We recently failed to connect over uTP */
127 uint16_t numFails;
128 time_t time; /* when the peer's connection status last changed */
129 time_t piece_data_time;
131 time_t lastConnectionAttemptAt;
132 time_t lastConnectionAt;
134 /* similar to a TTL field, but less rigid --
135 * if the swarm is small, the atom will be kept past this date. */
136 time_t shelf_date;
137 tr_peer * peer; /* will be NULL if not connected */
138 tr_address addr;
141 #ifdef NDEBUG
142 #define tr_isAtom(a) (TRUE)
143 #else
144 static bool
145 tr_isAtom( const struct peer_atom * atom )
147 return ( atom != NULL )
148 && ( atom->fromFirst < TR_PEER_FROM__MAX )
149 && ( atom->fromBest < TR_PEER_FROM__MAX )
150 && ( tr_address_is_valid( &atom->addr ) );
152 #endif
154 static const char*
155 tr_atomAddrStr( const struct peer_atom * atom )
157 return atom ? tr_peerIoAddrStr( &atom->addr, atom->port ) : "[no atom]";
160 struct block_request
162 tr_block_index_t block;
163 tr_peer * peer;
164 time_t sentAt;
167 struct weighted_piece
169 tr_piece_index_t index;
170 int16_t salt;
171 int16_t requestCount;
174 enum piece_sort_state
176 PIECES_UNSORTED,
177 PIECES_SORTED_BY_INDEX,
178 PIECES_SORTED_BY_WEIGHT
181 /** @brief Opaque, per-torrent data structure for peer connection information */
182 typedef struct tr_torrent_peers
184 tr_ptrArray outgoingHandshakes; /* tr_handshake */
185 tr_ptrArray pool; /* struct peer_atom */
186 tr_ptrArray peers; /* tr_peer */
187 tr_ptrArray webseeds; /* tr_webseed */
189 tr_torrent * tor;
190 struct tr_peerMgr * manager;
192 tr_peer * optimistic; /* the optimistic peer, or NULL if none */
193 int optimisticUnchokeTimeScaler;
195 bool isRunning;
196 bool needsCompletenessCheck;
198 struct block_request * requests;
199 int requestCount;
200 int requestAlloc;
202 struct weighted_piece * pieces;
203 int pieceCount;
204 enum piece_sort_state pieceSortState;
206 /* An array of pieceCount items stating how many peers have each piece.
207 This is used to help us for downloading pieces "rarest first."
208 This may be NULL if we don't have metainfo yet, or if we're not
209 downloading and don't care about rarity */
210 uint16_t * pieceReplication;
211 size_t pieceReplicationSize;
213 int interestedCount;
214 int maxPeers;
215 time_t lastCancel;
217 /* Before the endgame this should be 0. In endgame, is contains the average
218 * number of pending requests per peer. Only peers which have more pending
219 * requests are considered 'fast' are allowed to request a block that's
220 * already been requested from another (slower?) peer. */
221 int endgame;
223 Torrent;
225 struct tr_peerMgr
227 tr_session * session;
228 tr_ptrArray incomingHandshakes; /* tr_handshake */
229 struct event * bandwidthTimer;
230 struct event * rechokeTimer;
231 struct event * refillUpkeepTimer;
232 struct event * atomTimer;
235 #define tordbg( t, ... ) \
236 do { \
237 if( tr_deepLoggingIsActive( ) ) \
238 tr_deepLog( __FILE__, __LINE__, tr_torrentName( t->tor ), __VA_ARGS__ ); \
239 } while( 0 )
241 #define dbgmsg( ... ) \
242 do { \
243 if( tr_deepLoggingIsActive( ) ) \
244 tr_deepLog( __FILE__, __LINE__, NULL, __VA_ARGS__ ); \
245 } while( 0 )
251 static inline void
252 managerLock( const struct tr_peerMgr * manager )
254 tr_sessionLock( manager->session );
257 static inline void
258 managerUnlock( const struct tr_peerMgr * manager )
260 tr_sessionUnlock( manager->session );
263 static inline void
264 torrentLock( Torrent * torrent )
266 managerLock( torrent->manager );
269 static inline void
270 torrentUnlock( Torrent * torrent )
272 managerUnlock( torrent->manager );
275 static inline int
276 torrentIsLocked( const Torrent * t )
278 return tr_sessionIsLocked( t->manager->session );
285 static int
286 handshakeCompareToAddr( const void * va, const void * vb )
288 const tr_handshake * a = va;
290 return tr_address_compare( tr_handshakeGetAddr( a, NULL ), vb );
293 static int
294 handshakeCompare( const void * a, const void * b )
296 return handshakeCompareToAddr( a, tr_handshakeGetAddr( b, NULL ) );
299 static inline tr_handshake*
300 getExistingHandshake( tr_ptrArray * handshakes, const tr_address * addr )
302 if( tr_ptrArrayEmpty( handshakes ) )
303 return NULL;
305 return tr_ptrArrayFindSorted( handshakes, addr, handshakeCompareToAddr );
308 static int
309 comparePeerAtomToAddress( const void * va, const void * vb )
311 const struct peer_atom * a = va;
313 return tr_address_compare( &a->addr, vb );
316 static int
317 compareAtomsByAddress( const void * va, const void * vb )
319 const struct peer_atom * b = vb;
321 assert( tr_isAtom( b ) );
323 return comparePeerAtomToAddress( va, &b->addr );
330 const tr_address *
331 tr_peerAddress( const tr_peer * peer )
333 return &peer->atom->addr;
336 static Torrent*
337 getExistingTorrent( tr_peerMgr * manager,
338 const uint8_t * hash )
340 tr_torrent * tor = tr_torrentFindFromHash( manager->session, hash );
342 return tor == NULL ? NULL : tor->torrentPeers;
345 static int
346 peerCompare( const void * a, const void * b )
348 return tr_address_compare( tr_peerAddress( a ), tr_peerAddress( b ) );
351 static struct peer_atom*
352 getExistingAtom( const Torrent * t,
353 const tr_address * addr )
355 Torrent * tt = (Torrent*)t;
356 assert( torrentIsLocked( t ) );
357 return tr_ptrArrayFindSorted( &tt->pool, addr, comparePeerAtomToAddress );
360 static bool
361 peerIsInUse( const Torrent * ct, const struct peer_atom * atom )
363 Torrent * t = (Torrent*) ct;
365 assert( torrentIsLocked ( t ) );
367 return ( atom->peer != NULL )
368 || getExistingHandshake( &t->outgoingHandshakes, &atom->addr )
369 || getExistingHandshake( &t->manager->incomingHandshakes, &atom->addr );
372 void
373 tr_peerConstruct( tr_peer * peer )
375 memset( peer, 0, sizeof( tr_peer ) );
377 peer->have = TR_BITFIELD_INIT;
380 static tr_peer*
381 peerNew( struct peer_atom * atom )
383 tr_peer * peer = tr_new( tr_peer, 1 );
384 tr_peerConstruct( peer );
386 peer->atom = atom;
387 atom->peer = peer;
389 return peer;
392 static tr_peer*
393 getPeer( Torrent * torrent, struct peer_atom * atom )
395 tr_peer * peer;
397 assert( torrentIsLocked( torrent ) );
399 peer = atom->peer;
401 if( peer == NULL )
403 peer = peerNew( atom );
404 tr_bitfieldConstruct( &peer->have, torrent->tor->blockCount );
405 tr_bitfieldConstruct( &peer->blame, torrent->tor->blockCount );
406 tr_ptrArrayInsertSorted( &torrent->peers, peer, peerCompare );
409 return peer;
412 static void peerDeclinedAllRequests( Torrent *, const tr_peer * );
414 void
415 tr_peerDestruct( tr_torrent * tor, tr_peer * peer )
417 assert( peer != NULL );
419 peerDeclinedAllRequests( tor->torrentPeers, peer );
421 if( peer->msgs != NULL )
422 tr_peerMsgsFree( peer->msgs );
424 if( peer->io ) {
425 tr_peerIoClear( peer->io );
426 tr_peerIoUnref( peer->io ); /* balanced by the ref in handshakeDoneCB() */
429 tr_bitfieldDestruct( &peer->have );
430 tr_bitfieldDestruct( &peer->blame );
431 tr_free( peer->client );
433 if( peer->atom )
434 peer->atom->peer = NULL;
437 static void
438 peerDelete( Torrent * t, tr_peer * peer )
440 tr_peerDestruct( t->tor, peer );
441 tr_free( peer );
444 static bool
445 replicationExists( const Torrent * t )
447 return t->pieceReplication != NULL;
450 static void
451 replicationFree( Torrent * t )
453 tr_free( t->pieceReplication );
454 t->pieceReplication = NULL;
455 t->pieceReplicationSize = 0;
458 static void
459 replicationNew( Torrent * t )
461 tr_piece_index_t piece_i;
462 const tr_piece_index_t piece_count = t->tor->info.pieceCount;
463 tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( &t->peers );
464 const int peer_count = tr_ptrArraySize( &t->peers );
466 assert( !replicationExists( t ) );
468 t->pieceReplicationSize = piece_count;
469 t->pieceReplication = tr_new0( uint16_t, piece_count );
471 for( piece_i=0; piece_i<piece_count; ++piece_i )
473 int peer_i;
474 uint16_t r = 0;
476 for( peer_i=0; peer_i<peer_count; ++peer_i )
477 if( tr_bitfieldHas( &peers[peer_i]->have, piece_i ) )
478 ++r;
480 t->pieceReplication[piece_i] = r;
484 static void
485 torrentFree( void * vt )
487 Torrent * t = vt;
489 assert( t );
490 assert( !t->isRunning );
491 assert( torrentIsLocked( t ) );
492 assert( tr_ptrArrayEmpty( &t->outgoingHandshakes ) );
493 assert( tr_ptrArrayEmpty( &t->peers ) );
495 tr_ptrArrayDestruct( &t->webseeds, (PtrArrayForeachFunc)tr_webseedFree );
496 tr_ptrArrayDestruct( &t->pool, (PtrArrayForeachFunc)tr_free );
497 tr_ptrArrayDestruct( &t->outgoingHandshakes, NULL );
498 tr_ptrArrayDestruct( &t->peers, NULL );
500 replicationFree( t );
502 tr_free( t->requests );
503 tr_free( t->pieces );
504 tr_free( t );
507 static void peerCallbackFunc( tr_peer *, const tr_peer_event *, void * );
509 static Torrent*
510 torrentNew( tr_peerMgr * manager, tr_torrent * tor )
512 int i;
513 Torrent * t;
515 t = tr_new0( Torrent, 1 );
516 t->manager = manager;
517 t->tor = tor;
518 t->pool = TR_PTR_ARRAY_INIT;
519 t->peers = TR_PTR_ARRAY_INIT;
520 t->webseeds = TR_PTR_ARRAY_INIT;
521 t->outgoingHandshakes = TR_PTR_ARRAY_INIT;
523 for( i = 0; i < tor->info.webseedCount; ++i )
525 tr_webseed * w =
526 tr_webseedNew( tor, tor->info.webseeds[i], peerCallbackFunc, t );
527 tr_ptrArrayAppend( &t->webseeds, w );
530 return t;
533 tr_peerMgr*
534 tr_peerMgrNew( tr_session * session )
536 tr_peerMgr * m = tr_new0( tr_peerMgr, 1 );
537 m->session = session;
538 m->incomingHandshakes = TR_PTR_ARRAY_INIT;
539 return m;
542 static void
543 deleteTimer( struct event ** t )
545 if( *t != NULL )
547 event_free( *t );
548 *t = NULL;
552 static void
553 deleteTimers( struct tr_peerMgr * m )
555 deleteTimer( &m->atomTimer );
556 deleteTimer( &m->bandwidthTimer );
557 deleteTimer( &m->rechokeTimer );
558 deleteTimer( &m->refillUpkeepTimer );
561 void
562 tr_peerMgrFree( tr_peerMgr * manager )
564 managerLock( manager );
566 deleteTimers( manager );
568 /* free the handshakes. Abort invokes handshakeDoneCB(), which removes
569 * the item from manager->handshakes, so this is a little roundabout... */
570 while( !tr_ptrArrayEmpty( &manager->incomingHandshakes ) )
571 tr_handshakeAbort( tr_ptrArrayNth( &manager->incomingHandshakes, 0 ) );
573 tr_ptrArrayDestruct( &manager->incomingHandshakes, NULL );
575 managerUnlock( manager );
576 tr_free( manager );
579 static int
580 clientIsDownloadingFrom( const tr_torrent * tor, const tr_peer * peer )
582 if( !tr_torrentHasMetadata( tor ) )
583 return true;
585 return peer->clientIsInterested && !peer->clientIsChoked;
588 static int
589 clientIsUploadingTo( const tr_peer * peer )
591 return peer->peerIsInterested && !peer->peerIsChoked;
594 /***
595 ****
596 ***/
598 void
599 tr_peerMgrOnBlocklistChanged( tr_peerMgr * mgr )
601 tr_torrent * tor = NULL;
602 tr_session * session = mgr->session;
604 /* we cache whether or not a peer is blocklisted...
605 since the blocklist has changed, erase that cached value */
606 while(( tor = tr_torrentNext( session, tor )))
608 int i;
609 Torrent * t = tor->torrentPeers;
610 const int n = tr_ptrArraySize( &t->pool );
611 for( i=0; i<n; ++i ) {
612 struct peer_atom * atom = tr_ptrArrayNth( &t->pool, i );
613 atom->blocklisted = -1;
618 static bool
619 isAtomBlocklisted( tr_session * session, struct peer_atom * atom )
621 if( atom->blocklisted < 0 )
622 atom->blocklisted = tr_sessionIsAddressBlocked( session, &atom->addr );
624 assert( tr_isBool( atom->blocklisted ) );
625 return atom->blocklisted;
629 /***
630 ****
631 ***/
633 static void
634 atomSetSeedProbability( struct peer_atom * atom, int seedProbability )
636 assert( atom != NULL );
637 assert( -1<=seedProbability && seedProbability<=100 );
639 atom->seedProbability = seedProbability;
641 if( seedProbability == 100 )
642 atom->flags |= ADDED_F_SEED_FLAG;
643 else if( seedProbability != -1 )
644 atom->flags &= ~ADDED_F_SEED_FLAG;
647 static inline bool
648 atomIsSeed( const struct peer_atom * atom )
650 return atom->seedProbability == 100;
653 static void
654 atomSetSeed( const Torrent * t, struct peer_atom * atom )
656 if( !atomIsSeed( atom ) )
658 tordbg( t, "marking peer %s as a seed", tr_atomAddrStr( atom ) );
660 atomSetSeedProbability( atom, 100 );
665 bool
666 tr_peerMgrPeerIsSeed( const tr_torrent * tor,
667 const tr_address * addr )
669 bool isSeed = false;
670 const Torrent * t = tor->torrentPeers;
671 const struct peer_atom * atom = getExistingAtom( t, addr );
673 if( atom )
674 isSeed = atomIsSeed( atom );
676 return isSeed;
679 void
680 tr_peerMgrSetUtpSupported( tr_torrent * tor, const tr_address * addr )
682 struct peer_atom * atom = getExistingAtom( tor->torrentPeers, addr );
684 if( atom )
685 atom->flags |= ADDED_F_UTP_FLAGS;
688 void
689 tr_peerMgrSetUtpFailed( tr_torrent *tor, const tr_address *addr, bool failed )
691 struct peer_atom * atom = getExistingAtom( tor->torrentPeers, addr );
693 if( atom )
694 atom->utp_failed = failed;
699 *** REQUESTS
701 *** There are two data structures associated with managing block requests:
703 *** 1. Torrent::requests, an array of "struct block_request" which keeps
704 *** track of which blocks have been requested, and when, and by which peers.
705 *** This is list is used for (a) cancelling requests that have been pending
706 *** for too long and (b) avoiding duplicate requests before endgame.
708 *** 2. Torrent::pieces, an array of "struct weighted_piece" which lists the
709 *** pieces that we want to request. It's used to decide which blocks to
710 *** return next when tr_peerMgrGetBlockRequests() is called.
714 *** struct block_request
717 static int
718 compareReqByBlock( const void * va, const void * vb )
720 const struct block_request * a = va;
721 const struct block_request * b = vb;
723 /* primary key: block */
724 if( a->block < b->block ) return -1;
725 if( a->block > b->block ) return 1;
727 /* secondary key: peer */
728 if( a->peer < b->peer ) return -1;
729 if( a->peer > b->peer ) return 1;
731 return 0;
734 static void
735 requestListAdd( Torrent * t, tr_block_index_t block, tr_peer * peer )
737 struct block_request key;
739 /* ensure enough room is available... */
740 if( t->requestCount + 1 >= t->requestAlloc )
742 const int CHUNK_SIZE = 128;
743 t->requestAlloc += CHUNK_SIZE;
744 t->requests = tr_renew( struct block_request,
745 t->requests, t->requestAlloc );
748 /* populate the record we're inserting */
749 key.block = block;
750 key.peer = peer;
751 key.sentAt = tr_time( );
753 /* insert the request to our array... */
755 bool exact;
756 const int pos = tr_lowerBound( &key, t->requests, t->requestCount,
757 sizeof( struct block_request ),
758 compareReqByBlock, &exact );
759 assert( !exact );
760 memmove( t->requests + pos + 1,
761 t->requests + pos,
762 sizeof( struct block_request ) * ( t->requestCount++ - pos ) );
763 t->requests[pos] = key;
766 if( peer != NULL )
768 ++peer->pendingReqsToPeer;
769 assert( peer->pendingReqsToPeer >= 0 );
772 /*fprintf( stderr, "added request of block %lu from peer %s... "
773 "there are now %d block\n",
774 (unsigned long)block, tr_atomAddrStr( peer->atom ), t->requestCount );*/
777 static struct block_request *
778 requestListLookup( Torrent * t, tr_block_index_t block, const tr_peer * peer )
780 struct block_request key;
781 key.block = block;
782 key.peer = (tr_peer*) peer;
784 return bsearch( &key, t->requests, t->requestCount,
785 sizeof( struct block_request ),
786 compareReqByBlock );
790 * Find the peers are we currently requesting the block
791 * with index @a block from and append them to @a peerArr.
793 static void
794 getBlockRequestPeers( Torrent * t, tr_block_index_t block,
795 tr_ptrArray * peerArr )
797 bool exact;
798 int i, pos;
799 struct block_request key;
801 key.block = block;
802 key.peer = NULL;
803 pos = tr_lowerBound( &key, t->requests, t->requestCount,
804 sizeof( struct block_request ),
805 compareReqByBlock, &exact );
807 assert( !exact ); /* shouldn't have a request with .peer == NULL */
809 for( i = pos; i < t->requestCount; ++i )
811 if( t->requests[i].block != block )
812 break;
813 tr_ptrArrayAppend( peerArr, t->requests[i].peer );
817 static void
818 decrementPendingReqCount( const struct block_request * b )
820 if( b->peer != NULL )
821 if( b->peer->pendingReqsToPeer > 0 )
822 --b->peer->pendingReqsToPeer;
825 static void
826 requestListRemove( Torrent * t, tr_block_index_t block, const tr_peer * peer )
828 const struct block_request * b = requestListLookup( t, block, peer );
829 if( b != NULL )
831 const int pos = b - t->requests;
832 assert( pos < t->requestCount );
834 decrementPendingReqCount( b );
836 tr_removeElementFromArray( t->requests,
837 pos,
838 sizeof( struct block_request ),
839 t->requestCount-- );
841 /*fprintf( stderr, "removing request of block %lu from peer %s... "
842 "there are now %d block requests left\n",
843 (unsigned long)block, tr_atomAddrStr( peer->atom ), t->requestCount );*/
847 static int
848 countActiveWebseeds( const Torrent * t )
850 int activeCount = 0;
851 const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase( &t->webseeds );
852 const tr_webseed ** const wend = w + tr_ptrArraySize( &t->webseeds );
854 for( ; w!=wend; ++w )
855 if( tr_webseedIsActive( *w ) )
856 ++activeCount;
858 return activeCount;
861 static bool
862 testForEndgame( const Torrent * t )
864 /* we consider ourselves to be in endgame if the number of bytes
865 we've got requested is >= the number of bytes left to download */
866 return ( t->requestCount * t->tor->blockSize )
867 >= tr_cpLeftUntilDone( &t->tor->completion );
870 static void
871 updateEndgame( Torrent * t )
873 assert( t->requestCount >= 0 );
875 if( !testForEndgame( t ) )
877 /* not in endgame */
878 t->endgame = 0;
880 else if( !t->endgame ) /* only recalculate when endgame first begins */
882 int numDownloading = 0;
883 const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase( &t->peers );
884 const tr_peer ** const pend = p + tr_ptrArraySize( &t->peers );
886 /* add the active bittorrent peers... */
887 for( ; p!=pend; ++p )
888 if( (*p)->pendingReqsToPeer > 0 )
889 ++numDownloading;
891 /* add the active webseeds... */
892 numDownloading += countActiveWebseeds( t );
894 /* average number of pending requests per downloading peer */
895 t->endgame = t->requestCount / MAX( numDownloading, 1 );
900 /****
901 *****
902 ***** Piece List Manipulation / Accessors
903 *****
904 ****/
906 static inline void
907 invalidatePieceSorting( Torrent * t )
909 t->pieceSortState = PIECES_UNSORTED;
912 static const tr_torrent * weightTorrent;
914 static const uint16_t * weightReplication;
916 static void
917 setComparePieceByWeightTorrent( Torrent * t )
919 if( !replicationExists( t ) )
920 replicationNew( t );
922 weightTorrent = t->tor;
923 weightReplication = t->pieceReplication;
926 /* we try to create a "weight" s.t. high-priority pieces come before others,
927 * and that partially-complete pieces come before empty ones. */
928 static int
929 comparePieceByWeight( const void * va, const void * vb )
931 const struct weighted_piece * a = va;
932 const struct weighted_piece * b = vb;
933 int ia, ib, missing, pending;
934 const tr_torrent * tor = weightTorrent;
935 const uint16_t * rep = weightReplication;
937 /* primary key: weight */
938 missing = tr_cpMissingBlocksInPiece( &tor->completion, a->index );
939 pending = a->requestCount;
940 ia = missing > pending ? missing - pending : (tor->blockCountInPiece + pending);
941 missing = tr_cpMissingBlocksInPiece( &tor->completion, b->index );
942 pending = b->requestCount;
943 ib = missing > pending ? missing - pending : (tor->blockCountInPiece + pending);
944 if( ia < ib ) return -1;
945 if( ia > ib ) return 1;
947 /* secondary key: higher priorities go first */
948 ia = tor->info.pieces[a->index].priority;
949 ib = tor->info.pieces[b->index].priority;
950 if( ia > ib ) return -1;
951 if( ia < ib ) return 1;
953 /* tertiary key: rarest first. */
954 ia = rep[a->index];
955 ib = rep[b->index];
956 if( ia < ib ) return -1;
957 if( ia > ib ) return 1;
959 /* quaternary key: random */
960 if( a->salt < b->salt ) return -1;
961 if( a->salt > b->salt ) return 1;
963 /* okay, they're equal */
964 return 0;
967 static int
968 comparePieceByIndex( const void * va, const void * vb )
970 const struct weighted_piece * a = va;
971 const struct weighted_piece * b = vb;
972 if( a->index < b->index ) return -1;
973 if( a->index > b->index ) return 1;
974 return 0;
977 static void
978 pieceListSort( Torrent * t, enum piece_sort_state state )
980 assert( state==PIECES_SORTED_BY_INDEX
981 || state==PIECES_SORTED_BY_WEIGHT );
984 if( state == PIECES_SORTED_BY_WEIGHT )
986 setComparePieceByWeightTorrent( t );
987 qsort( t->pieces, t->pieceCount, sizeof( struct weighted_piece ), comparePieceByWeight );
989 else
990 qsort( t->pieces, t->pieceCount, sizeof( struct weighted_piece ), comparePieceByIndex );
992 t->pieceSortState = state;
996 * These functions are useful for testing, but too expensive for nightly builds.
997 * let's leave it disabled but add an easy hook to compile it back in
999 #if 1
1000 #define assertWeightedPiecesAreSorted(t)
1001 #define assertReplicationCountIsExact(t)
1002 #else
1003 static void
1004 assertWeightedPiecesAreSorted( Torrent * t )
1006 if( !t->endgame )
1008 int i;
1009 setComparePieceByWeightTorrent( t );
1010 for( i=0; i<t->pieceCount-1; ++i )
1011 assert( comparePieceByWeight( &t->pieces[i], &t->pieces[i+1] ) <= 0 );
1014 static void
1015 assertReplicationCountIsExact( Torrent * t )
1017 /* This assert might fail due to errors of implementations in other
1018 * clients. It happens when receiving duplicate bitfields/HaveAll/HaveNone
1019 * from a client. If a such a behavior is noticed,
1020 * a bug report should be filled to the faulty client. */
1022 size_t piece_i;
1023 const uint16_t * rep = t->pieceReplication;
1024 const size_t piece_count = t->pieceReplicationSize;
1025 const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase( &t->peers );
1026 const int peer_count = tr_ptrArraySize( &t->peers );
1028 assert( piece_count == t->tor->info.pieceCount );
1030 for( piece_i=0; piece_i<piece_count; ++piece_i )
1032 int peer_i;
1033 uint16_t r = 0;
1035 for( peer_i=0; peer_i<peer_count; ++peer_i )
1036 if( tr_bitsetHas( &peers[peer_i]->have, piece_i ) )
1037 ++r;
1039 assert( rep[piece_i] == r );
1042 #endif
1044 static struct weighted_piece *
1045 pieceListLookup( Torrent * t, tr_piece_index_t index )
1047 int i;
1049 for( i=0; i<t->pieceCount; ++i )
1050 if( t->pieces[i].index == index )
1051 return &t->pieces[i];
1053 return NULL;
1056 static void
1057 pieceListRebuild( Torrent * t )
1060 if( !tr_torrentIsSeed( t->tor ) )
1062 tr_piece_index_t i;
1063 tr_piece_index_t * pool;
1064 tr_piece_index_t poolCount = 0;
1065 const tr_torrent * tor = t->tor;
1066 const tr_info * inf = tr_torrentInfo( tor );
1067 struct weighted_piece * pieces;
1068 int pieceCount;
1070 /* build the new list */
1071 pool = tr_new( tr_piece_index_t, inf->pieceCount );
1072 for( i=0; i<inf->pieceCount; ++i )
1073 if( !inf->pieces[i].dnd )
1074 if( !tr_cpPieceIsComplete( &tor->completion, i ) )
1075 pool[poolCount++] = i;
1076 pieceCount = poolCount;
1077 pieces = tr_new0( struct weighted_piece, pieceCount );
1078 for( i=0; i<poolCount; ++i ) {
1079 struct weighted_piece * piece = pieces + i;
1080 piece->index = pool[i];
1081 piece->requestCount = 0;
1082 piece->salt = tr_cryptoWeakRandInt( 4096 );
1085 /* if we already had a list of pieces, merge it into
1086 * the new list so we don't lose its requestCounts */
1087 if( t->pieces != NULL )
1089 struct weighted_piece * o = t->pieces;
1090 struct weighted_piece * oend = o + t->pieceCount;
1091 struct weighted_piece * n = pieces;
1092 struct weighted_piece * nend = n + pieceCount;
1094 pieceListSort( t, PIECES_SORTED_BY_INDEX );
1096 while( o!=oend && n!=nend ) {
1097 if( o->index < n->index )
1098 ++o;
1099 else if( o->index > n->index )
1100 ++n;
1101 else
1102 *n++ = *o++;
1105 tr_free( t->pieces );
1108 t->pieces = pieces;
1109 t->pieceCount = pieceCount;
1111 pieceListSort( t, PIECES_SORTED_BY_WEIGHT );
1113 /* cleanup */
1114 tr_free( pool );
1118 static void
1119 pieceListRemovePiece( Torrent * t, tr_piece_index_t piece )
1121 struct weighted_piece * p;
1123 if(( p = pieceListLookup( t, piece )))
1125 const int pos = p - t->pieces;
1127 tr_removeElementFromArray( t->pieces,
1128 pos,
1129 sizeof( struct weighted_piece ),
1130 t->pieceCount-- );
1132 if( t->pieceCount == 0 )
1134 tr_free( t->pieces );
1135 t->pieces = NULL;
1140 static void
1141 pieceListResortPiece( Torrent * t, struct weighted_piece * p )
1143 int pos;
1144 bool isSorted = true;
1146 if( p == NULL )
1147 return;
1149 /* is the torrent already sorted? */
1150 pos = p - t->pieces;
1151 setComparePieceByWeightTorrent( t );
1152 if( isSorted && ( pos > 0 ) && ( comparePieceByWeight( p-1, p ) > 0 ) )
1153 isSorted = false;
1154 if( isSorted && ( pos < t->pieceCount - 1 ) && ( comparePieceByWeight( p, p+1 ) > 0 ) )
1155 isSorted = false;
1157 if( t->pieceSortState != PIECES_SORTED_BY_WEIGHT )
1159 pieceListSort( t, PIECES_SORTED_BY_WEIGHT);
1160 isSorted = true;
1163 /* if it's not sorted, move it around */
1164 if( !isSorted )
1166 bool exact;
1167 const struct weighted_piece tmp = *p;
1169 tr_removeElementFromArray( t->pieces,
1170 pos,
1171 sizeof( struct weighted_piece ),
1172 t->pieceCount-- );
1174 pos = tr_lowerBound( &tmp, t->pieces, t->pieceCount,
1175 sizeof( struct weighted_piece ),
1176 comparePieceByWeight, &exact );
1178 memmove( &t->pieces[pos + 1],
1179 &t->pieces[pos],
1180 sizeof( struct weighted_piece ) * ( t->pieceCount++ - pos ) );
1182 t->pieces[pos] = tmp;
1185 assertWeightedPiecesAreSorted( t );
1188 static void
1189 pieceListRemoveRequest( Torrent * t, tr_block_index_t block )
1191 struct weighted_piece * p;
1192 const tr_piece_index_t index = tr_torBlockPiece( t->tor, block );
1194 if( ((p = pieceListLookup( t, index ))) && ( p->requestCount > 0 ) )
1196 --p->requestCount;
1197 pieceListResortPiece( t, p );
1202 /****
1203 *****
1204 ***** Replication count ( for rarest first policy )
1205 *****
1206 ****/
1209 * Increase the replication count of this piece and sort it if the
1210 * piece list is already sorted
1212 static void
1213 tr_incrReplicationOfPiece( Torrent * t, const size_t index )
1215 assert( replicationExists( t ) );
1216 assert( t->pieceReplicationSize == t->tor->info.pieceCount );
1218 /* One more replication of this piece is present in the swarm */
1219 ++t->pieceReplication[index];
1221 /* we only resort the piece if the list is already sorted */
1222 if( t->pieceSortState == PIECES_SORTED_BY_WEIGHT )
1223 pieceListResortPiece( t, pieceListLookup( t, index ) );
1227 * Increases the replication count of pieces present in the bitfield
1229 static void
1230 tr_incrReplicationFromBitfield( Torrent * t, const tr_bitfield * b )
1232 size_t i;
1233 uint16_t * rep = t->pieceReplication;
1234 const size_t n = t->tor->info.pieceCount;
1236 assert( replicationExists( t ) );
1238 for( i=0; i<n; ++i )
1239 if( tr_bitfieldHas( b, i ) )
1240 ++rep[i];
1242 if( t->pieceSortState == PIECES_SORTED_BY_WEIGHT )
1243 invalidatePieceSorting( t );
1247 * Increase the replication count of every piece
1249 static void
1250 tr_incrReplication( Torrent * t )
1252 int i;
1253 const int n = t->pieceReplicationSize;
1255 assert( replicationExists( t ) );
1256 assert( t->pieceReplicationSize == t->tor->info.pieceCount );
1258 for( i=0; i<n; ++i )
1259 ++t->pieceReplication[i];
1263 * Decrease the replication count of pieces present in the bitset.
1265 static void
1266 tr_decrReplicationFromBitfield( Torrent * t, const tr_bitfield * b )
1268 int i;
1269 const int n = t->pieceReplicationSize;
1271 assert( replicationExists( t ) );
1272 assert( t->pieceReplicationSize == t->tor->info.pieceCount );
1274 if( tr_bitfieldHasAll( b ) )
1276 for( i=0; i<n; ++i )
1277 --t->pieceReplication[i];
1279 else if ( !tr_bitfieldHasNone( b ) )
1281 for( i=0; i<n; ++i )
1282 if( tr_bitfieldHas( b, i ) )
1283 --t->pieceReplication[i];
1285 if( t->pieceSortState == PIECES_SORTED_BY_WEIGHT )
1286 invalidatePieceSorting( t );
1294 void
1295 tr_peerMgrRebuildRequests( tr_torrent * tor )
1297 assert( tr_isTorrent( tor ) );
1299 pieceListRebuild( tor->torrentPeers );
1302 void
1303 tr_peerMgrGetNextRequests( tr_torrent * tor,
1304 tr_peer * peer,
1305 int numwant,
1306 tr_block_index_t * setme,
1307 int * numgot,
1308 bool get_intervals )
1310 int i;
1311 int got;
1312 Torrent * t;
1313 struct weighted_piece * pieces;
1314 const tr_bitfield * const have = &peer->have;
1316 /* sanity clause */
1317 assert( tr_isTorrent( tor ) );
1318 assert( peer->clientIsInterested );
1319 assert( !peer->clientIsChoked );
1320 assert( numwant > 0 );
1322 /* walk through the pieces and find blocks that should be requested */
1323 got = 0;
1324 t = tor->torrentPeers;
1326 /* prep the pieces list */
1327 if( t->pieces == NULL )
1328 pieceListRebuild( t );
1330 if( t->pieceSortState != PIECES_SORTED_BY_WEIGHT )
1331 pieceListSort( t, PIECES_SORTED_BY_WEIGHT );
1333 assertReplicationCountIsExact( t );
1334 assertWeightedPiecesAreSorted( t );
1336 updateEndgame( t );
1337 pieces = t->pieces;
1338 for( i=0; i<t->pieceCount && got<numwant; ++i )
1340 struct weighted_piece * p = pieces + i;
1342 /* if the peer has this piece that we want... */
1343 if( tr_bitfieldHas( have, p->index ) )
1345 tr_block_index_t b;
1346 tr_block_index_t first;
1347 tr_block_index_t last;
1348 tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
1350 tr_torGetPieceBlockRange( tor, p->index, &first, &last );
1352 for( b=first; b<=last && (got<numwant || (get_intervals && setme[2*got-1] == b-1)); ++b )
1354 int peerCount;
1355 tr_peer ** peers;
1357 /* don't request blocks we've already got */
1358 if( tr_cpBlockIsComplete( &tor->completion, b ) )
1359 continue;
1361 /* always add peer if this block has no peers yet */
1362 tr_ptrArrayClear( &peerArr );
1363 getBlockRequestPeers( t, b, &peerArr );
1364 peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
1365 if( peerCount != 0 )
1367 /* don't make a second block request until the endgame */
1368 if( !t->endgame )
1369 continue;
1371 /* don't have more than two peers requesting this block */
1372 if( peerCount > 1 )
1373 continue;
1375 /* don't send the same request to the same peer twice */
1376 if( peer == peers[0] )
1377 continue;
1379 /* in the endgame allow an additional peer to download a
1380 block but only if the peer seems to be handling requests
1381 relatively fast */
1382 if( peer->pendingReqsToPeer + numwant - got < t->endgame )
1383 continue;
1386 /* update the caller's table */
1387 if( !get_intervals ) {
1388 setme[got++] = b;
1390 /* if intervals are requested two array entries are necessarry:
1391 one for the interval's starting block and one for its end block */
1392 else if( got && setme[2 * got - 1] == b - 1 && b != first ) {
1393 /* expand the last interval */
1394 ++setme[2 * got - 1];
1396 else {
1397 /* begin a new interval */
1398 setme[2 * got] = setme[2 * got + 1] = b;
1399 ++got;
1402 /* update our own tables */
1403 requestListAdd( t, b, peer );
1404 ++p->requestCount;
1407 tr_ptrArrayDestruct( &peerArr, NULL );
1411 /* In most cases we've just changed the weights of a small number of pieces.
1412 * So rather than qsort()ing the entire array, it's faster to apply an
1413 * adaptive insertion sort algorithm. */
1414 if( got > 0 )
1416 /* not enough requests || last piece modified */
1417 if ( i == t->pieceCount ) --i;
1419 setComparePieceByWeightTorrent( t );
1420 while( --i >= 0 )
1422 bool exact;
1424 /* relative position! */
1425 const int newpos = tr_lowerBound( &t->pieces[i], &t->pieces[i + 1],
1426 t->pieceCount - (i + 1),
1427 sizeof( struct weighted_piece ),
1428 comparePieceByWeight, &exact );
1429 if( newpos > 0 )
1431 const struct weighted_piece piece = t->pieces[i];
1432 memmove( &t->pieces[i],
1433 &t->pieces[i + 1],
1434 sizeof( struct weighted_piece ) * ( newpos ) );
1435 t->pieces[i + newpos] = piece;
1440 assertWeightedPiecesAreSorted( t );
1441 *numgot = got;
1444 bool
1445 tr_peerMgrDidPeerRequest( const tr_torrent * tor,
1446 const tr_peer * peer,
1447 tr_block_index_t block )
1449 const Torrent * t = tor->torrentPeers;
1450 return requestListLookup( (Torrent*)t, block, peer ) != NULL;
1453 /* cancel requests that are too old */
1454 static void
1455 refillUpkeep( int foo UNUSED, short bar UNUSED, void * vmgr )
1457 time_t now;
1458 time_t too_old;
1459 tr_torrent * tor;
1460 int cancel_buflen = 0;
1461 struct block_request * cancel = NULL;
1462 tr_peerMgr * mgr = vmgr;
1463 managerLock( mgr );
1465 now = tr_time( );
1466 too_old = now - REQUEST_TTL_SECS;
1468 /* alloc the temporary "cancel" buffer */
1469 tor = NULL;
1470 while(( tor = tr_torrentNext( mgr->session, tor )))
1471 cancel_buflen = MAX( cancel_buflen, tor->torrentPeers->requestCount );
1472 if( cancel_buflen > 0 )
1473 cancel = tr_new( struct block_request, cancel_buflen );
1475 /* prune requests that are too old */
1476 tor = NULL;
1477 while(( tor = tr_torrentNext( mgr->session, tor )))
1479 Torrent * t = tor->torrentPeers;
1480 const int n = t->requestCount;
1481 if( n > 0 )
1483 int keepCount = 0;
1484 int cancelCount = 0;
1485 const struct block_request * it;
1486 const struct block_request * end;
1488 for( it=t->requests, end=it+n; it!=end; ++it )
1490 if( ( it->sentAt <= too_old ) && it->peer->msgs && !tr_peerMsgsIsReadingBlock( it->peer->msgs, it->block ) )
1491 cancel[cancelCount++] = *it;
1492 else
1494 if( it != &t->requests[keepCount] )
1495 t->requests[keepCount] = *it;
1496 keepCount++;
1500 /* prune out the ones we aren't keeping */
1501 t->requestCount = keepCount;
1503 /* send cancel messages for all the "cancel" ones */
1504 for( it=cancel, end=it+cancelCount; it!=end; ++it ) {
1505 if( ( it->peer != NULL ) && ( it->peer->msgs != NULL ) ) {
1506 tr_historyAdd( &it->peer->cancelsSentToPeer, now, 1 );
1507 tr_peerMsgsCancel( it->peer->msgs, it->block );
1508 decrementPendingReqCount( it );
1512 /* decrement the pending request counts for the timed-out blocks */
1513 for( it=cancel, end=it+cancelCount; it!=end; ++it )
1514 pieceListRemoveRequest( t, it->block );
1518 tr_free( cancel );
1519 tr_timerAddMsec( mgr->refillUpkeepTimer, REFILL_UPKEEP_PERIOD_MSEC );
1520 managerUnlock( mgr );
1523 static void
1524 addStrike( Torrent * t, tr_peer * peer )
1526 tordbg( t, "increasing peer %s strike count to %d",
1527 tr_atomAddrStr( peer->atom ), peer->strikes + 1 );
1529 if( ++peer->strikes >= MAX_BAD_PIECES_PER_PEER )
1531 struct peer_atom * atom = peer->atom;
1532 atom->flags2 |= MYFLAG_BANNED;
1533 peer->doPurge = 1;
1534 tordbg( t, "banning peer %s", tr_atomAddrStr( atom ) );
1538 static void
1539 gotBadPiece( Torrent * t, tr_piece_index_t pieceIndex )
1541 tr_torrent * tor = t->tor;
1542 const uint32_t byteCount = tr_torPieceCountBytes( tor, pieceIndex );
1544 tor->corruptCur += byteCount;
1545 tor->downloadedCur -= MIN( tor->downloadedCur, byteCount );
1547 tr_announcerAddBytes( tor, TR_ANN_CORRUPT, byteCount );
1550 static void
1551 peerSuggestedPiece( Torrent * t UNUSED,
1552 tr_peer * peer UNUSED,
1553 tr_piece_index_t pieceIndex UNUSED,
1554 int isFastAllowed UNUSED )
1556 #if 0
1557 assert( t );
1558 assert( peer );
1559 assert( peer->msgs );
1561 /* is this a valid piece? */
1562 if( pieceIndex >= t->tor->info.pieceCount )
1563 return;
1565 /* don't ask for it if we've already got it */
1566 if( tr_cpPieceIsComplete( t->tor->completion, pieceIndex ) )
1567 return;
1569 /* don't ask for it if they don't have it */
1570 if( !tr_bitfieldHas( peer->have, pieceIndex ) )
1571 return;
1573 /* don't ask for it if we're choked and it's not fast */
1574 if( !isFastAllowed && peer->clientIsChoked )
1575 return;
1577 /* request the blocks that we don't have in this piece */
1579 tr_block_index_t b;
1580 tr_block_index_t first;
1581 tr_block_index_t last;
1582 const tr_torrent * tor = t->tor;
1584 tr_torGetPieceBlockRange( t->tor, pieceIndex, &first, &last );
1586 for( b=first; b<=last; ++b )
1588 if( !tr_cpBlockIsComplete( tor->completion, b ) )
1590 const uint32_t offset = getBlockOffsetInPiece( tor, b );
1591 const uint32_t length = tr_torBlockCountBytes( tor, b );
1592 tr_peerMsgsAddRequest( peer->msgs, pieceIndex, offset, length );
1593 incrementPieceRequests( t, pieceIndex );
1597 #endif
1600 static void
1601 removeRequestFromTables( Torrent * t, tr_block_index_t block, const tr_peer * peer )
1603 requestListRemove( t, block, peer );
1604 pieceListRemoveRequest( t, block );
1607 /* peer choked us, or maybe it disconnected.
1608 either way we need to remove all its requests */
1609 static void
1610 peerDeclinedAllRequests( Torrent * t, const tr_peer * peer )
1612 int i, n;
1613 tr_block_index_t * blocks = tr_new( tr_block_index_t, t->requestCount );
1615 for( i=n=0; i<t->requestCount; ++i )
1616 if( peer == t->requests[i].peer )
1617 blocks[n++] = t->requests[i].block;
1619 for( i=0; i<n; ++i )
1620 removeRequestFromTables( t, blocks[i], peer );
1622 tr_free( blocks );
1625 static void tr_peerMgrSetBlame( tr_torrent *, tr_piece_index_t, int );
1627 static void
1628 peerCallbackFunc( tr_peer * peer, const tr_peer_event * e, void * vt )
1630 Torrent * t = vt;
1632 torrentLock( t );
1634 assert( peer != NULL );
1636 switch( e->eventType )
1638 case TR_PEER_PEER_GOT_DATA:
1640 const time_t now = tr_time( );
1641 tr_torrent * tor = t->tor;
1643 if( e->wasPieceData )
1645 tor->uploadedCur += e->length;
1646 tr_announcerAddBytes( tor, TR_ANN_UP, e->length );
1647 tr_torrentSetActivityDate( tor, now );
1648 tr_torrentSetDirty( tor );
1651 /* update the stats */
1652 if( e->wasPieceData )
1653 tr_statsAddUploaded( tor->session, e->length );
1655 /* update our atom */
1656 if( peer->atom && e->wasPieceData )
1657 peer->atom->piece_data_time = now;
1659 break;
1662 case TR_PEER_CLIENT_GOT_HAVE:
1663 if( replicationExists( t ) ) {
1664 tr_incrReplicationOfPiece( t, e->pieceIndex );
1665 assertReplicationCountIsExact( t );
1667 break;
1669 case TR_PEER_CLIENT_GOT_HAVE_ALL:
1670 if( replicationExists( t ) ) {
1671 tr_incrReplication( t );
1672 assertReplicationCountIsExact( t );
1674 break;
1676 case TR_PEER_CLIENT_GOT_HAVE_NONE:
1677 /* noop */
1678 break;
1680 case TR_PEER_CLIENT_GOT_BITFIELD:
1681 assert( e->bitfield != NULL );
1682 if( replicationExists( t ) ) {
1683 tr_incrReplicationFromBitfield( t, e->bitfield );
1684 assertReplicationCountIsExact( t );
1686 break;
1688 case TR_PEER_CLIENT_GOT_REJ: {
1689 tr_block_index_t b = _tr_block( t->tor, e->pieceIndex, e->offset );
1690 if( b < t->tor->blockCount )
1691 removeRequestFromTables( t, b, peer );
1692 else
1693 tordbg( t, "Peer %s sent an out-of-range reject message",
1694 tr_atomAddrStr( peer->atom ) );
1695 break;
1698 case TR_PEER_CLIENT_GOT_CHOKE:
1699 peerDeclinedAllRequests( t, peer );
1700 break;
1702 case TR_PEER_CLIENT_GOT_PORT:
1703 if( peer->atom )
1704 peer->atom->port = e->port;
1705 break;
1707 case TR_PEER_CLIENT_GOT_SUGGEST:
1708 peerSuggestedPiece( t, peer, e->pieceIndex, false );
1709 break;
1711 case TR_PEER_CLIENT_GOT_ALLOWED_FAST:
1712 peerSuggestedPiece( t, peer, e->pieceIndex, true );
1713 break;
1715 case TR_PEER_CLIENT_GOT_DATA:
1717 const time_t now = tr_time( );
1718 tr_torrent * tor = t->tor;
1720 if( e->wasPieceData )
1722 tor->downloadedCur += e->length;
1723 tr_torrentSetActivityDate( tor, now );
1724 tr_torrentSetDirty( tor );
1727 /* update the stats */
1728 if( e->wasPieceData )
1729 tr_statsAddDownloaded( tor->session, e->length );
1731 /* update our atom */
1732 if( peer->atom && e->wasPieceData )
1733 peer->atom->piece_data_time = now;
1735 break;
1738 case TR_PEER_CLIENT_GOT_BLOCK:
1740 tr_torrent * tor = t->tor;
1741 tr_block_index_t block = _tr_block( tor, e->pieceIndex, e->offset );
1742 int i, peerCount;
1743 tr_peer ** peers;
1744 tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
1746 removeRequestFromTables( t, block, peer );
1747 getBlockRequestPeers( t, block, &peerArr );
1748 peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
1750 /* remove additional block requests and send cancel to peers */
1751 for( i=0; i<peerCount; i++ ) {
1752 tr_peer * p = peers[i];
1753 assert( p != peer );
1754 if( p->msgs ) {
1755 tr_historyAdd( &p->cancelsSentToPeer, tr_time( ), 1 );
1756 tr_peerMsgsCancel( p->msgs, block );
1758 removeRequestFromTables( t, block, p );
1761 tr_ptrArrayDestruct( &peerArr, false );
1763 tr_historyAdd( &peer->blocksSentToClient, tr_time( ), 1 );
1765 if( tr_cpBlockIsComplete( &tor->completion, block ) )
1767 /* we already have this block... */
1768 const uint32_t n = tr_torBlockCountBytes( tor, block );
1769 tor->downloadedCur -= MIN( tor->downloadedCur, n );
1770 tordbg( t, "we have this block already..." );
1772 else
1774 tr_cpBlockAdd( &tor->completion, block );
1775 pieceListResortPiece( t, pieceListLookup( t, e->pieceIndex ) );
1776 tr_torrentSetDirty( tor );
1778 if( tr_cpPieceIsComplete( &tor->completion, e->pieceIndex ) )
1780 const tr_piece_index_t p = e->pieceIndex;
1781 const bool ok = tr_torrentCheckPiece( tor, p );
1783 tordbg( t, "[LAZY] checked just-completed piece %zu", (size_t)p );
1785 if( !ok )
1787 tr_torerr( tor, _( "Piece %lu, which was just downloaded, failed its checksum test" ),
1788 (unsigned long)p );
1791 tr_peerMgrSetBlame( tor, p, ok );
1793 if( !ok )
1795 gotBadPiece( t, p );
1797 else
1799 int i;
1800 int peerCount;
1801 tr_peer ** peers;
1802 tr_file_index_t fileIndex;
1804 /* only add this to downloadedCur if we got it from a peer --
1805 * webseeds shouldn't count against our ratio. As one tracker
1806 * admin put it, "Those pieces are downloaded directly from the
1807 * content distributor, not the peers, it is the tracker's job
1808 * to manage the swarms, not the web server and does not fit
1809 * into the jurisdiction of the tracker." */
1810 if( peer->msgs != NULL ) {
1811 const uint32_t n = tr_torPieceCountBytes( tor, p );
1812 tr_announcerAddBytes( tor, TR_ANN_DOWN, n );
1815 peerCount = tr_ptrArraySize( &t->peers );
1816 peers = (tr_peer**) tr_ptrArrayBase( &t->peers );
1817 for( i=0; i<peerCount; ++i )
1818 tr_peerMsgsHave( peers[i]->msgs, p );
1820 for( fileIndex=0; fileIndex<tor->info.fileCount; ++fileIndex ) {
1821 const tr_file * file = &tor->info.files[fileIndex];
1822 if( ( file->firstPiece <= p ) && ( p <= file->lastPiece ) ) {
1823 if( tr_cpFileIsComplete( &tor->completion, fileIndex ) ) {
1824 tr_cacheFlushFile( tor->session->cache, tor, fileIndex );
1825 tr_torrentFileCompleted( tor, fileIndex );
1830 pieceListRemovePiece( t, p );
1834 t->needsCompletenessCheck = true;
1836 break;
1839 case TR_PEER_ERROR:
1840 if( ( e->err == ERANGE ) || ( e->err == EMSGSIZE ) || ( e->err == ENOTCONN ) )
1842 /* some protocol error from the peer */
1843 peer->doPurge = 1;
1844 tordbg( t, "setting %s doPurge flag because we got an ERANGE, EMSGSIZE, or ENOTCONN error",
1845 tr_atomAddrStr( peer->atom ) );
1847 else
1849 tordbg( t, "unhandled error: %s", tr_strerror( e->err ) );
1851 break;
1853 default:
1854 assert( 0 );
1857 torrentUnlock( t );
1860 static int
1861 getDefaultShelfLife( uint8_t from )
1863 /* in general, peers obtained from firsthand contact
1864 * are better than those from secondhand, etc etc */
1865 switch( from )
1867 case TR_PEER_FROM_INCOMING : return 60 * 60 * 6;
1868 case TR_PEER_FROM_LTEP : return 60 * 60 * 6;
1869 case TR_PEER_FROM_TRACKER : return 60 * 60 * 3;
1870 case TR_PEER_FROM_DHT : return 60 * 60 * 3;
1871 case TR_PEER_FROM_PEX : return 60 * 60 * 2;
1872 case TR_PEER_FROM_RESUME : return 60 * 60;
1873 case TR_PEER_FROM_LPD : return 10 * 60;
1874 default : return 60 * 60;
1878 static void
1879 ensureAtomExists( Torrent * t,
1880 const tr_address * addr,
1881 const tr_port port,
1882 const uint8_t flags,
1883 const int8_t seedProbability,
1884 const uint8_t from )
1886 struct peer_atom * a;
1888 assert( tr_address_is_valid( addr ) );
1889 assert( from < TR_PEER_FROM__MAX );
1891 a = getExistingAtom( t, addr );
1893 if( a == NULL )
1895 const int jitter = tr_cryptoWeakRandInt( 60*10 );
1896 a = tr_new0( struct peer_atom, 1 );
1897 a->addr = *addr;
1898 a->port = port;
1899 a->flags = flags;
1900 a->fromFirst = from;
1901 a->fromBest = from;
1902 a->shelf_date = tr_time( ) + getDefaultShelfLife( from ) + jitter;
1903 a->blocklisted = -1;
1904 atomSetSeedProbability( a, seedProbability );
1905 tr_ptrArrayInsertSorted( &t->pool, a, compareAtomsByAddress );
1907 tordbg( t, "got a new atom: %s", tr_atomAddrStr( a ) );
1909 else
1911 if( from < a->fromBest )
1912 a->fromBest = from;
1914 if( a->seedProbability == -1 )
1915 atomSetSeedProbability( a, seedProbability );
1917 a->flags |= flags;
1921 static int
1922 getMaxPeerCount( const tr_torrent * tor )
1924 return tor->maxConnectedPeers;
1927 static int
1928 getPeerCount( const Torrent * t )
1930 return tr_ptrArraySize( &t->peers );/* + tr_ptrArraySize( &t->outgoingHandshakes ); */
1933 /* FIXME: this is kind of a mess. */
1934 static bool
1935 myHandshakeDoneCB( tr_handshake * handshake,
1936 tr_peerIo * io,
1937 bool readAnythingFromPeer,
1938 bool isConnected,
1939 const uint8_t * peer_id,
1940 void * vmanager )
1942 bool ok = isConnected;
1943 bool success = false;
1944 tr_port port;
1945 const tr_address * addr;
1946 tr_peerMgr * manager = vmanager;
1947 Torrent * t;
1948 tr_handshake * ours;
1950 assert( io );
1951 assert( tr_isBool( ok ) );
1953 t = tr_peerIoHasTorrentHash( io )
1954 ? getExistingTorrent( manager, tr_peerIoGetTorrentHash( io ) )
1955 : NULL;
1957 if( tr_peerIoIsIncoming ( io ) )
1958 ours = tr_ptrArrayRemoveSorted( &manager->incomingHandshakes,
1959 handshake, handshakeCompare );
1960 else if( t )
1961 ours = tr_ptrArrayRemoveSorted( &t->outgoingHandshakes,
1962 handshake, handshakeCompare );
1963 else
1964 ours = handshake;
1966 assert( ours );
1967 assert( ours == handshake );
1969 if( t )
1970 torrentLock( t );
1972 addr = tr_peerIoGetAddress( io, &port );
1974 if( !ok || !t || !t->isRunning )
1976 if( t )
1978 struct peer_atom * atom = getExistingAtom( t, addr );
1979 if( atom )
1981 ++atom->numFails;
1983 if( !readAnythingFromPeer )
1985 tordbg( t, "marking peer %s as unreachable... numFails is %d", tr_atomAddrStr( atom ), (int)atom->numFails );
1986 atom->flags2 |= MYFLAG_UNREACHABLE;
1991 else /* looking good */
1993 struct peer_atom * atom;
1995 ensureAtomExists( t, addr, port, 0, -1, TR_PEER_FROM_INCOMING );
1996 atom = getExistingAtom( t, addr );
1997 atom->time = tr_time( );
1998 atom->piece_data_time = 0;
1999 atom->lastConnectionAt = tr_time( );
2001 if( !tr_peerIoIsIncoming( io ) )
2003 atom->flags |= ADDED_F_CONNECTABLE;
2004 atom->flags2 &= ~MYFLAG_UNREACHABLE;
2007 /* In principle, this flag specifies whether the peer groks uTP,
2008 not whether it's currently connected over uTP. */
2009 if( io->utp_socket )
2010 atom->flags |= ADDED_F_UTP_FLAGS;
2012 if( atom->flags2 & MYFLAG_BANNED )
2014 tordbg( t, "banned peer %s tried to reconnect",
2015 tr_atomAddrStr( atom ) );
2017 else if( tr_peerIoIsIncoming( io )
2018 && ( getPeerCount( t ) >= getMaxPeerCount( t->tor ) ) )
2022 else
2024 tr_peer * peer = atom->peer;
2026 if( peer ) /* we already have this peer */
2029 else
2031 peer = getPeer( t, atom );
2032 tr_free( peer->client );
2034 if( !peer_id )
2035 peer->client = NULL;
2036 else {
2037 char client[128];
2038 tr_clientForId( client, sizeof( client ), peer_id );
2039 peer->client = tr_strdup( client );
2042 peer->io = tr_handshakeStealIO( handshake ); /* this steals its refcount too, which is
2043 balanced by our unref in peerDelete() */
2044 tr_peerIoSetParent( peer->io, &t->tor->bandwidth );
2045 tr_peerMsgsNew( t->tor, peer, peerCallbackFunc, t );
2047 success = true;
2052 if( t )
2053 torrentUnlock( t );
2055 return success;
2058 void
2059 tr_peerMgrAddIncoming( tr_peerMgr * manager,
2060 tr_address * addr,
2061 tr_port port,
2062 int socket,
2063 struct UTPSocket * utp_socket )
2065 tr_session * session;
2067 managerLock( manager );
2069 assert( tr_isSession( manager->session ) );
2070 session = manager->session;
2072 if( tr_sessionIsAddressBlocked( session, addr ) )
2074 tr_dbg( "Banned IP address \"%s\" tried to connect to us", tr_address_to_string( addr ) );
2075 if(socket >= 0)
2076 tr_netClose( session, socket );
2077 else
2078 UTP_Close( utp_socket );
2080 else if( getExistingHandshake( &manager->incomingHandshakes, addr ) )
2082 if(socket >= 0)
2083 tr_netClose( session, socket );
2084 else
2085 UTP_Close( utp_socket );
2087 else /* we don't have a connection to them yet... */
2089 tr_peerIo * io;
2090 tr_handshake * handshake;
2092 io = tr_peerIoNewIncoming( session, &session->bandwidth, addr, port, socket, utp_socket );
2094 handshake = tr_handshakeNew( io,
2095 session->encryptionMode,
2096 myHandshakeDoneCB,
2097 manager );
2099 tr_peerIoUnref( io ); /* balanced by the implicit ref in tr_peerIoNewIncoming() */
2101 tr_ptrArrayInsertSorted( &manager->incomingHandshakes, handshake,
2102 handshakeCompare );
2105 managerUnlock( manager );
2108 void
2109 tr_peerMgrAddPex( tr_torrent * tor, uint8_t from,
2110 const tr_pex * pex, int8_t seedProbability )
2112 if( tr_isPex( pex ) ) /* safeguard against corrupt data */
2114 Torrent * t = tor->torrentPeers;
2115 managerLock( t->manager );
2117 if( !tr_sessionIsAddressBlocked( t->manager->session, &pex->addr ) )
2118 if( tr_address_is_valid_for_peers( &pex->addr, pex->port ) )
2119 ensureAtomExists( t, &pex->addr, pex->port, pex->flags, seedProbability, from );
2121 managerUnlock( t->manager );
2125 void
2126 tr_peerMgrMarkAllAsSeeds( tr_torrent * tor )
2128 Torrent * t = tor->torrentPeers;
2129 const int n = tr_ptrArraySize( &t->pool );
2130 struct peer_atom ** it = (struct peer_atom**) tr_ptrArrayBase( &t->pool );
2131 struct peer_atom ** end = it + n;
2133 while( it != end )
2134 atomSetSeed( t, *it++ );
2137 tr_pex *
2138 tr_peerMgrCompactToPex( const void * compact,
2139 size_t compactLen,
2140 const uint8_t * added_f,
2141 size_t added_f_len,
2142 size_t * pexCount )
2144 size_t i;
2145 size_t n = compactLen / 6;
2146 const uint8_t * walk = compact;
2147 tr_pex * pex = tr_new0( tr_pex, n );
2149 for( i = 0; i < n; ++i )
2151 pex[i].addr.type = TR_AF_INET;
2152 memcpy( &pex[i].addr.addr, walk, 4 ); walk += 4;
2153 memcpy( &pex[i].port, walk, 2 ); walk += 2;
2154 if( added_f && ( n == added_f_len ) )
2155 pex[i].flags = added_f[i];
2158 *pexCount = n;
2159 return pex;
2162 tr_pex *
2163 tr_peerMgrCompact6ToPex( const void * compact,
2164 size_t compactLen,
2165 const uint8_t * added_f,
2166 size_t added_f_len,
2167 size_t * pexCount )
2169 size_t i;
2170 size_t n = compactLen / 18;
2171 const uint8_t * walk = compact;
2172 tr_pex * pex = tr_new0( tr_pex, n );
2174 for( i = 0; i < n; ++i )
2176 pex[i].addr.type = TR_AF_INET6;
2177 memcpy( &pex[i].addr.addr.addr6.s6_addr, walk, 16 ); walk += 16;
2178 memcpy( &pex[i].port, walk, 2 ); walk += 2;
2179 if( added_f && ( n == added_f_len ) )
2180 pex[i].flags = added_f[i];
2183 *pexCount = n;
2184 return pex;
2187 tr_pex *
2188 tr_peerMgrArrayToPex( const void * array,
2189 size_t arrayLen,
2190 size_t * pexCount )
2192 size_t i;
2193 size_t n = arrayLen / ( sizeof( tr_address ) + 2 );
2194 /*size_t n = arrayLen / sizeof( tr_peerArrayElement );*/
2195 const uint8_t * walk = array;
2196 tr_pex * pex = tr_new0( tr_pex, n );
2198 for( i = 0 ; i < n ; i++ ) {
2199 memcpy( &pex[i].addr, walk, sizeof( tr_address ) );
2200 memcpy( &pex[i].port, walk + sizeof( tr_address ), 2 );
2201 pex[i].flags = 0x00;
2202 walk += sizeof( tr_address ) + 2;
2205 *pexCount = n;
2206 return pex;
2213 static void
2214 tr_peerMgrSetBlame( tr_torrent * tor,
2215 tr_piece_index_t pieceIndex,
2216 int success )
2218 if( !success )
2220 int peerCount, i;
2221 Torrent * t = tor->torrentPeers;
2222 tr_peer ** peers;
2224 assert( torrentIsLocked( t ) );
2226 peers = (tr_peer **) tr_ptrArrayPeek( &t->peers, &peerCount );
2227 for( i = 0; i < peerCount; ++i )
2229 tr_peer * peer = peers[i];
2230 if( tr_bitfieldHas( &peer->blame, pieceIndex ) )
2232 tordbg( t, "peer %s contributed to corrupt piece (%d); now has %d strikes",
2233 tr_atomAddrStr( peer->atom ),
2234 pieceIndex, (int)peer->strikes + 1 );
2235 addStrike( t, peer );
2242 tr_pexCompare( const void * va, const void * vb )
2244 const tr_pex * a = va;
2245 const tr_pex * b = vb;
2246 int i;
2248 assert( tr_isPex( a ) );
2249 assert( tr_isPex( b ) );
2251 if(( i = tr_address_compare( &a->addr, &b->addr )))
2252 return i;
2254 if( a->port != b->port )
2255 return a->port < b->port ? -1 : 1;
2257 return 0;
2260 #if 0
2261 static int
2262 peerPrefersCrypto( const tr_peer * peer )
2264 if( peer->encryption_preference == ENCRYPTION_PREFERENCE_YES )
2265 return true;
2267 if( peer->encryption_preference == ENCRYPTION_PREFERENCE_NO )
2268 return false;
2270 return tr_peerIoIsEncrypted( peer->io );
2272 #endif
2274 /* better goes first */
2275 static int
2276 compareAtomsByUsefulness( const void * va, const void *vb )
2278 const struct peer_atom * a = * (const struct peer_atom**) va;
2279 const struct peer_atom * b = * (const struct peer_atom**) vb;
2281 assert( tr_isAtom( a ) );
2282 assert( tr_isAtom( b ) );
2284 if( a->piece_data_time != b->piece_data_time )
2285 return a->piece_data_time > b->piece_data_time ? -1 : 1;
2286 if( a->fromBest != b->fromBest )
2287 return a->fromBest < b->fromBest ? -1 : 1;
2288 if( a->numFails != b->numFails )
2289 return a->numFails < b->numFails ? -1 : 1;
2291 return 0;
2294 static bool
2295 isAtomInteresting( const tr_torrent * tor, struct peer_atom * atom )
2297 if( tr_torrentIsSeed( tor ) && atomIsSeed( atom ) )
2298 return false;
2300 if( peerIsInUse( tor->torrentPeers, atom ) )
2301 return true;
2303 if( isAtomBlocklisted( tor->session, atom ) )
2304 return false;
2306 if( atom->flags2 & MYFLAG_BANNED )
2307 return false;
2309 return true;
2313 tr_peerMgrGetPeers( tr_torrent * tor,
2314 tr_pex ** setme_pex,
2315 uint8_t af,
2316 uint8_t list_mode,
2317 int maxCount )
2319 int i;
2320 int n;
2321 int count = 0;
2322 int atomCount = 0;
2323 const Torrent * t = tor->torrentPeers;
2324 struct peer_atom ** atoms = NULL;
2325 tr_pex * pex;
2326 tr_pex * walk;
2328 assert( tr_isTorrent( tor ) );
2329 assert( setme_pex != NULL );
2330 assert( af==TR_AF_INET || af==TR_AF_INET6 );
2331 assert( list_mode==TR_PEERS_CONNECTED || list_mode==TR_PEERS_INTERESTING );
2333 managerLock( t->manager );
2336 *** build a list of atoms
2339 if( list_mode == TR_PEERS_CONNECTED ) /* connected peers only */
2341 int i;
2342 const tr_peer ** peers = (const tr_peer **) tr_ptrArrayBase( &t->peers );
2343 atomCount = tr_ptrArraySize( &t->peers );
2344 atoms = tr_new( struct peer_atom *, atomCount );
2345 for( i=0; i<atomCount; ++i )
2346 atoms[i] = peers[i]->atom;
2348 else /* TR_PEERS_INTERESTING */
2350 int i;
2351 struct peer_atom ** atomBase = (struct peer_atom**) tr_ptrArrayBase( &t->pool );
2352 n = tr_ptrArraySize( &t->pool );
2353 atoms = tr_new( struct peer_atom *, n );
2354 for( i=0; i<n; ++i )
2355 if( isAtomInteresting( tor, atomBase[i] ) )
2356 atoms[atomCount++] = atomBase[i];
2359 qsort( atoms, atomCount, sizeof( struct peer_atom * ), compareAtomsByUsefulness );
2362 *** add the first N of them into our return list
2365 n = MIN( atomCount, maxCount );
2366 pex = walk = tr_new0( tr_pex, n );
2368 for( i=0; i<atomCount && count<n; ++i )
2370 const struct peer_atom * atom = atoms[i];
2371 if( atom->addr.type == af )
2373 assert( tr_address_is_valid( &atom->addr ) );
2374 walk->addr = atom->addr;
2375 walk->port = atom->port;
2376 walk->flags = atom->flags;
2377 ++count;
2378 ++walk;
2382 qsort( pex, count, sizeof( tr_pex ), tr_pexCompare );
2384 assert( ( walk - pex ) == count );
2385 *setme_pex = pex;
2387 /* cleanup */
2388 tr_free( atoms );
2389 managerUnlock( t->manager );
2390 return count;
2393 static void atomPulse ( int, short, void * );
2394 static void bandwidthPulse ( int, short, void * );
2395 static void rechokePulse ( int, short, void * );
2396 static void reconnectPulse ( int, short, void * );
2398 static struct event *
2399 createTimer( tr_session * session, int msec, void (*callback)(int, short, void *), void * cbdata )
2401 struct event * timer = evtimer_new( session->event_base, callback, cbdata );
2402 tr_timerAddMsec( timer, msec );
2403 return timer;
2406 static void
2407 ensureMgrTimersExist( struct tr_peerMgr * m )
2409 if( m->atomTimer == NULL )
2410 m->atomTimer = createTimer( m->session, ATOM_PERIOD_MSEC, atomPulse, m );
2412 if( m->bandwidthTimer == NULL )
2413 m->bandwidthTimer = createTimer( m->session, BANDWIDTH_PERIOD_MSEC, bandwidthPulse, m );
2415 if( m->rechokeTimer == NULL )
2416 m->rechokeTimer = createTimer( m->session, RECHOKE_PERIOD_MSEC, rechokePulse, m );
2418 if( m->refillUpkeepTimer == NULL )
2419 m->refillUpkeepTimer = createTimer( m->session, REFILL_UPKEEP_PERIOD_MSEC, refillUpkeep, m );
2422 void
2423 tr_peerMgrStartTorrent( tr_torrent * tor )
2425 Torrent * t = tor->torrentPeers;
2427 assert( tr_isTorrent( tor ) );
2428 assert( tr_torrentIsLocked( tor ) );
2430 ensureMgrTimersExist( t->manager );
2432 t->isRunning = true;
2433 t->maxPeers = t->tor->maxConnectedPeers;
2434 t->pieceSortState = PIECES_UNSORTED;
2436 rechokePulse( 0, 0, t->manager );
2439 static void
2440 stopTorrent( Torrent * t )
2442 tr_peer * peer;
2444 t->isRunning = false;
2446 replicationFree( t );
2447 invalidatePieceSorting( t );
2449 /* disconnect the peers. */
2450 while(( peer = tr_ptrArrayPop( &t->peers )))
2451 peerDelete( t, peer );
2453 /* disconnect the handshakes. handshakeAbort calls handshakeDoneCB(),
2454 * which removes the handshake from t->outgoingHandshakes... */
2455 while( !tr_ptrArrayEmpty( &t->outgoingHandshakes ) )
2456 tr_handshakeAbort( tr_ptrArrayNth( &t->outgoingHandshakes, 0 ) );
2459 void
2460 tr_peerMgrStopTorrent( tr_torrent * tor )
2462 assert( tr_isTorrent( tor ) );
2463 assert( tr_torrentIsLocked( tor ) );
2465 stopTorrent( tor->torrentPeers );
2468 void
2469 tr_peerMgrAddTorrent( tr_peerMgr * manager, tr_torrent * tor )
2471 assert( tr_isTorrent( tor ) );
2472 assert( tr_torrentIsLocked( tor ) );
2473 assert( tor->torrentPeers == NULL );
2475 tor->torrentPeers = torrentNew( manager, tor );
2478 void
2479 tr_peerMgrRemoveTorrent( tr_torrent * tor )
2481 assert( tr_isTorrent( tor ) );
2482 assert( tr_torrentIsLocked( tor ) );
2484 stopTorrent( tor->torrentPeers );
2485 torrentFree( tor->torrentPeers );
2488 void
2489 tr_peerUpdateProgress( tr_torrent * tor, tr_peer * peer )
2491 const tr_bitfield * have = &peer->have;
2493 if( tr_bitfieldHasAll( have ) )
2495 peer->progress = 1.0;
2497 else if( tr_bitfieldHasNone( have ) )
2499 peer->progress = 0.0;
2501 else
2503 const float true_count = tr_bitfieldCountTrueBits( have );
2505 if( tr_torrentHasMetadata( tor ) )
2506 peer->progress = true_count / tor->info.pieceCount;
2507 else /* without pieceCount, this result is only a best guess... */
2508 peer->progress = true_count / ( have->bit_count + 1 );
2511 if( peer->atom && ( peer->progress >= 1.0 ) )
2512 atomSetSeed( tor->torrentPeers, peer->atom );
2515 void
2516 tr_peerMgrOnTorrentGotMetainfo( tr_torrent * tor )
2518 int i;
2519 const int peerCount = tr_ptrArraySize( &tor->torrentPeers->peers );
2520 tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( &tor->torrentPeers->peers );
2522 /* some peer_msgs' progress fields may not be accurate if we
2523 didn't have the metadata before now... so refresh them all... */
2524 for( i=0; i<peerCount; ++i )
2525 tr_peerUpdateProgress( tor, peers[i] );
2528 void
2529 tr_peerMgrTorrentAvailability( const tr_torrent * tor, int8_t * tab, unsigned int tabCount )
2531 assert( tr_isTorrent( tor ) );
2532 assert( torrentIsLocked( tor->torrentPeers ) );
2533 assert( tab != NULL );
2534 assert( tabCount > 0 );
2536 memset( tab, 0, tabCount );
2538 if( tr_torrentHasMetadata( tor ) )
2540 tr_piece_index_t i;
2541 const int peerCount = tr_ptrArraySize( &tor->torrentPeers->peers );
2542 const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase( &tor->torrentPeers->peers );
2543 const float interval = tor->info.pieceCount / (float)tabCount;
2544 const bool isSeed = tr_cpGetStatus( &tor->completion ) == TR_SEED;
2546 for( i=0; i<tabCount; ++i )
2548 const int piece = i * interval;
2550 if( isSeed || tr_cpPieceIsComplete( &tor->completion, piece ) )
2551 tab[i] = -1;
2552 else if( peerCount ) {
2553 int j;
2554 for( j=0; j<peerCount; ++j )
2555 if( tr_bitfieldHas( &peers[j]->have, piece ) )
2556 ++tab[i];
2562 static bool
2563 peerIsSeed( const tr_peer * peer )
2565 if( peer->progress >= 1.0 )
2566 return true;
2568 if( peer->atom && atomIsSeed( peer->atom ) )
2569 return true;
2571 return false;
2574 /* count how many bytes we want that connected peers have */
2575 uint64_t
2576 tr_peerMgrGetDesiredAvailable( const tr_torrent * tor )
2578 size_t i;
2579 size_t n;
2580 uint64_t desiredAvailable;
2581 const Torrent * t = tor->torrentPeers;
2583 /* common shortcuts... */
2585 if( tr_torrentIsSeed( t->tor ) )
2586 return 0;
2588 if( !tr_torrentHasMetadata( tor ) )
2589 return 0;
2591 n = tr_ptrArraySize( &t->peers );
2592 if( n == 0 )
2593 return 0;
2594 else {
2595 const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase( &t->peers );
2596 for( i=0; i<n; ++i )
2597 if( peers[i]->atom && atomIsSeed( peers[i]->atom ) )
2598 return tr_cpLeftUntilDone( &tor->completion );
2601 if( !t->pieceReplication || !t->pieceReplicationSize )
2602 return 0;
2604 /* do it the hard way */
2606 desiredAvailable = 0;
2607 for( i=0, n=MIN(tor->info.pieceCount, t->pieceReplicationSize); i<n; ++i )
2608 if( !tor->info.pieces[i].dnd && ( t->pieceReplication[i] > 0 ) )
2609 desiredAvailable += tr_cpMissingBytesInPiece( &t->tor->completion, i );
2611 assert( desiredAvailable <= tor->info.totalSize );
2612 return desiredAvailable;
2615 void
2616 tr_peerMgrTorrentStats( tr_torrent * tor,
2617 int * setmePeersConnected,
2618 int * setmeWebseedsSendingToUs,
2619 int * setmePeersSendingToUs,
2620 int * setmePeersGettingFromUs,
2621 int * setmePeersFrom )
2623 int i, size;
2624 const Torrent * t = tor->torrentPeers;
2625 const tr_peer ** peers;
2627 assert( tr_torrentIsLocked( tor ) );
2629 peers = (const tr_peer **) tr_ptrArrayBase( &t->peers );
2630 size = tr_ptrArraySize( &t->peers );
2632 *setmePeersConnected = 0;
2633 *setmePeersGettingFromUs = 0;
2634 *setmePeersSendingToUs = 0;
2635 *setmeWebseedsSendingToUs = 0;
2637 for( i=0; i<TR_PEER_FROM__MAX; ++i )
2638 setmePeersFrom[i] = 0;
2640 for( i=0; i<size; ++i )
2642 const tr_peer * peer = peers[i];
2643 const struct peer_atom * atom = peer->atom;
2645 if( peer->io == NULL ) /* not connected */
2646 continue;
2648 ++*setmePeersConnected;
2650 ++setmePeersFrom[atom->fromFirst];
2652 if( clientIsDownloadingFrom( tor, peer ) )
2653 ++*setmePeersSendingToUs;
2655 if( clientIsUploadingTo( peer ) )
2656 ++*setmePeersGettingFromUs;
2659 *setmeWebseedsSendingToUs = countActiveWebseeds( t );
2662 double*
2663 tr_peerMgrWebSpeeds_KBps( const tr_torrent * tor )
2665 int i;
2666 const Torrent * t = tor->torrentPeers;
2667 const int webseedCount = tr_ptrArraySize( &t->webseeds );
2668 const tr_webseed ** webseeds = (const tr_webseed**) tr_ptrArrayBase( &t->webseeds );
2669 const uint64_t now = tr_time_msec( );
2670 double * ret = tr_new0( double, webseedCount );
2672 assert( tr_isTorrent( tor ) );
2673 assert( tr_torrentIsLocked( tor ) );
2674 assert( t->manager != NULL );
2675 assert( webseedCount == tor->info.webseedCount );
2677 for( i=0; i<webseedCount; ++i ) {
2678 int Bps;
2679 if( tr_webseedGetSpeed_Bps( webseeds[i], now, &Bps ) )
2680 ret[i] = Bps / (double)tr_speed_K;
2681 else
2682 ret[i] = -1.0;
2685 return ret;
2689 tr_peerGetPieceSpeed_Bps( const tr_peer * peer, uint64_t now, tr_direction direction )
2691 return peer->io ? tr_peerIoGetPieceSpeed_Bps( peer->io, now, direction ) : 0.0;
2694 struct tr_peer_stat *
2695 tr_peerMgrPeerStats( const tr_torrent * tor, int * setmeCount )
2697 int i;
2698 const Torrent * t = tor->torrentPeers;
2699 const int size = tr_ptrArraySize( &t->peers );
2700 const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase( &t->peers );
2701 const uint64_t now_msec = tr_time_msec( );
2702 const time_t now = tr_time();
2703 tr_peer_stat * ret = tr_new0( tr_peer_stat, size );
2705 assert( tr_isTorrent( tor ) );
2706 assert( tr_torrentIsLocked( tor ) );
2707 assert( t->manager );
2709 for( i=0; i<size; ++i )
2711 char * pch;
2712 const tr_peer * peer = peers[i];
2713 const struct peer_atom * atom = peer->atom;
2714 tr_peer_stat * stat = ret + i;
2716 tr_address_to_string_with_buf( &atom->addr, stat->addr, sizeof( stat->addr ) );
2717 tr_strlcpy( stat->client, ( peer->client ? peer->client : "" ),
2718 sizeof( stat->client ) );
2719 stat->port = ntohs( peer->atom->port );
2720 stat->from = atom->fromFirst;
2721 stat->progress = peer->progress;
2722 stat->isUTP = peer->io->utp_socket != NULL;
2723 stat->isEncrypted = tr_peerIoIsEncrypted( peer->io ) ? 1 : 0;
2724 stat->rateToPeer_KBps = toSpeedKBps( tr_peerGetPieceSpeed_Bps( peer, now_msec, TR_CLIENT_TO_PEER ) );
2725 stat->rateToClient_KBps = toSpeedKBps( tr_peerGetPieceSpeed_Bps( peer, now_msec, TR_PEER_TO_CLIENT ) );
2726 stat->peerIsChoked = peer->peerIsChoked;
2727 stat->peerIsInterested = peer->peerIsInterested;
2728 stat->clientIsChoked = peer->clientIsChoked;
2729 stat->clientIsInterested = peer->clientIsInterested;
2730 stat->isIncoming = tr_peerIoIsIncoming( peer->io );
2731 stat->isDownloadingFrom = clientIsDownloadingFrom( tor, peer );
2732 stat->isUploadingTo = clientIsUploadingTo( peer );
2733 stat->isSeed = peerIsSeed( peer );
2735 stat->blocksToPeer = tr_historyGet( &peer->blocksSentToPeer, now, CANCEL_HISTORY_SEC );
2736 stat->blocksToClient = tr_historyGet( &peer->blocksSentToClient, now, CANCEL_HISTORY_SEC );
2737 stat->cancelsToPeer = tr_historyGet( &peer->cancelsSentToPeer, now, CANCEL_HISTORY_SEC );
2738 stat->cancelsToClient = tr_historyGet( &peer->cancelsSentToClient, now, CANCEL_HISTORY_SEC );
2740 stat->pendingReqsToPeer = peer->pendingReqsToPeer;
2741 stat->pendingReqsToClient = peer->pendingReqsToClient;
2743 pch = stat->flagStr;
2744 if( stat->isUTP ) *pch++ = 'T';
2745 if( t->optimistic == peer ) *pch++ = 'O';
2746 if( stat->isDownloadingFrom ) *pch++ = 'D';
2747 else if( stat->clientIsInterested ) *pch++ = 'd';
2748 if( stat->isUploadingTo ) *pch++ = 'U';
2749 else if( stat->peerIsInterested ) *pch++ = 'u';
2750 if( !stat->clientIsChoked && !stat->clientIsInterested ) *pch++ = 'K';
2751 if( !stat->peerIsChoked && !stat->peerIsInterested ) *pch++ = '?';
2752 if( stat->isEncrypted ) *pch++ = 'E';
2753 if( stat->from == TR_PEER_FROM_DHT ) *pch++ = 'H';
2754 else if( stat->from == TR_PEER_FROM_PEX ) *pch++ = 'X';
2755 if( stat->isIncoming ) *pch++ = 'I';
2756 *pch = '\0';
2759 *setmeCount = size;
2761 return ret;
2764 /***
2765 ****
2766 ****
2767 ***/
2769 void
2770 tr_peerMgrClearInterest( tr_torrent * tor )
2772 int i;
2773 Torrent * t = tor->torrentPeers;
2774 const int peerCount = tr_ptrArraySize( &t->peers );
2776 assert( tr_isTorrent( tor ) );
2777 assert( tr_torrentIsLocked( tor ) );
2779 for( i=0; i<peerCount; ++i )
2781 const tr_peer * peer = tr_ptrArrayNth( &t->peers, i );
2782 tr_peerMsgsSetInterested( peer->msgs, false );
2786 /* does this peer have any pieces that we want? */
2787 static bool
2788 isPeerInteresting( const tr_torrent * const tor,
2789 const tr_bitfield * const interesting_pieces,
2790 const tr_peer * const peer )
2792 tr_piece_index_t i, n;
2794 /* these cases should have already been handled by the calling code... */
2795 assert( !tr_torrentIsSeed( tor ) );
2796 assert( tr_torrentIsPieceTransferAllowed( tor, TR_PEER_TO_CLIENT ) );
2798 if( peerIsSeed( peer ) )
2799 return true;
2801 for( i=0, n=tor->info.pieceCount; i<n; ++i )
2802 if( tr_bitfieldHas( interesting_pieces, i ) && tr_bitfieldHas( &peer->have, i ) )
2803 return true;
2805 return false;
2808 typedef enum
2810 RECHOKE_STATE_GOOD,
2811 RECHOKE_STATE_UNTESTED,
2812 RECHOKE_STATE_BAD
2814 tr_rechoke_state;
2816 struct tr_rechoke_info
2818 tr_peer * peer;
2819 int salt;
2820 int rechoke_state;
2823 static int
2824 compare_rechoke_info( const void * va, const void * vb )
2826 const struct tr_rechoke_info * a = va;
2827 const struct tr_rechoke_info * b = vb;
2829 if( a->rechoke_state != b->rechoke_state )
2830 return a->rechoke_state - b->rechoke_state;
2832 return a->salt - b->salt;
2835 /* determines who we send "interested" messages to */
2836 static void
2837 rechokeDownloads( Torrent * t )
2839 int i;
2840 int maxPeers = 0;
2841 int rechoke_count = 0;
2842 struct tr_rechoke_info * rechoke = NULL;
2843 const int MIN_INTERESTING_PEERS = 5;
2844 const int peerCount = tr_ptrArraySize( &t->peers );
2845 const time_t now = tr_time( );
2847 /* some cases where this function isn't necessary */
2848 if( tr_torrentIsSeed( t->tor ) )
2849 return;
2850 if ( !tr_torrentIsPieceTransferAllowed( t->tor, TR_PEER_TO_CLIENT ) )
2851 return;
2853 /* decide HOW MANY peers to be interested in */
2855 int blocks = 0;
2856 int cancels = 0;
2857 time_t timeSinceCancel;
2859 /* Count up how many blocks & cancels each peer has.
2861 * There are two situations where we send out cancels --
2863 * 1. We've got unresponsive peers, which is handled by deciding
2864 * -which- peers to be interested in.
2866 * 2. We've hit our bandwidth cap, which is handled by deciding
2867 * -how many- peers to be interested in.
2869 * We're working on 2. here, so we need to ignore unresponsive
2870 * peers in our calculations lest they confuse Transmission into
2871 * thinking it's hit its bandwidth cap.
2873 for( i=0; i<peerCount; ++i )
2875 const tr_peer * peer = tr_ptrArrayNth( &t->peers, i );
2876 const int b = tr_historyGet( &peer->blocksSentToClient, now, CANCEL_HISTORY_SEC );
2877 const int c = tr_historyGet( &peer->cancelsSentToPeer, now, CANCEL_HISTORY_SEC );
2879 if( b == 0 ) /* ignore unresponsive peers, as described above */
2880 continue;
2882 blocks += b;
2883 cancels += c;
2886 if( cancels > 0 )
2888 /* cancelRate: of the block requests we've recently made, the percentage we cancelled.
2889 * higher values indicate more congestion. */
2890 const double cancelRate = cancels / (double)(cancels + blocks);
2891 const double mult = 1 - MIN( cancelRate, 0.5 );
2892 maxPeers = t->interestedCount * mult;
2893 tordbg( t, "cancel rate is %.3f -- reducing the "
2894 "number of peers we're interested in by %.0f percent",
2895 cancelRate, mult * 100 );
2896 t->lastCancel = now;
2899 timeSinceCancel = now - t->lastCancel;
2900 if( timeSinceCancel )
2902 const int maxIncrease = 15;
2903 const time_t maxHistory = 2 * CANCEL_HISTORY_SEC;
2904 const double mult = MIN( timeSinceCancel, maxHistory ) / (double) maxHistory;
2905 const int inc = maxIncrease * mult;
2906 maxPeers = t->maxPeers + inc;
2907 tordbg( t, "time since last cancel is %li -- increasing the "
2908 "number of peers we're interested in by %d",
2909 timeSinceCancel, inc );
2913 /* don't let the previous section's number tweaking go too far... */
2914 if( maxPeers < MIN_INTERESTING_PEERS )
2915 maxPeers = MIN_INTERESTING_PEERS;
2916 if( maxPeers > t->tor->maxConnectedPeers )
2917 maxPeers = t->tor->maxConnectedPeers;
2919 t->maxPeers = maxPeers;
2921 if( peerCount > 0 )
2923 const tr_torrent * const tor = t->tor;
2924 const int n = tor->info.pieceCount;
2925 tr_bitfield interesting_pieces = TR_BITFIELD_INIT;
2927 /* build a bitfield of interesting pieces... */
2928 tr_bitfieldConstruct( &interesting_pieces, n );
2929 for( i=0; i<n; i++ )
2930 if( !tor->info.pieces[i].dnd && !tr_cpPieceIsComplete( &tor->completion, i ) )
2931 tr_bitfieldAdd( &interesting_pieces, i );
2933 /* decide WHICH peers to be interested in (based on their cancel-to-block ratio) */
2934 for( i=0; i<peerCount; ++i )
2936 tr_peer * peer = tr_ptrArrayNth( &t->peers, i );
2938 if( !isPeerInteresting( t->tor, &interesting_pieces, peer ) )
2940 tr_peerMsgsSetInterested( peer->msgs, false );
2942 else
2944 tr_rechoke_state rechoke_state;
2945 const int blocks = tr_historyGet( &peer->blocksSentToClient, now, CANCEL_HISTORY_SEC );
2946 const int cancels = tr_historyGet( &peer->cancelsSentToPeer, now, CANCEL_HISTORY_SEC );
2948 if( !blocks && !cancels )
2949 rechoke_state = RECHOKE_STATE_UNTESTED;
2950 else if( !cancels )
2951 rechoke_state = RECHOKE_STATE_GOOD;
2952 else if( !blocks )
2953 rechoke_state = RECHOKE_STATE_BAD;
2954 else if( ( cancels * 10 ) < blocks )
2955 rechoke_state = RECHOKE_STATE_GOOD;
2956 else
2957 rechoke_state = RECHOKE_STATE_BAD;
2959 if( rechoke == NULL )
2960 rechoke = tr_new( struct tr_rechoke_info, peerCount );
2962 rechoke[rechoke_count].peer = peer;
2963 rechoke[rechoke_count].rechoke_state = rechoke_state;
2964 rechoke[rechoke_count].salt = tr_cryptoWeakRandInt( INT_MAX );
2965 rechoke_count++;
2970 tr_bitfieldDestruct( &interesting_pieces );
2973 /* now that we know which & how many peers to be interested in... update the peer interest */
2974 qsort( rechoke, rechoke_count, sizeof( struct tr_rechoke_info ), compare_rechoke_info );
2975 t->interestedCount = MIN( maxPeers, rechoke_count );
2976 for( i=0; i<rechoke_count; ++i )
2977 tr_peerMsgsSetInterested( rechoke[i].peer->msgs, i<t->interestedCount );
2979 /* cleanup */
2980 tr_free( rechoke );
2987 struct ChokeData
2989 bool isInterested;
2990 bool wasChoked;
2991 bool isChoked;
2992 int rate;
2993 int salt;
2994 tr_peer * peer;
2997 static int
2998 compareChoke( const void * va, const void * vb )
3000 const struct ChokeData * a = va;
3001 const struct ChokeData * b = vb;
3003 if( a->rate != b->rate ) /* prefer higher overall speeds */
3004 return a->rate > b->rate ? -1 : 1;
3006 if( a->wasChoked != b->wasChoked ) /* prefer unchoked */
3007 return a->wasChoked ? 1 : -1;
3009 if( a->salt != b->salt ) /* random order */
3010 return a->salt - b->salt;
3012 return 0;
3015 /* is this a new connection? */
3016 static int
3017 isNew( const tr_peer * peer )
3019 return peer && peer->io && tr_peerIoGetAge( peer->io ) < 45;
3022 /* get a rate for deciding which peers to choke and unchoke. */
3023 static int
3024 getRate( const tr_torrent * tor, struct peer_atom * atom, uint64_t now )
3026 int Bps;
3028 if( tr_torrentIsSeed( tor ) )
3029 Bps = tr_peerGetPieceSpeed_Bps( atom->peer, now, TR_CLIENT_TO_PEER );
3031 /* downloading a private torrent... take upload speed into account
3032 * because there may only be a small window of opportunity to share */
3033 else if( tr_torrentIsPrivate( tor ) )
3034 Bps = tr_peerGetPieceSpeed_Bps( atom->peer, now, TR_PEER_TO_CLIENT )
3035 + tr_peerGetPieceSpeed_Bps( atom->peer, now, TR_CLIENT_TO_PEER );
3037 /* downloading a public torrent */
3038 else
3039 Bps = tr_peerGetPieceSpeed_Bps( atom->peer, now, TR_PEER_TO_CLIENT );
3041 /* convert it to bytes per second */
3042 return Bps;
3045 static inline bool
3046 isBandwidthMaxedOut( const tr_bandwidth * b,
3047 const uint64_t now_msec, tr_direction dir )
3049 if( !tr_bandwidthIsLimited( b, dir ) )
3050 return false;
3051 else {
3052 const int got = tr_bandwidthGetPieceSpeed_Bps( b, now_msec, dir );
3053 const int want = tr_bandwidthGetDesiredSpeed_Bps( b, dir );
3054 return got >= want;
3058 static void
3059 rechokeUploads( Torrent * t, const uint64_t now )
3061 int i, size, unchokedInterested;
3062 const int peerCount = tr_ptrArraySize( &t->peers );
3063 tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( &t->peers );
3064 struct ChokeData * choke = tr_new0( struct ChokeData, peerCount );
3065 const tr_session * session = t->manager->session;
3066 const int chokeAll = !tr_torrentIsPieceTransferAllowed( t->tor, TR_CLIENT_TO_PEER );
3067 const bool isMaxedOut = isBandwidthMaxedOut( &t->tor->bandwidth, now, TR_UP );
3069 assert( torrentIsLocked( t ) );
3071 /* an optimistic unchoke peer's "optimistic"
3072 * state lasts for N calls to rechokeUploads(). */
3073 if( t->optimisticUnchokeTimeScaler > 0 )
3074 t->optimisticUnchokeTimeScaler--;
3075 else
3076 t->optimistic = NULL;
3078 /* sort the peers by preference and rate */
3079 for( i = 0, size = 0; i < peerCount; ++i )
3081 tr_peer * peer = peers[i];
3082 struct peer_atom * atom = peer->atom;
3084 if( peerIsSeed( peer ) ) /* choke seeds and partial seeds */
3086 tr_peerMsgsSetChoke( peer->msgs, true );
3088 else if( chokeAll ) /* choke everyone if we're not uploading */
3090 tr_peerMsgsSetChoke( peer->msgs, true );
3092 else if( peer != t->optimistic )
3094 struct ChokeData * n = &choke[size++];
3095 n->peer = peer;
3096 n->isInterested = peer->peerIsInterested;
3097 n->wasChoked = peer->peerIsChoked;
3098 n->rate = getRate( t->tor, atom, now );
3099 n->salt = tr_cryptoWeakRandInt( INT_MAX );
3100 n->isChoked = true;
3104 qsort( choke, size, sizeof( struct ChokeData ), compareChoke );
3107 * Reciprocation and number of uploads capping is managed by unchoking
3108 * the N peers which have the best upload rate and are interested.
3109 * This maximizes the client's download rate. These N peers are
3110 * referred to as downloaders, because they are interested in downloading
3111 * from the client.
3113 * Peers which have a better upload rate (as compared to the downloaders)
3114 * but aren't interested get unchoked. If they become interested, the
3115 * downloader with the worst upload rate gets choked. If a client has
3116 * a complete file, it uses its upload rate rather than its download
3117 * rate to decide which peers to unchoke.
3119 * If our bandwidth is maxed out, don't unchoke any more peers.
3121 unchokedInterested = 0;
3122 for( i=0; i<size && unchokedInterested<session->uploadSlotsPerTorrent; ++i ) {
3123 choke[i].isChoked = isMaxedOut ? choke[i].wasChoked : false;
3124 if( choke[i].isInterested )
3125 ++unchokedInterested;
3128 /* optimistic unchoke */
3129 if( !t->optimistic && !isMaxedOut && (i<size) )
3131 int n;
3132 struct ChokeData * c;
3133 tr_ptrArray randPool = TR_PTR_ARRAY_INIT;
3135 for( ; i<size; ++i )
3137 if( choke[i].isInterested )
3139 const tr_peer * peer = choke[i].peer;
3140 int x = 1, y;
3141 if( isNew( peer ) ) x *= 3;
3142 for( y=0; y<x; ++y )
3143 tr_ptrArrayAppend( &randPool, &choke[i] );
3147 if(( n = tr_ptrArraySize( &randPool )))
3149 c = tr_ptrArrayNth( &randPool, tr_cryptoWeakRandInt( n ));
3150 c->isChoked = false;
3151 t->optimistic = c->peer;
3152 t->optimisticUnchokeTimeScaler = OPTIMISTIC_UNCHOKE_MULTIPLIER;
3155 tr_ptrArrayDestruct( &randPool, NULL );
3158 for( i=0; i<size; ++i )
3159 tr_peerMsgsSetChoke( choke[i].peer->msgs, choke[i].isChoked );
3161 /* cleanup */
3162 tr_free( choke );
3165 static void
3166 rechokePulse( int foo UNUSED, short bar UNUSED, void * vmgr )
3168 tr_torrent * tor = NULL;
3169 tr_peerMgr * mgr = vmgr;
3170 const uint64_t now = tr_time_msec( );
3172 managerLock( mgr );
3174 while(( tor = tr_torrentNext( mgr->session, tor ))) {
3175 if( tor->isRunning ) {
3176 Torrent * t = tor->torrentPeers;
3177 if( !tr_ptrArrayEmpty( &t->peers ) ) {
3178 rechokeUploads( t, now );
3179 rechokeDownloads( t );
3184 tr_timerAddMsec( mgr->rechokeTimer, RECHOKE_PERIOD_MSEC );
3185 managerUnlock( mgr );
3188 /***
3189 ****
3190 **** Life and Death
3191 ****
3192 ***/
3194 static bool
3195 shouldPeerBeClosed( const Torrent * t,
3196 const tr_peer * peer,
3197 int peerCount,
3198 const time_t now )
3200 const tr_torrent * tor = t->tor;
3201 const struct peer_atom * atom = peer->atom;
3203 /* if it's marked for purging, close it */
3204 if( peer->doPurge )
3206 tordbg( t, "purging peer %s because its doPurge flag is set",
3207 tr_atomAddrStr( atom ) );
3208 return true;
3211 /* disconnect if we're both seeds and enough time has passed for PEX */
3212 if( tr_torrentIsSeed( tor ) && peerIsSeed( peer ) )
3213 return !tr_torrentAllowsPex(tor) || (now-atom->time>=30);
3215 /* disconnect if it's been too long since piece data has been transferred.
3216 * this is on a sliding scale based on number of available peers... */
3218 const int relaxStrictnessIfFewerThanN = (int)( ( getMaxPeerCount( tor ) * 0.9 ) + 0.5 );
3219 /* if we have >= relaxIfFewerThan, strictness is 100%.
3220 * if we have zero connections, strictness is 0% */
3221 const float strictness = peerCount >= relaxStrictnessIfFewerThanN
3222 ? 1.0
3223 : peerCount / (float)relaxStrictnessIfFewerThanN;
3224 const int lo = MIN_UPLOAD_IDLE_SECS;
3225 const int hi = MAX_UPLOAD_IDLE_SECS;
3226 const int limit = hi - ( ( hi - lo ) * strictness );
3227 const int idleTime = now - MAX( atom->time, atom->piece_data_time );
3228 /*fprintf( stderr, "strictness is %.3f, limit is %d seconds... time since connect is %d, time since piece is %d ... idleTime is %d, doPurge is %d\n", (double)strictness, limit, (int)(now - atom->time), (int)(now - atom->piece_data_time), idleTime, idleTime > limit );*/
3229 if( idleTime > limit ) {
3230 tordbg( t, "purging peer %s because it's been %d secs since we shared anything",
3231 tr_atomAddrStr( atom ), idleTime );
3232 return true;
3236 return false;
3239 static tr_peer **
3240 getPeersToClose( Torrent * t, const time_t now_sec, int * setmeSize )
3242 int i, peerCount, outsize;
3243 struct tr_peer ** ret = NULL;
3244 tr_peer ** peers = (tr_peer**) tr_ptrArrayPeek( &t->peers, &peerCount );
3246 assert( torrentIsLocked( t ) );
3248 for( i = outsize = 0; i < peerCount; ++i ) {
3249 if( shouldPeerBeClosed( t, peers[i], peerCount, now_sec ) ) {
3250 if( ret == NULL )
3251 ret = tr_new( tr_peer *, peerCount );
3252 ret[outsize++] = peers[i];
3256 *setmeSize = outsize;
3257 return ret;
3260 static int
3261 getReconnectIntervalSecs( const struct peer_atom * atom, const time_t now )
3263 int sec;
3265 /* if we were recently connected to this peer and transferring piece
3266 * data, try to reconnect to them sooner rather that later -- we don't
3267 * want network troubles to get in the way of a good peer. */
3268 if( ( now - atom->piece_data_time ) <= ( MINIMUM_RECONNECT_INTERVAL_SECS * 2 ) )
3269 sec = MINIMUM_RECONNECT_INTERVAL_SECS;
3271 /* don't allow reconnects more often than our minimum */
3272 else if( ( now - atom->time ) < MINIMUM_RECONNECT_INTERVAL_SECS )
3273 sec = MINIMUM_RECONNECT_INTERVAL_SECS;
3275 /* otherwise, the interval depends on how many times we've tried
3276 * and failed to connect to the peer */
3277 else switch( atom->numFails ) {
3278 case 0: sec = 0; break;
3279 case 1: sec = 5; break;
3280 case 2: sec = 2 * 60; break;
3281 case 3: sec = 15 * 60; break;
3282 case 4: sec = 30 * 60; break;
3283 case 5: sec = 60 * 60; break;
3284 default: sec = 120 * 60; break;
3287 /* penalize peers that were unreachable the last time we tried */
3288 if( atom->flags2 & MYFLAG_UNREACHABLE )
3289 sec += sec;
3291 dbgmsg( "reconnect interval for %s is %d seconds", tr_atomAddrStr( atom ), sec );
3292 return sec;
3295 static void
3296 removePeer( Torrent * t, tr_peer * peer )
3298 tr_peer * removed;
3299 struct peer_atom * atom = peer->atom;
3301 assert( torrentIsLocked( t ) );
3302 assert( atom );
3304 atom->time = tr_time( );
3306 removed = tr_ptrArrayRemoveSorted( &t->peers, peer, peerCompare );
3308 if( replicationExists( t ) )
3309 tr_decrReplicationFromBitfield( t, &peer->have );
3311 assert( removed == peer );
3312 peerDelete( t, removed );
3315 static void
3316 closePeer( Torrent * t, tr_peer * peer )
3318 struct peer_atom * atom;
3320 assert( t != NULL );
3321 assert( peer != NULL );
3323 atom = peer->atom;
3325 /* if we transferred piece data, then they might be good peers,
3326 so reset their `numFails' weight to zero. otherwise we connected
3327 to them fruitlessly, so mark it as another fail */
3328 if( atom->piece_data_time ) {
3329 tordbg( t, "resetting atom %s numFails to 0", tr_atomAddrStr(atom) );
3330 atom->numFails = 0;
3331 } else {
3332 ++atom->numFails;
3333 tordbg( t, "incremented atom %s numFails to %d", tr_atomAddrStr(atom), (int)atom->numFails );
3336 tordbg( t, "removing bad peer %s", tr_peerIoGetAddrStr( peer->io ) );
3337 removePeer( t, peer );
3340 static void
3341 removeAllPeers( Torrent * t )
3343 while( !tr_ptrArrayEmpty( &t->peers ) )
3344 removePeer( t, tr_ptrArrayNth( &t->peers, 0 ) );
3347 static void
3348 closeBadPeers( Torrent * t, const time_t now_sec )
3350 if( !tr_ptrArrayEmpty( &t->peers ) )
3352 int i;
3353 int peerCount;
3354 struct tr_peer ** peers = getPeersToClose( t, now_sec, &peerCount );
3355 for( i=0; i<peerCount; ++i )
3356 closePeer( t, peers[i] );
3357 tr_free( peers );
3361 struct peer_liveliness
3363 tr_peer * peer;
3364 void * clientData;
3365 time_t pieceDataTime;
3366 time_t time;
3367 int speed;
3368 bool doPurge;
3371 static int
3372 comparePeerLiveliness( const void * va, const void * vb )
3374 const struct peer_liveliness * a = va;
3375 const struct peer_liveliness * b = vb;
3377 if( a->doPurge != b->doPurge )
3378 return a->doPurge ? 1 : -1;
3380 if( a->speed != b->speed ) /* faster goes first */
3381 return a->speed > b->speed ? -1 : 1;
3383 /* the one to give us data more recently goes first */
3384 if( a->pieceDataTime != b->pieceDataTime )
3385 return a->pieceDataTime > b->pieceDataTime ? -1 : 1;
3387 /* the one we connected to most recently goes first */
3388 if( a->time != b->time )
3389 return a->time > b->time ? -1 : 1;
3391 return 0;
3394 static void
3395 sortPeersByLivelinessImpl( tr_peer ** peers,
3396 void ** clientData,
3397 int n,
3398 uint64_t now,
3399 int (*compare) ( const void *va, const void *vb ) )
3401 int i;
3402 struct peer_liveliness *lives, *l;
3404 /* build a sortable array of peer + extra info */
3405 lives = l = tr_new0( struct peer_liveliness, n );
3406 for( i=0; i<n; ++i, ++l )
3408 tr_peer * p = peers[i];
3409 l->peer = p;
3410 l->doPurge = p->doPurge;
3411 l->pieceDataTime = p->atom->piece_data_time;
3412 l->time = p->atom->time;
3413 l->speed = tr_peerGetPieceSpeed_Bps( p, now, TR_UP )
3414 + tr_peerGetPieceSpeed_Bps( p, now, TR_DOWN );
3415 if( clientData )
3416 l->clientData = clientData[i];
3419 /* sort 'em */
3420 assert( n == ( l - lives ) );
3421 qsort( lives, n, sizeof( struct peer_liveliness ), compare );
3423 /* build the peer array */
3424 for( i=0, l=lives; i<n; ++i, ++l ) {
3425 peers[i] = l->peer;
3426 if( clientData )
3427 clientData[i] = l->clientData;
3429 assert( n == ( l - lives ) );
3431 /* cleanup */
3432 tr_free( lives );
3435 static void
3436 sortPeersByLiveliness( tr_peer ** peers, void ** clientData, int n, uint64_t now )
3438 sortPeersByLivelinessImpl( peers, clientData, n, now, comparePeerLiveliness );
3442 static void
3443 enforceTorrentPeerLimit( Torrent * t, uint64_t now )
3445 int n = tr_ptrArraySize( &t->peers );
3446 const int max = tr_torrentGetPeerLimit( t->tor );
3447 if( n > max )
3449 void * base = tr_ptrArrayBase( &t->peers );
3450 tr_peer ** peers = tr_memdup( base, n*sizeof( tr_peer* ) );
3451 sortPeersByLiveliness( peers, NULL, n, now );
3452 while( n > max )
3453 closePeer( t, peers[--n] );
3454 tr_free( peers );
3458 static void
3459 enforceSessionPeerLimit( tr_session * session, uint64_t now )
3461 int n = 0;
3462 tr_torrent * tor = NULL;
3463 const int max = tr_sessionGetPeerLimit( session );
3465 /* count the total number of peers */
3466 while(( tor = tr_torrentNext( session, tor )))
3467 n += tr_ptrArraySize( &tor->torrentPeers->peers );
3469 /* if there are too many, prune out the worst */
3470 if( n > max )
3472 tr_peer ** peers = tr_new( tr_peer*, n );
3473 Torrent ** torrents = tr_new( Torrent*, n );
3475 /* populate the peer array */
3476 n = 0;
3477 tor = NULL;
3478 while(( tor = tr_torrentNext( session, tor ))) {
3479 int i;
3480 Torrent * t = tor->torrentPeers;
3481 const int tn = tr_ptrArraySize( &t->peers );
3482 for( i=0; i<tn; ++i, ++n ) {
3483 peers[n] = tr_ptrArrayNth( &t->peers, i );
3484 torrents[n] = t;
3488 /* sort 'em */
3489 sortPeersByLiveliness( peers, (void**)torrents, n, now );
3491 /* cull out the crappiest */
3492 while( n-- > max )
3493 closePeer( torrents[n], peers[n] );
3495 /* cleanup */
3496 tr_free( torrents );
3497 tr_free( peers );
3501 static void makeNewPeerConnections( tr_peerMgr * mgr, const int max );
3503 static void
3504 reconnectPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
3506 tr_torrent * tor;
3507 tr_peerMgr * mgr = vmgr;
3508 const time_t now_sec = tr_time( );
3509 const uint64_t now_msec = tr_time_msec( );
3512 *** enforce the per-session and per-torrent peer limits
3515 /* if we're over the per-torrent peer limits, cull some peers */
3516 tor = NULL;
3517 while(( tor = tr_torrentNext( mgr->session, tor )))
3518 if( tor->isRunning )
3519 enforceTorrentPeerLimit( tor->torrentPeers, now_msec );
3521 /* if we're over the per-session peer limits, cull some peers */
3522 enforceSessionPeerLimit( mgr->session, now_msec );
3524 /* remove crappy peers */
3525 tor = NULL;
3526 while(( tor = tr_torrentNext( mgr->session, tor )))
3527 if( !tor->torrentPeers->isRunning )
3528 removeAllPeers( tor->torrentPeers );
3529 else
3530 closeBadPeers( tor->torrentPeers, now_sec );
3532 /* try to make new peer connections */
3533 makeNewPeerConnections( mgr, MAX_CONNECTIONS_PER_PULSE );
3536 /****
3537 *****
3538 ***** BANDWIDTH ALLOCATION
3539 *****
3540 ****/
3542 static void
3543 pumpAllPeers( tr_peerMgr * mgr )
3545 tr_torrent * tor = NULL;
3547 while(( tor = tr_torrentNext( mgr->session, tor )))
3549 int j;
3550 Torrent * t = tor->torrentPeers;
3552 for( j=0; j<tr_ptrArraySize( &t->peers ); ++j )
3554 tr_peer * peer = tr_ptrArrayNth( &t->peers, j );
3555 tr_peerMsgsPulse( peer->msgs );
3560 static void
3561 bandwidthPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
3563 tr_torrent * tor;
3564 tr_peerMgr * mgr = vmgr;
3565 managerLock( mgr );
3567 /* FIXME: this next line probably isn't necessary... */
3568 pumpAllPeers( mgr );
3570 /* allocate bandwidth to the peers */
3571 tr_bandwidthAllocate( &mgr->session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
3572 tr_bandwidthAllocate( &mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
3574 /* torrent upkeep */
3575 tor = NULL;
3576 while(( tor = tr_torrentNext( mgr->session, tor )))
3578 /* possibly stop torrents that have seeded enough */
3579 tr_torrentCheckSeedLimit( tor );
3581 /* run the completeness check for any torrents that need it */
3582 if( tor->torrentPeers->needsCompletenessCheck ) {
3583 tor->torrentPeers->needsCompletenessCheck = false;
3584 tr_torrentRecheckCompleteness( tor );
3587 /* stop torrents that are ready to stop, but couldn't be stopped
3588 earlier during the peer-io callback call chain */
3589 if( tor->isStopping )
3590 tr_torrentStop( tor );
3593 reconnectPulse( 0, 0, mgr );
3595 tr_timerAddMsec( mgr->bandwidthTimer, BANDWIDTH_PERIOD_MSEC );
3596 managerUnlock( mgr );
3599 /***
3600 ****
3601 ***/
3603 static int
3604 compareAtomPtrsByAddress( const void * va, const void *vb )
3606 const struct peer_atom * a = * (const struct peer_atom**) va;
3607 const struct peer_atom * b = * (const struct peer_atom**) vb;
3609 assert( tr_isAtom( a ) );
3610 assert( tr_isAtom( b ) );
3612 return tr_address_compare( &a->addr, &b->addr );
3615 /* best come first, worst go last */
3616 static int
3617 compareAtomPtrsByShelfDate( const void * va, const void *vb )
3619 time_t atime;
3620 time_t btime;
3621 const struct peer_atom * a = * (const struct peer_atom**) va;
3622 const struct peer_atom * b = * (const struct peer_atom**) vb;
3623 const int data_time_cutoff_secs = 60 * 60;
3624 const time_t tr_now = tr_time( );
3626 assert( tr_isAtom( a ) );
3627 assert( tr_isAtom( b ) );
3629 /* primary key: the last piece data time *if* it was within the last hour */
3630 atime = a->piece_data_time; if( atime + data_time_cutoff_secs < tr_now ) atime = 0;
3631 btime = b->piece_data_time; if( btime + data_time_cutoff_secs < tr_now ) btime = 0;
3632 if( atime != btime )
3633 return atime > btime ? -1 : 1;
3635 /* secondary key: shelf date. */
3636 if( a->shelf_date != b->shelf_date )
3637 return a->shelf_date > b->shelf_date ? -1 : 1;
3639 return 0;
3642 static int
3643 getMaxAtomCount( const tr_torrent * tor )
3645 const int n = tor->maxConnectedPeers;
3646 /* approximate fit of the old jump discontinuous function */
3647 if( n >= 55 ) return n + 150;
3648 if( n >= 20 ) return 2 * n + 95;
3649 return 4 * n + 55;
3652 static void
3653 atomPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
3655 tr_torrent * tor = NULL;
3656 tr_peerMgr * mgr = vmgr;
3657 managerLock( mgr );
3659 while(( tor = tr_torrentNext( mgr->session, tor )))
3661 int atomCount;
3662 Torrent * t = tor->torrentPeers;
3663 const int maxAtomCount = getMaxAtomCount( tor );
3664 struct peer_atom ** atoms = (struct peer_atom**) tr_ptrArrayPeek( &t->pool, &atomCount );
3666 if( atomCount > maxAtomCount ) /* we've got too many atoms... time to prune */
3668 int i;
3669 int keepCount = 0;
3670 int testCount = 0;
3671 struct peer_atom ** keep = tr_new( struct peer_atom*, atomCount );
3672 struct peer_atom ** test = tr_new( struct peer_atom*, atomCount );
3674 /* keep the ones that are in use */
3675 for( i=0; i<atomCount; ++i ) {
3676 struct peer_atom * atom = atoms[i];
3677 if( peerIsInUse( t, atom ) )
3678 keep[keepCount++] = atom;
3679 else
3680 test[testCount++] = atom;
3683 /* if there's room, keep the best of what's left */
3684 i = 0;
3685 if( keepCount < maxAtomCount ) {
3686 qsort( test, testCount, sizeof( struct peer_atom * ), compareAtomPtrsByShelfDate );
3687 while( i<testCount && keepCount<maxAtomCount )
3688 keep[keepCount++] = test[i++];
3691 /* free the culled atoms */
3692 while( i<testCount )
3693 tr_free( test[i++] );
3695 /* rebuild Torrent.pool with what's left */
3696 tr_ptrArrayDestruct( &t->pool, NULL );
3697 t->pool = TR_PTR_ARRAY_INIT;
3698 qsort( keep, keepCount, sizeof( struct peer_atom * ), compareAtomPtrsByAddress );
3699 for( i=0; i<keepCount; ++i )
3700 tr_ptrArrayAppend( &t->pool, keep[i] );
3702 tordbg( t, "max atom count is %d... pruned from %d to %d\n", maxAtomCount, atomCount, keepCount );
3704 /* cleanup */
3705 tr_free( test );
3706 tr_free( keep );
3710 tr_timerAddMsec( mgr->atomTimer, ATOM_PERIOD_MSEC );
3711 managerUnlock( mgr );
3714 /***
3715 ****
3716 ****
3717 ****
3718 ***/
3720 /* is this atom someone that we'd want to initiate a connection to? */
3721 static bool
3722 isPeerCandidate( const tr_torrent * tor, struct peer_atom * atom, const time_t now )
3724 /* not if we're both seeds */
3725 if( tr_torrentIsSeed( tor ) && atomIsSeed( atom ) )
3726 return false;
3728 /* not if we've already got a connection to them... */
3729 if( peerIsInUse( tor->torrentPeers, atom ) )
3730 return false;
3732 /* not if we just tried them already */
3733 if( ( now - atom->time ) < getReconnectIntervalSecs( atom, now ) )
3734 return false;
3736 /* not if they're blocklisted */
3737 if( isAtomBlocklisted( tor->session, atom ) )
3738 return false;
3740 /* not if they're banned... */
3741 if( atom->flags2 & MYFLAG_BANNED )
3742 return false;
3744 return true;
3747 struct peer_candidate
3749 uint64_t score;
3750 tr_torrent * tor;
3751 struct peer_atom * atom;
3754 static bool
3755 torrentWasRecentlyStarted( const tr_torrent * tor )
3757 return difftime( tr_time( ), tor->startDate ) < 120;
3760 static inline uint64_t
3761 addValToKey( uint64_t value, int width, uint64_t addme )
3763 value = (value << (uint64_t)width);
3764 value |= addme;
3765 return value;
3768 /* smaller value is better */
3769 static uint64_t
3770 getPeerCandidateScore( const tr_torrent * tor, const struct peer_atom * atom, uint8_t salt )
3772 uint64_t i;
3773 uint64_t score = 0;
3774 const bool failed = atom->lastConnectionAt < atom->lastConnectionAttemptAt;
3776 /* prefer peers we've connected to, or never tried, over peers we failed to connect to. */
3777 i = failed ? 1 : 0;
3778 score = addValToKey( score, 1, i );
3780 /* prefer the one we attempted least recently (to cycle through all peers) */
3781 i = atom->lastConnectionAttemptAt;
3782 score = addValToKey( score, 32, i );
3784 /* prefer peers belonging to a torrent of a higher priority */
3785 switch( tr_torrentGetPriority( tor ) ) {
3786 case TR_PRI_HIGH: i = 0; break;
3787 case TR_PRI_NORMAL: i = 1; break;
3788 case TR_PRI_LOW: i = 2; break;
3790 score = addValToKey( score, 4, i );
3792 /* prefer recently-started torrents */
3793 i = torrentWasRecentlyStarted( tor ) ? 0 : 1;
3794 score = addValToKey( score, 1, i );
3796 /* prefer torrents we're downloading with */
3797 i = tr_torrentIsSeed( tor ) ? 1 : 0;
3798 score = addValToKey( score, 1, i );
3800 /* prefer peers that are known to be connectible */
3801 i = ( atom->flags & ADDED_F_CONNECTABLE ) ? 0 : 1;
3802 score = addValToKey( score, 1, i );
3804 /* prefer peers that we might have a chance of uploading to...
3805 so lower seed probability is better */
3806 if( atom->seedProbability == 100 ) i = 101;
3807 else if( atom->seedProbability == -1 ) i = 100;
3808 else i = atom->seedProbability;
3809 score = addValToKey( score, 8, i );
3811 /* Prefer peers that we got from more trusted sources.
3812 * lower `fromBest' values indicate more trusted sources */
3813 score = addValToKey( score, 4, atom->fromBest );
3815 /* salt */
3816 score = addValToKey( score, 8, salt );
3818 return score;
3821 /* sort an array of peer candidates */
3822 static int
3823 comparePeerCandidates( const void * va, const void * vb )
3825 const struct peer_candidate * a = va;
3826 const struct peer_candidate * b = vb;
3828 if( a->score < b->score ) return -1;
3829 if( a->score > b->score ) return 1;
3831 return 0;
3834 /** @return an array of all the atoms we might want to connect to */
3835 static struct peer_candidate*
3836 getPeerCandidates( tr_session * session, int * candidateCount )
3838 int atomCount;
3839 int peerCount;
3840 tr_torrent * tor;
3841 struct peer_candidate * candidates;
3842 struct peer_candidate * walk;
3843 const time_t now = tr_time( );
3844 const uint64_t now_msec = tr_time_msec( );
3845 /* leave 5% of connection slots for incoming connections -- ticket #2609 */
3846 const int maxCandidates = tr_sessionGetPeerLimit( session ) * 0.95;
3848 /* count how many peers and atoms we've got */
3849 tor= NULL;
3850 atomCount = 0;
3851 peerCount = 0;
3852 while(( tor = tr_torrentNext( session, tor ))) {
3853 atomCount += tr_ptrArraySize( &tor->torrentPeers->pool );
3854 peerCount += tr_ptrArraySize( &tor->torrentPeers->peers );
3857 /* don't start any new handshakes if we're full up */
3858 if( maxCandidates <= peerCount ) {
3859 *candidateCount = 0;
3860 return NULL;
3863 /* allocate an array of candidates */
3864 walk = candidates = tr_new( struct peer_candidate, atomCount );
3866 /* populate the candidate array */
3867 tor = NULL;
3868 while(( tor = tr_torrentNext( session, tor )))
3870 int i, nAtoms;
3871 struct peer_atom ** atoms;
3873 if( !tor->torrentPeers->isRunning )
3874 continue;
3876 /* if we've already got enough peers in this torrent... */
3877 if( tr_torrentGetPeerLimit( tor ) <= tr_ptrArraySize( &tor->torrentPeers->peers ) )
3878 continue;
3880 /* if we've already got enough speed in this torrent... */
3881 if( tr_torrentIsSeed( tor ) && isBandwidthMaxedOut( &tor->bandwidth, now_msec, TR_UP ) )
3882 continue;
3884 atoms = (struct peer_atom**) tr_ptrArrayPeek( &tor->torrentPeers->pool, &nAtoms );
3885 for( i=0; i<nAtoms; ++i )
3887 struct peer_atom * atom = atoms[i];
3889 if( isPeerCandidate( tor, atom, now ) )
3891 const uint8_t salt = tr_cryptoWeakRandInt( 1024 );
3892 walk->tor = tor;
3893 walk->atom = atom;
3894 walk->score = getPeerCandidateScore( tor, atom, salt );
3895 ++walk;
3900 *candidateCount = walk - candidates;
3901 if( *candidateCount > 1 )
3902 qsort( candidates, *candidateCount, sizeof( struct peer_candidate ), comparePeerCandidates );
3903 return candidates;
3906 static void
3907 initiateConnection( tr_peerMgr * mgr, Torrent * t, struct peer_atom * atom )
3909 tr_peerIo * io;
3910 const time_t now = tr_time( );
3911 bool utp = tr_sessionIsUTPEnabled(mgr->session) && !atom->utp_failed;
3913 if( atom->fromFirst == TR_PEER_FROM_PEX )
3914 /* PEX has explicit signalling for uTP support. If an atom
3915 originally came from PEX and doesn't have the uTP flag, skip the
3916 uTP connection attempt. Are we being optimistic here? */
3917 utp = utp && (atom->flags & ADDED_F_UTP_FLAGS);
3919 tordbg( t, "Starting an OUTGOING%s connection with %s",
3920 utp ? " µTP" : "",
3921 tr_atomAddrStr( atom ) );
3923 io = tr_peerIoNewOutgoing( mgr->session,
3924 &mgr->session->bandwidth,
3925 &atom->addr,
3926 atom->port,
3927 t->tor->info.hash,
3928 t->tor->completeness == TR_SEED,
3929 utp );
3931 if( io == NULL )
3933 tordbg( t, "peerIo not created; marking peer %s as unreachable",
3934 tr_atomAddrStr( atom ) );
3935 atom->flags2 |= MYFLAG_UNREACHABLE;
3936 atom->numFails++;
3938 else
3940 tr_handshake * handshake = tr_handshakeNew( io,
3941 mgr->session->encryptionMode,
3942 myHandshakeDoneCB,
3943 mgr );
3945 assert( tr_peerIoGetTorrentHash( io ) );
3947 tr_peerIoUnref( io ); /* balanced by the initial ref
3948 in tr_peerIoNewOutgoing() */
3950 tr_ptrArrayInsertSorted( &t->outgoingHandshakes, handshake,
3951 handshakeCompare );
3954 atom->lastConnectionAttemptAt = now;
3955 atom->time = now;
3958 static void
3959 initiateCandidateConnection( tr_peerMgr * mgr, struct peer_candidate * c )
3961 #if 0
3962 fprintf( stderr, "Starting an OUTGOING connection with %s - [%s] seedProbability==%d; %s, %s\n",
3963 tr_atomAddrStr( c->atom ),
3964 tr_torrentName( c->tor ),
3965 (int)c->atom->seedProbability,
3966 tr_torrentIsPrivate( c->tor ) ? "private" : "public",
3967 tr_torrentIsSeed( c->tor ) ? "seed" : "downloader" );
3968 #endif
3970 initiateConnection( mgr, c->tor->torrentPeers, c->atom );
3973 static void
3974 makeNewPeerConnections( struct tr_peerMgr * mgr, const int max )
3976 int i, n;
3977 struct peer_candidate * candidates;
3979 candidates = getPeerCandidates( mgr->session, &n );
3981 for( i=0; i<n && i<max; ++i )
3982 initiateCandidateConnection( mgr, &candidates[i] );
3984 tr_free( candidates );