source: trunk/libtransmission/peer.c @ 2441

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

more work on the speed limits as hammered out w/BentMyWookie

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