source: trunk/libtransmission/peer.c @ 2923

Last change on this file since 2923 was 2923, checked in by joshe, 15 years ago

Enable the azureus/libtorrent extension negotiation reserved bits.

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