source: trunk/libtransmission/peer.c @ 2772

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

Implement proposed extension to indicate which of azrueus or extended messaging are preferred.
This is disabled for now.

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