source: trunk/libtransmission/peer.c @ 2803

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

I'm an idiot. Base 2 is not the same thing as base 16.

  • Property svn:keywords set to Date Rev Author Id
File size: 30.7 KB
Line 
1/******************************************************************************
2 * $Id: peer.c 2803 2007-08-16 18:34:44Z 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        ( 0x0 )
154#define HANDSHAKE_EXTPREF_WANT_EXT         ( 0x1 )
155#define HANDSHAKE_EXTPREF_WANT_AZ          ( 0x2 )
156#define HANDSHAKE_EXTPREF_FORCE_AZ         ( 0x3 )
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.