source: trunk/libtransmission/peer.c @ 2781

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

Save client name from azureus or extended handshake, overriding name deduced from peer id.

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