source: trunk/libtransmission/peer.c @ 2891

Last change on this file since 2891 was 2891, checked in by charles, 15 years ago

added support for `corrupt' announce tag s.t. corrupted bytes don't count towards your download ratio

  • Property svn:keywords set to Date Rev Author Id
File size: 31.4 KB
Line 
1/******************************************************************************
2 * $Id: peer.c 2891 2007-08-21 15:17:02Z charles $
3 *
4 * Copyright (c) 2005-2007 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <assert.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <time.h>
30
31#include <sys/types.h>
32
33#include "transmission.h"
34#include "bencode.h"
35#include "clients.h" /* for tr_clientForId() */
36#include "completion.h"
37#include "inout.h"
38#include "list.h"
39#include "net.h"
40#include "peer.h"
41#include "peertree.h"
42#include "ratecontrol.h"
43#include "trcompat.h" /* for strlcpy */
44#include "utils.h"
45
46/*****
47******
48*****/
49
50/**
51*** The "SWIFT" system is described by Karthik Tamilmani,
52*** Vinay Pai, and Alexander Mohr of Stony Brook University
53*** in their paper "SWIFT: A System With Incentives For Trading"
54*** http://citeseer.ist.psu.edu/tamilmani04swift.html
55**/
56
57/**
58 * Use SWIFT?
59 */
60static const int SWIFT_ENABLED = 1;
61
62/**
63 * For every byte the peer uploads to us,
64 * allow them to download this many bytes from us
65 */
66static const double SWIFT_REPAYMENT_RATIO = 1.33;
67
68/**
69 * Allow new peers to download this many bytes from
70 * us when getting started.  This can prevent gridlock
71 * with other peers using tit-for-tat algorithms
72 */
73static const int SWIFT_INITIAL_CREDIT = 64 * 1024; /* 64 KiB */
74
75/**
76 * We expend a fraction of our torrent's total upload speed
77 * on largesse by uniformly distributing free credit to
78 * all of our peers.  This too helps prevent gridlock.
79 */
80static const double SWIFT_LARGESSE = 0.10; /* 10% of our UL */
81
82/**
83 * How frequently to extend largesse-based credit
84 */
85static const int SWIFT_REFRESH_INTERVAL_SEC = 5;
86
87/*****
88******
89*****/
90
91#define PERCENT_PEER_WANTED     25      /* Percent before we start relax peers min activeness */
92#define MIN_UPLOAD_IDLE         60000   /* In high peer situations we wait only 1 min
93                                            until dropping peers for idling */
94#define MAX_UPLOAD_IDLE         240000  /* In low peer situations we wait the
95                                            4 mins until dropping peers for idling */
96#define MIN_KEEP_ALIVE          180000  /* In high peer situations we wait only 3 min
97                                            without a keep-alive */
98#define MAX_KEEP_ALIVE          360000  /* In low peer situations we wait the
99                                            6 mins without a keep-alive */
100#define MIN_CON_TIMEOUT         8000    /* Time to timeout connecting to peer,
101                                            during low peer situations */
102#define MAX_CON_TIMEOUT         30000   /* Time to timeout connecting to peer,
103                                            during high peer situations */
104#define PEX_PEER_CUTOFF         50 /* only try to add new peers from pex if
105                                      we have fewer existing peers than this */
106#define PEX_INTERVAL            60 /* don't send pex messages more frequently
107                                      than PEX_INTERVAL +
108                                      rand( PEX_INTERVAL / 10 ) seconds */
109
110/* uncomment this to disable support for the extended messaging bit */
111/* #define DISABLE_EXTMSGS */
112/* uncomment this to disable support for the azureus protocol bit */
113/* #define DISABLE_AZPROTO */
114
115/* uncomment this to use the new reserved bits proposed here:
116   http://www.azureuswiki.com/index.php/Extension_negotiation_protocol */
117/* #define NEW_AZ_BITS */
118
119#define HANDSHAKE_NAME          "\023BitTorrent protocol"
120#define HANDSHAKE_NAME_LEN      20
121#define HANDSHAKE_FLAGS_OFF     HANDSHAKE_NAME_LEN
122#define HANDSHAKE_FLAGS_LEN     8
123#define HANDSHAKE_HASH_OFF      ( HANDSHAKE_FLAGS_OFF + HANDSHAKE_FLAGS_LEN )
124#define HANDSHAKE_PEERID_OFF    ( HANDSHAKE_HASH_OFF + SHA_DIGEST_LENGTH )
125#define HANDSHAKE_SIZE          ( HANDSHAKE_PEERID_OFF + TR_ID_LEN )
126
127/* these macros test and set the bit indicating extended messaging support */
128#ifdef DISABLE_EXTMSGS
129#define HANDSHAKE_HAS_EXTMSGS( bits ) ( 0 )
130#define HANDSHAKE_SET_EXTMSGS( bits ) ( (void)0 )
131#else
132#define HANDSHAKE_HAS_EXTMSGS( bits ) ( (bits)[5] & 0x10 )
133#define HANDSHAKE_SET_EXTMSGS( bits ) ( (bits)[5] |= 0x10 )
134#endif
135
136/* these macros test and set the bit indicating azureus protocol support */
137#ifdef DISABLE_AZPROTO
138#define HANDSHAKE_HAS_AZPROTO( bits ) ( 0 )
139#define HANDSHAKE_SET_AZPROTO( bits ) ( (void)0 )
140#else
141#define HANDSHAKE_HAS_AZPROTO( bits ) ( (bits)[0] & 0x80 )
142#define HANDSHAKE_SET_AZPROTO( bits ) ( (bits)[0] |= 0x80 )
143#endif
144
145/* these macros are to be used if both extended messaging and the
146   azureus protocol is supported, they indicate which protocol is preferred */
147#ifdef NEW_AZ_BITS
148#define HANDSHAKE_GET_EXTPREF( bits )      ( (bits)[5] & 0x03 )
149#define HANDSHAKE_SET_EXTPREF( bits, val ) ( (bits)[5] |= 0x03 & (val) )
150#else
151#define HANDSHAKE_GET_EXTPREF( bits )      ( 0 )
152#define HANDSHAKE_SET_EXTPREF( bits, val ) ( (void)0 )
153#endif
154#define HANDSHAKE_EXTPREF_FORCE_EXT        ( 0x0 )
155#define HANDSHAKE_EXTPREF_WANT_EXT         ( 0x1 )
156#define HANDSHAKE_EXTPREF_WANT_AZ          ( 0x2 )
157#define HANDSHAKE_EXTPREF_FORCE_AZ         ( 0x3 )
158
159#define PEER_MSG_CHOKE          0
160#define PEER_MSG_UNCHOKE        1
161#define PEER_MSG_INTERESTED     2
162#define PEER_MSG_UNINTERESTED   3
163#define PEER_MSG_HAVE           4
164#define PEER_MSG_BITFIELD       5
165#define PEER_MSG_REQUEST        6
166#define PEER_MSG_PIECE          7
167#define PEER_MSG_CANCEL         8
168#define PEER_MSG_PORT           9
169#define PEER_MSG_EXTENDED       20
170
171typedef struct tr_request_s
172{
173    int index;
174    int begin;
175    int length;
176
177} tr_request_t;
178
179struct tr_peer_s
180{
181    tr_torrent_t      * tor;
182
183    struct in_addr      addr;
184    tr_port_t           port;  /* peer's listening port, 0 if not known */
185
186#define PEER_STATUS_IDLE        1 /* Need to connect */
187#define PEER_STATUS_CONNECTING  2 /* Trying to send handshake */
188#define PEER_STATUS_HANDSHAKE   3 /* Waiting for peer's handshake */
189#define PEER_STATUS_AZ_GIVER    4 /* Sending Azureus handshake */
190#define PEER_STATUS_AZ_RECEIVER 5 /* Receiving Azureus handshake */
191#define PEER_STATUS_CONNECTED   6 /* Got peer's handshake */
192    int                 status;
193    int                 socket;
194    char                from;
195    char                private;
196    char                azproto;  /* azureus peer protocol is being used */
197    uint64_t            date;
198    uint64_t            keepAlive;
199
200#define EXTENDED_NOT_SUPPORTED   0 /* extended messages not supported */
201#define EXTENDED_SUPPORTED       1 /* waiting to send extended handshake */
202#define EXTENDED_HANDSHAKE       2 /* sent extended handshake */
203    uint8_t             extStatus;
204    uint8_t             pexStatus;   /* peer's ut_pex id, 0 if not supported */
205    uint64_t            lastPex;     /* time when last pex packet was sent */
206    int                 advertisedPort; /* listening port we last told peer */
207    tr_peertree_t       sentPeers;
208
209    char                isChokedByUs;
210    char                isChokingUs;
211    char                isInteresting;
212    char                isInterested;
213
214    int                 optimistic;
215    int                 timesChoked;
216    uint64_t            lastChoke;
217
218    uint8_t             id[TR_ID_LEN];
219
220    /* The pieces that the peer has */
221    tr_bitfield_t     * bitfield;
222
223    /* blocks we've requested from this peer */
224    tr_bitfield_t     * reqfield;
225    int                 pieceCount;
226    float               progress;
227
228    int                 goodPcs;
229    int                 badPcs;
230    int                 banned;
231    /* The pieces that the peer is contributing to */
232    tr_bitfield_t     * blamefield;
233    /* The bad pieces that the peer has contributed to */
234    tr_bitfield_t     * banfield;
235
236    uint8_t           * buf;
237    int                 size;
238    int                 pos;
239
240    uint8_t           * outMessages;
241    int                 outMessagesSize;
242    int                 outMessagesPos;
243    uint8_t             outBlock[25+16384];
244    int                 outBlockSize;
245    int                 outBlockLoaded;
246    int                 outBlockSending;
247
248    int                 inRequestCount;
249    int                 inRequestMax;
250    int                 inRequestAlloc;
251    tr_request_t      * inRequests;
252    int                 inIndex;
253    int                 inBegin;
254    int                 inLength;
255
256    tr_list_t         * outRequests;
257    uint64_t            outDate;
258
259    tr_ratecontrol_t  * download;
260    tr_ratecontrol_t  * upload;
261
262    char              * client;
263    int                 extclient;
264
265    int64_t             credit;
266};
267
268#define peer_dbg( a... ) __peer_dbg( peer, ## a )
269
270static void __peer_dbg( tr_peer_t * peer, char * msg, ... )
271{
272    char    string[256];
273    va_list args;
274
275    va_start( args, msg );
276    snprintf( string, sizeof string, "%08x:%04x ",
277             (uint32_t) peer->addr.s_addr, peer->port );
278    vsnprintf( &string[14], sizeof( string ) - 14, msg, args );
279    va_end( args ); 
280
281    tr_dbg( "%s", string );
282}
283
284/* utilities for endian conversions with char pointers */
285
286static uint32_t tr_ntohl( const void * p )
287{
288    uint32_t u;
289    memcpy( &u, p, sizeof( uint32_t ) );
290    return ntohl( u );
291}
292static void tr_htonl( uint32_t a, void * p )
293{
294    const uint32_t u = htonl( a );
295    memcpy ( p, &u, sizeof( uint32_t ) );
296}
297
298static const char* getPeerId( void )
299{
300    static char * peerId = NULL;
301    if( !peerId ) {
302        peerId = tr_new0( char, TR_ID_LEN + 1 );
303        tr_peerIdNew( peerId, TR_ID_LEN + 1 );
304    }
305    return peerId;
306}
307
308static void tr_peerPieceIsCorrupt  ( tr_peer_t *, int pieceIndex );
309
310#include "peerext.h"
311#include "peeraz.h"
312#include "peermessages.h"
313#include "peerutils.h"
314#include "peerparse.h"
315
316/***********************************************************************
317 * tr_peerInit
318 ***********************************************************************
319 * Initializes a new peer.
320 **********************************************************************/
321tr_peer_t * tr_peerInit( const struct in_addr * addr, tr_port_t port,
322                         int s, int from )
323{
324    tr_peer_t * peer;
325
326    assert( 0 <= from && TR_PEER_FROM__MAX > from );
327
328    peer                   = tr_new0( tr_peer_t, 1 );
329    peer->isChokedByUs     = TRUE;
330    peer->isChokingUs      = TRUE;
331    peer->date             = tr_date();
332    peer->keepAlive        = peer->date;
333    peer->download         = tr_rcInit();
334    peer->upload           = tr_rcInit();
335    peertreeInit( &peer->sentPeers );
336
337    peer->inRequestMax = peer->inRequestAlloc = 2;
338    peer->inRequests = tr_new0( tr_request_t, peer->inRequestAlloc );
339
340    peer->socket = s;
341    peer->addr = *addr;
342    peer->port = port;
343    peer->from = from;
344    peer->credit = SWIFT_INITIAL_CREDIT;
345    if( s >= 0 )
346    {
347        assert( TR_PEER_FROM_INCOMING == from );
348        peer->status = PEER_STATUS_CONNECTING;
349    }
350    else
351    {
352        peer->status = PEER_STATUS_IDLE;
353    }
354
355    return peer;
356}
357
358void tr_peerDestroy( tr_peer_t * peer )
359{
360    tr_torrent_t * tor = peer->tor;
361    tr_request_t * r;
362    int i, block;
363
364    peertreeFree( &peer->sentPeers );
365    for( i = 0; i < peer->inRequestCount; i++ )
366    {
367        r = &peer->inRequests[i];
368        block = tr_block( r->index, r->begin );
369        if( tor != NULL )
370            tr_cpDownloaderRem( tor->completion, block );
371    }
372    tr_bitfieldFree( peer->bitfield );
373    tr_bitfieldFree( peer->blamefield );
374    tr_bitfieldFree( peer->banfield );
375    tr_bitfieldFree( peer->reqfield );
376    tr_list_foreach( peer->outRequests, tr_free );
377    tr_list_free( &peer->outRequests );
378    tr_free( peer->inRequests );
379    tr_free( peer->buf );
380    tr_free( peer->outMessages );
381    if( peer->status > PEER_STATUS_IDLE )
382    {
383        tr_netClose( peer->socket );
384    }
385    tr_rcClose( peer->download );
386    tr_rcClose( peer->upload );
387    free( peer->client );
388
389    memset( peer, '\0', sizeof(tr_peer_t) );
390
391    free( peer );
392}
393
394const char *
395tr_peerClient( tr_peer_t * peer )
396{
397    if( PEER_STATUS_HANDSHAKE >= peer->status )
398    {
399        return "not connected";
400    }
401
402    if( NULL == peer->client )
403    {
404        peer->client = tr_clientForId( peer->id );
405    }
406
407    return peer->client;
408}
409
410void tr_peerSetPrivate( tr_peer_t * peer, int private )
411{
412    if( peer->private == private )
413    {
414        return;
415    }
416
417    peer->private = private;
418
419    if( !private )
420    {
421        peer->lastPex = 0;
422    }
423
424    if( EXTENDED_HANDSHAKE == peer->extStatus )
425    {
426        sendExtended( peer->tor, peer, EXTENDED_HANDSHAKE_ID );
427    }
428}
429
430void tr_peerSetTorrent( tr_peer_t * peer, tr_torrent_t * tor )
431{
432    peer->tor = tor;
433}
434
435/***********************************************************************
436 * tr_peerRead
437 ***********************************************************************
438 *
439 **********************************************************************/
440int tr_peerRead( tr_peer_t * peer )
441{
442    tr_torrent_t * tor = peer->tor;
443    int ret;
444    uint64_t date;
445
446    /* Try to read */
447    for( ;; )
448    {
449        if( tor )
450        {
451            int canDL;
452            switch( tor->downloadLimitMode ) {
453                case TR_SPEEDLIMIT_GLOBAL:
454                    canDL = !tor->handle->useDownloadLimit ||
455                             tr_rcCanTransfer( tor->handle->download ); break;
456                case TR_SPEEDLIMIT_SINGLE:
457                    canDL = tr_rcCanTransfer( tor->download ); break;
458                default: /* unlimited */
459                    canDL = TRUE;
460            }
461            if( !canDL )
462                break;
463        }
464
465        if( peer->size < 1 )
466        {
467            peer->size = 1024;
468            peer->buf  = malloc( peer->size );
469        }
470        else if( peer->pos >= peer->size )
471        {
472            peer->size *= 2;
473            peer->buf   = realloc( peer->buf, peer->size );
474        }
475
476        /* Read in smallish chunks, otherwise we might read more
477         * than the download cap is supposed to allow us */
478        ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
479                          MIN( 1024, peer->size - peer->pos ) ); 
480
481        if( ret & TR_NET_CLOSE )
482        {
483            peer_dbg( "connection closed" );
484            return TR_ERROR;
485        }
486        else if( ret & TR_NET_BLOCK )
487        {
488            break;
489        }
490        date        = tr_date();
491        peer->date  = date;
492        peer->pos  += ret;
493        if( NULL != tor )
494        {
495            if( peer->isInteresting && !peer->isChokingUs )
496            {
497                tor->activityDate = date;
498            }
499           
500            if( ( ret = parseBuf( tor, peer ) ) )
501            {
502                return ret;
503            }
504        }
505        else
506        {
507            if( ( ret = parseBufHeader( peer ) ) )
508            {
509                return ret;
510            }
511        }
512    }
513
514    return TR_OK;
515}
516
517uint64_t tr_peerDate( const tr_peer_t * peer )
518{
519    return peer->date;
520}
521
522/***********************************************************************
523 * tr_peerAddress
524 ***********************************************************************
525 *
526 **********************************************************************/
527struct in_addr * tr_peerAddress( tr_peer_t * peer )
528{
529    return &peer->addr;
530}
531
532/***********************************************************************
533 * tr_peerHash
534 ***********************************************************************
535 *
536 **********************************************************************/
537const uint8_t * tr_peerHash( const tr_peer_t * peer )
538{
539    return parseBufHash( peer );
540}
541
542/***********************************************************************
543 * tr_peerPulse
544 ***********************************************************************
545 *
546 **********************************************************************/
547int tr_peerPulse( tr_peer_t * peer )
548{
549    tr_torrent_t * tor = peer->tor;
550    int ret, size;
551    uint8_t * p;
552    uint64_t date;
553    int isSeeding;
554
555    assert( peer != NULL );
556    assert( peer->tor != NULL );
557
558    isSeeding = tr_cpGetStatus( tor->completion ) != TR_CP_INCOMPLETE;
559
560    if( ( ret = checkPeer( peer ) ) )
561    {
562        return ret;
563    }
564
565    /* Connect */
566    if( PEER_STATUS_IDLE == peer->status )
567    {
568        peer->socket = tr_netOpenTCP( &peer->addr, peer->port, 0 );
569        if( peer->socket < 0 )
570        {
571            return TR_ERROR;
572        }
573        peer->status = PEER_STATUS_CONNECTING;
574    }
575   
576    /* Disconnect if seeder and torrent is seeding */
577    if(   ( peer->progress >= 1.0 )
578       && ( peer->tor->cpStatus != TR_CP_INCOMPLETE ) )
579    {
580        return TR_ERROR;
581    }
582
583    /* Try to send handshake */
584    if( PEER_STATUS_CONNECTING == peer->status )
585    {
586        uint8_t buf[HANDSHAKE_SIZE];
587        const tr_info_t * inf;
588
589        inf = tr_torrentInfo( tor );
590        assert( 68 == HANDSHAKE_SIZE );
591        memcpy( buf, HANDSHAKE_NAME, HANDSHAKE_NAME_LEN );
592        memset( buf + HANDSHAKE_FLAGS_OFF, 0, HANDSHAKE_FLAGS_LEN );
593        HANDSHAKE_SET_EXTMSGS( buf + HANDSHAKE_FLAGS_OFF );
594        HANDSHAKE_SET_AZPROTO( buf + HANDSHAKE_FLAGS_OFF );
595        HANDSHAKE_SET_EXTPREF( buf + HANDSHAKE_FLAGS_OFF,
596                               HANDSHAKE_EXTPREF_WANT_EXT );
597        memcpy( buf + HANDSHAKE_HASH_OFF, inf->hash, SHA_DIGEST_LENGTH );
598        memcpy( buf + HANDSHAKE_PEERID_OFF, getPeerId(), TR_ID_LEN );
599
600        switch( tr_netSend( peer->socket, buf, 68 ) )
601        {
602            case HANDSHAKE_SIZE:
603                peer_dbg( "SEND handshake" );
604                peer->status = PEER_STATUS_HANDSHAKE;
605                break;
606            case TR_NET_BLOCK:
607                break;
608            default:
609                peer_dbg( "connection closed" );
610                return TR_ERROR;
611        }
612    }
613    if( peer->status < PEER_STATUS_HANDSHAKE )
614    {
615        /* Nothing more we can do till we sent the handshake */
616        return TR_OK;
617    }
618
619    /* Read incoming messages */
620    if( ( ret = tr_peerRead( peer ) ) )
621    {
622        return ret;
623    }
624
625    /* Try to send Azureus handshake */
626    if( PEER_STATUS_AZ_GIVER == peer->status )
627    {
628        switch( sendAZHandshake( tor, peer ) )
629        {
630            case TR_NET_BLOCK:
631                break;
632            case TR_NET_CLOSE:
633                peer_dbg( "connection closed" );
634                return TR_ERROR;
635            default:
636                peer->status = PEER_STATUS_AZ_RECEIVER;
637                break;
638        }
639    }
640
641    if( peer->status < PEER_STATUS_CONNECTED )
642    {
643        /* Nothing more we can do till we got the other guy's handshake */
644        return TR_OK;
645    }
646
647    /* Try to write */
648writeBegin:
649
650    /* Send all smaller messages regardless of the upload cap */
651    while( ( p = messagesPending( peer, &size ) ) )
652    {
653        ret = tr_netSend( peer->socket, p, size );
654        if( ret & TR_NET_CLOSE )
655        {
656            return TR_ERROR;
657        }
658        else if( ret & TR_NET_BLOCK )
659        {
660            goto writeEnd;
661        }
662        messagesSent( peer, ret );
663    }
664
665    /* Send pieces if we can */
666    while( ( p = blockPending( tor, peer, &size ) ) )
667    {
668        int canUL;
669
670        if( SWIFT_ENABLED && !isSeeding && (peer->credit<0) )
671            canUL = FALSE;
672        else switch( tor->uploadLimitMode )
673        {
674            case TR_SPEEDLIMIT_GLOBAL:
675                canUL = !tor->handle->useUploadLimit ||
676                         tr_rcCanTransfer( tor->handle->upload ); break;
677
678            case TR_SPEEDLIMIT_SINGLE:
679                canUL = tr_rcCanTransfer( tor->upload ); break;
680
681            default: /* unlimited */
682                canUL = TRUE;
683        }
684        if( !canUL )
685            break;
686
687        ret = tr_netSend( peer->socket, p, size );
688        if( ret & TR_NET_CLOSE )
689            return TR_ERROR;
690
691        if( ret & TR_NET_BLOCK )
692            break;
693
694        blockSent( peer, ret );
695
696        if( ret > 0 )
697            tr_peerGotBlockFromUs( peer, ret );
698
699        date              = tr_date();
700        peer->outDate     = date;
701       
702        if( !tr_peerIsChokedByUs( peer ) )
703            tor->activityDate = date;
704
705        /* In case this block is done, you may have messages
706           pending. Send them before we start the next block */
707        goto writeBegin;
708    }
709writeEnd:
710
711    /* Ask for a block whenever possible */
712    if( !isSeeding
713        && !peer->isInteresting
714        && tor->peerCount > TR_MAX_PEER_COUNT - 2 )
715    {
716        /* This peer is no use to us, and it seems there are
717           more */
718        peer_dbg( "not interesting" );
719        return TR_ERROR;
720    }
721
722    if(     peer->isInteresting
723        && !peer->isChokingUs
724        && !peer->banned
725        &&  peer->inRequestCount < peer->inRequestMax )
726    {
727        int poolSize = 0;
728        int endgame = FALSE;
729        int openSlots = peer->inRequestMax - peer->inRequestCount;
730        int * pool = getPreferredPieces ( tor, peer, &poolSize, &endgame );
731
732        if( !endgame )
733        {
734            /* pool is sorted from most to least desirable pieces,
735               so work our way through starting at beginning */
736            int p;
737            for( p=0; p<poolSize && openSlots>0; )
738            {
739                const int piece = pool[p];
740                const int block = tr_cpMissingBlockInPiece ( tor->completion, piece );
741                if( block < 0 )
742                    ++p;
743                else { 
744                    sendRequest( tor, peer, block );
745                    --openSlots;
746                }
747            }
748        }
749        else
750        {
751            /* During endgame we remove the constraint of not asking for
752               pieces we've already requested from a different peer.
753               So if we follow the non-endgame approach of walking through
754               [0..poolCount) we'll bog down asking all peers for 1, then
755               all peers for 2, and so on.  Randomize our starting point
756               into "pool" to reduce such overlap */
757            int piecesLeft = poolSize;
758            int p = piecesLeft ? tr_rand(piecesLeft) : 0;
759            for( ; openSlots>0 && piecesLeft>0; --piecesLeft, p=(p+1)%poolSize )
760            {
761                const int piece = pool[p]; 
762                const int firstBlock = tr_torPieceFirstBlock( tor, piece );
763                const int n = tr_torPieceCountBlocks( tor, piece );
764                const int end = firstBlock + n;
765                int block;
766                for( block=firstBlock; openSlots>0 && block<end; ++block )
767                {
768                    /* don't ask for it if we've already got it */
769                    if( tr_cpBlockIsComplete( tor->completion, block ))
770                        continue;
771
772                    /* don't ask for it twice from the same peer */
773                    if( tr_bitfieldHas( peer->reqfield, block ) )
774                        continue;
775
776                    /* ask peer for the piece */
777                    if( !peer->reqfield )
778                         peer->reqfield = tr_bitfieldNew( tor->blockCount );
779                    tr_bitfieldAdd( peer->reqfield, block );
780                    sendRequest( tor, peer, block );
781                    --openSlots;
782                }
783            }
784        }
785
786        tr_free( pool );
787    }
788
789    assert( peer->inRequestCount <= peer->inRequestAlloc );
790    assert( peer->inRequestMax <= peer->inRequestAlloc );
791
792    return TR_OK;
793}
794
795int tr_peerIsConnected( const tr_peer_t * peer )
796{
797    return peer && (peer->status == PEER_STATUS_CONNECTED);
798}
799
800int tr_peerIsFrom( const tr_peer_t * peer )
801{
802    return peer->from;
803}
804
805int tr_peerIsChokedByUs( const tr_peer_t * peer )
806{
807    return peer->isChokedByUs;
808}
809int tr_peerIsInteresting( const tr_peer_t * peer )
810{
811    return peer->isInteresting;
812}
813int tr_peerIsChokingUs( const tr_peer_t * peer )
814{
815    return peer->isChokingUs;
816}
817int tr_peerIsInterested( const tr_peer_t * peer )
818{
819    return peer->isInterested;
820}
821
822float tr_peerProgress( const tr_peer_t * peer )
823{
824    return peer->progress;
825}
826
827int tr_peerPort( const tr_peer_t * peer )
828{
829    return ntohs( peer->port );
830}
831
832int tr_peerHasPiece( const tr_peer_t * peer, int pieceIndex )
833{
834    return tr_bitfieldHas( peer->bitfield, pieceIndex );
835}
836
837float tr_peerDownloadRate( const tr_peer_t * peer )
838{
839    return tr_rcRate( peer->download );
840}
841
842float tr_peerUploadRate( const tr_peer_t * peer )
843{
844    return tr_rcRate( peer->upload );
845}
846
847int tr_peerTimesChoked( const tr_peer_t * peer )
848{
849    return peer->timesChoked;
850}
851
852void tr_peerChoke( tr_peer_t * peer )
853{
854    sendChoke( peer, 1 );
855    peer->lastChoke = tr_date();
856    ++peer->timesChoked;
857}
858
859void tr_peerUnchoke( tr_peer_t * peer )
860{
861    sendChoke( peer, 0 );
862    peer->lastChoke = tr_date();
863}
864
865uint64_t tr_peerLastChoke( const tr_peer_t * peer )
866{
867    return peer->lastChoke;
868}
869
870void tr_peerSetOptimistic( tr_peer_t * peer, int o )
871{
872    peer->optimistic = o;
873}
874
875int tr_peerIsOptimistic( const tr_peer_t * peer )
876{
877    return peer->optimistic;
878}
879
880static int peerIsBad( const tr_peer_t * peer )
881{
882    return peer->badPcs > 4 + 2 * peer->goodPcs;
883}
884
885static int peerIsGood( const tr_peer_t * peer )
886{
887    return peer->goodPcs > 3 * peer->badPcs;
888}
889
890void tr_peerBlame( tr_peer_t * peer, int piece, int success )
891{
892    tr_torrent_t * tor = peer->tor;
893
894    if( !peer->blamefield || !tr_bitfieldHas( peer->blamefield, piece ) )
895    {
896        return;
897    }
898
899    if( success )
900    {
901        peer->goodPcs++;
902
903        if( peer->banfield && peerIsGood( peer ) )
904        {
905            /* Assume the peer wasn't responsible for the bad pieces
906               we was banned for */
907            tr_bitfieldClear( peer->banfield );
908        }
909    }
910    else
911    {
912        peer->badPcs++;
913
914        /* Ban the peer for this piece */
915        if( !peer->banfield )
916        {
917            peer->banfield = tr_bitfieldNew( tor->info.pieceCount );
918        }
919        tr_bitfieldAdd( peer->banfield, piece );
920
921        if( peerIsBad( peer ) )
922        {
923            /* Full ban */
924            peer_dbg( "banned (%d / %d)", peer->goodPcs, peer->badPcs );
925            peer->banned = TRUE;
926            peer->isInteresting = FALSE;
927            peer->isInterested = FALSE;
928        }
929    }
930    tr_bitfieldRem( peer->blamefield, piece );
931}
932
933int tr_peerGetConnectable( const tr_torrent_t * tor, uint8_t ** _buf )
934{
935    int count = 0;
936    uint8_t * buf;
937    tr_peer_t * peer;
938    int i;
939
940    if( tor->peerCount < 1 )
941    {
942        *_buf = NULL;
943        return 0;
944    }
945
946    buf = malloc( 6 * tor->peerCount );
947    for( i = 0; i < tor->peerCount; i++ )
948    {
949        peer = tor->peers[i];
950
951        /* Skip peers with no known listening port */
952        if( 0 == peer->port )
953            continue;
954
955        memcpy( &buf[count*6], &peer->addr, 4 );
956        memcpy( &buf[count*6+4], &peer->port, 2 );
957        count++;
958    }
959
960    if( count < 1 )
961    {
962        free( buf ); buf = NULL;
963    }
964    *_buf = buf;
965
966    return count * 6;
967}
968
969/***
970****
971***/
972
973void
974tr_peerPieceIsCorrupt( tr_peer_t * peer, int pieceIndex )
975{
976    tr_torrent_t * tor = peer->tor;
977
978    const uint64_t byteCount = tr_torPieceCountBytes( tor, pieceIndex );
979
980    /* increment the `corrupt' field */
981    tor->corruptCur += byteCount;
982
983    /* decrement the `downloaded' field */
984    if( tor->downloadedCur >= byteCount )
985        tor->downloadedCur -= byteCount;
986    else
987        tor->downloadedCur = 0;
988}
989
990void
991tr_peerSentBlockToUs( tr_peer_t * peer, int byteCount )
992{
993    tr_torrent_t * tor = peer->tor;
994
995    assert( byteCount >= 0 );
996    assert( byteCount <= tor->info.pieceSize );
997
998    tor->downloadedCur += byteCount;
999    tr_rcTransferred( peer->download, byteCount );
1000    tr_rcTransferred( tor->download, byteCount );
1001    tr_rcTransferred( tor->handle->download, byteCount );
1002
1003    peer->credit += (int)(byteCount * SWIFT_REPAYMENT_RATIO);
1004}
1005
1006void
1007tr_peerGotBlockFromUs ( tr_peer_t * peer, int byteCount )
1008{
1009    tr_torrent_t * tor = peer->tor;
1010
1011    assert( byteCount >= 0 );
1012    assert( byteCount <= tor->info.pieceSize );
1013
1014    tor->uploadedCur += byteCount;
1015    tr_rcTransferred( peer->upload, byteCount );
1016    tr_rcTransferred( tor->upload, byteCount );
1017    tr_rcTransferred( tor->handle->upload, byteCount );
1018
1019    peer->credit -= byteCount;
1020}
1021
1022static void
1023tr_torrentSwiftPulse ( tr_torrent_t * tor )
1024{
1025    /* Preferred # of seconds for the request queue's turnaround time.
1026       This is just an arbitrary number. */
1027    const int queueTimeSec = 5;
1028    const int blockSizeKiB = tor->blockSize / 1024;
1029    const int isSeeding = tr_cpGetStatus( tor->completion ) != TR_CP_INCOMPLETE;
1030    int i;
1031
1032    tr_torrentWriterLock( tor );
1033
1034    for( i=0; i<tor->peerCount; ++i )
1035    {
1036        double outboundSpeedKiBs;
1037        int size;
1038        tr_peer_t * peer = tor->peers[ i ];
1039
1040        if( !tr_peerIsConnected( peer ) )
1041            continue;
1042
1043        /* decide how many blocks we'll concurrently ask this peer for */
1044        outboundSpeedKiBs = tr_rcRate(peer->upload);
1045        size = queueTimeSec * outboundSpeedKiBs / blockSizeKiB;
1046        if( size < 4 ) /* don't let it get TOO small */
1047            size = 4;
1048        size += 4; /* and always leave room to grow */
1049        peer->inRequestMax = size;
1050        if( peer->inRequestAlloc < peer->inRequestMax ) {
1051            peer->inRequestAlloc = peer->inRequestMax;
1052            peer->inRequests = tr_renew( tr_request_t, peer->inRequests, peer->inRequestAlloc );
1053        }
1054    }
1055
1056    /* if we're not seeding, decide on how much
1057       bandwidth to allocate for leechers */
1058    if( !isSeeding )
1059    {
1060        tr_peer_t ** deadbeats = tr_new( tr_peer_t*, tor->peerCount );
1061        int deadbeatCount = 0;
1062
1063        for( i=0; i<tor->peerCount; ++i ) {
1064            tr_peer_t * peer = tor->peers[ i ];
1065            if( tr_peerIsConnected( peer ) && ( peer->credit < 0 ) )
1066                deadbeats[deadbeatCount++] = peer;
1067        }
1068
1069        if( deadbeatCount )
1070        {
1071            const double ul_KiBsec = tr_rcRate( tor->download );
1072            const double ul_KiB = ul_KiBsec * SWIFT_REFRESH_INTERVAL_SEC;
1073            const double ul_bytes = ul_KiB * 1024;
1074            const double freeCreditTotal = ul_bytes * SWIFT_LARGESSE;
1075            const int freeCreditPerPeer = (int)( freeCreditTotal / deadbeatCount );
1076            for( i=0; i<deadbeatCount; ++i )
1077                deadbeats[i]->credit = freeCreditPerPeer;
1078            tr_dbg( "torrent %s has %d deadbeats, "
1079                    "who are each being granted %d bytes' credit "
1080                    "for a total of %.1f KiB, "
1081                    "%d%% of the torrent's ul speed %.1f\n", 
1082                tor->info.name, deadbeatCount, freeCreditPerPeer,
1083                ul_KiBsec*SWIFT_LARGESSE, (int)(SWIFT_LARGESSE*100), ul_KiBsec );
1084        }
1085
1086        tr_free( deadbeats );
1087    }
1088
1089    tr_torrentWriterUnlock( tor );
1090}
1091void
1092tr_swiftPulse( tr_handle_t * h )
1093{
1094    static time_t lastPulseTime = 0;
1095
1096    if( lastPulseTime + SWIFT_REFRESH_INTERVAL_SEC <= time( NULL ) )
1097    {
1098        tr_torrent_t * tor;
1099        for( tor=h->torrentList; tor; tor=tor->next )
1100            tr_torrentSwiftPulse( tor );
1101
1102        lastPulseTime = time( NULL );
1103    }
1104}
Note: See TracBrowser for help on using the repository browser.