source: trunk/libtransmission/peer.c @ 2149

Last change on this file since 2149 was 2149, checked in by livings124, 15 years ago

Merge file selection and torrent creation into the main branch.

The new code for these features is under a new license.

  • Property svn:keywords set to Date Rev Author Id
File size: 22.3 KB
Line 
1/******************************************************************************
2 * $Id: peer.c 2149 2007-06-18 03:40:41Z livings124 $
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 "transmission.h"
26#include "peertree.h"
27
28#define PERCENT_PEER_WANTED     25      /* Percent before we start relax peers min activeness */
29#define MIN_UPLOAD_IDLE         60000   /* In high peer situations we wait only 1 min
30                                            until dropping peers for idling */
31#define MAX_UPLOAD_IDLE         240000  /* In low peer situations we wait the
32                                            4 mins until dropping peers for idling */
33#define MIN_KEEP_ALIVE          180000  /* In high peer situations we wait only 3 min
34                                            without a keep-alive */
35#define MAX_KEEP_ALIVE          360000  /* In low peer situations we wait the
36                                            6 mins without a keep-alive */
37#define MIN_CON_TIMEOUT         8000    /* Time to timeout connecting to peer,
38                                            during low peer situations */
39#define MAX_CON_TIMEOUT         30000   /* Time to timeout connecting to peer,
40                                            during high peer situations */
41#define MAX_REQUEST_COUNT       32
42#define OUR_REQUEST_COUNT       8  /* TODO: we should detect if we are on a
43                                      high-speed network and adapt */
44#define PEX_PEER_CUTOFF         50 /* only try to add new peers from pex if
45                                      we have fewer existing peers than this */
46#define PEX_INTERVAL            60 /* don't send pex messages more frequently
47                                      than PEX_INTERVAL +
48                                      rand( PEX_INTERVAL / 10 ) seconds */
49#define PEER_SUPPORTS_EXTENDED_MESSAGES( bits ) ( (bits)[5] & 0x10 )
50#define PEER_SUPPORTS_AZUREUS_PROTOCOL( bits )  ( (bits)[0] & 0x80 )
51
52#define PEER_MSG_CHOKE          0
53#define PEER_MSG_UNCHOKE        1
54#define PEER_MSG_INTERESTED     2
55#define PEER_MSG_UNINTERESTED   3
56#define PEER_MSG_HAVE           4
57#define PEER_MSG_BITFIELD       5
58#define PEER_MSG_REQUEST        6
59#define PEER_MSG_PIECE          7
60#define PEER_MSG_CANCEL         8
61#define PEER_MSG_PORT           9
62#define PEER_MSG_EXTENDED       20
63
64typedef struct tr_request_s
65{
66    int index;
67    int begin;
68    int length;
69
70} tr_request_t;
71
72struct tr_peer_s
73{
74    tr_torrent_t      * tor;
75
76    struct in_addr      addr;
77    in_port_t           port;  /* peer's listening port, 0 if not known */
78
79#define PEER_STATUS_IDLE        1 /* Need to connect */
80#define PEER_STATUS_CONNECTING  2 /* Trying to send handshake */
81#define PEER_STATUS_HANDSHAKE   3 /* Waiting for peer's handshake */
82#define PEER_STATUS_AZ_GIVER    4 /* Sending Azureus handshake */
83#define PEER_STATUS_AZ_RECEIVER 5 /* Receiving Azureus handshake */
84#define PEER_STATUS_CONNECTED   6 /* Got peer's handshake */
85    int                 status;
86    int                 socket;
87    char                from;
88    char                private;
89    char                azproto;  /* azureus peer protocol is being used */
90    uint64_t            date;
91    uint64_t            keepAlive;
92
93#define EXTENDED_NOT_SUPPORTED   0 /* extended messages not supported */
94#define EXTENDED_SUPPORTED       1 /* waiting to send extended handshake */
95#define EXTENDED_HANDSHAKE       2 /* sent extended handshake */
96    uint8_t             extStatus;
97    uint8_t             pexStatus;   /* peer's ut_pex id, 0 if not supported */
98    uint64_t            lastPex;     /* time when last pex packet was sent */
99    int                 advertisedPort; /* listening port we last told peer */
100    tr_peertree_t       sentPeers;
101
102    char                amChoking;
103    char                amInterested;
104    char                peerChoking;
105    char                peerInterested;
106
107    int                 optimistic;
108    uint64_t            lastChoke;
109
110    uint8_t             id[TR_ID_LEN];
111
112    /* The pieces that the peer has */
113    tr_bitfield_t     * bitfield;
114    int                 pieceCount;
115    float               progress;
116
117    int                 goodPcs;
118    int                 badPcs;
119    int                 banned;
120    /* The pieces that the peer is contributing to */
121    tr_bitfield_t     * blamefield;
122    /* The bad pieces that the peer has contributed to */
123    tr_bitfield_t     * banfield;
124
125    uint8_t           * buf;
126    int                 size;
127    int                 pos;
128
129    uint8_t           * outMessages;
130    int                 outMessagesSize;
131    int                 outMessagesPos;
132    uint8_t             outBlock[25+16384];
133    int                 outBlockSize;
134    int                 outBlockLoaded;
135    int                 outBlockSending;
136
137    int                 inRequestCount;
138    tr_request_t        inRequests[OUR_REQUEST_COUNT];
139    int                 inIndex;
140    int                 inBegin;
141    int                 inLength;
142    uint64_t            inTotal;
143
144    int                 outRequestCount;
145    tr_request_t        outRequests[MAX_REQUEST_COUNT];
146    uint64_t            outTotal;
147    uint64_t            outDate;
148
149    tr_ratecontrol_t  * download;
150    tr_ratecontrol_t  * upload;
151
152    char              * client;
153};
154
155#define peer_dbg( a... ) __peer_dbg( peer, ## a )
156static void __peer_dbg( tr_peer_t * peer, char * msg, ... ) PRINTF( 2, 3 );
157
158static void __peer_dbg( tr_peer_t * peer, char * msg, ... )
159{
160    char    string[256];
161    va_list args;
162
163    va_start( args, msg );
164    snprintf( string, sizeof string, "%08x:%04x ",
165             (uint32_t) peer->addr.s_addr, peer->port );
166    vsnprintf( &string[14], sizeof( string ) - 14, msg, args );
167    va_end( args ); 
168
169    tr_dbg( "%s", string );
170}
171
172#include "peerext.h"
173#include "peeraz.h"
174#include "peermessages.h"
175#include "peerutils.h"
176#include "peerparse.h"
177
178/***********************************************************************
179 * tr_peerInit
180 ***********************************************************************
181 * Initializes a new peer.
182 **********************************************************************/
183tr_peer_t * tr_peerInit( struct in_addr addr, in_port_t port, int s, int from )
184{
185    tr_peer_t * peer = peerInit();
186
187    assert( 0 <= from && TR_PEER_FROM__MAX > from );
188
189    peer->socket = s;
190    peer->addr = addr;
191    peer->port = port;
192    peer->from = from;
193    if( s >= 0 )
194    {
195        assert( TR_PEER_FROM_INCOMING == from );
196        peer->status = PEER_STATUS_CONNECTING;
197    }
198    else
199    {
200        peer->status = PEER_STATUS_IDLE;
201    }
202
203    return peer;
204}
205
206void tr_peerDestroy( tr_peer_t * peer )
207{
208    tr_torrent_t * tor = peer->tor;
209    tr_request_t * r;
210    int i, block;
211
212    peertreeFree( &peer->sentPeers );
213    for( i = 0; i < peer->inRequestCount; i++ )
214    {
215        r = &peer->inRequests[i];
216        block = tr_block( r->index, r->begin );
217        tr_cpDownloaderRem( tor->completion, block );
218    }
219    tr_bitfieldFree( peer->bitfield );
220    tr_bitfieldFree( peer->blamefield );
221    tr_bitfieldFree( peer->banfield );
222    if( peer->buf )
223    {
224        free( peer->buf );
225    }
226    if( peer->outMessages )
227    {
228        free( peer->outMessages );
229    }
230    if( peer->status > PEER_STATUS_IDLE )
231    {
232        tr_netClose( peer->socket );
233    }
234    tr_rcClose( peer->download );
235    tr_rcClose( peer->upload );
236    free( peer->client );
237    free( peer );
238}
239
240const char *
241tr_peerClient( tr_peer_t * peer )
242{
243    if( PEER_STATUS_HANDSHAKE >= peer->status )
244    {
245        return "not connected";
246    }
247
248    if( NULL == peer->client )
249    {
250        peer->client = tr_clientForId( peer->id );
251    }
252
253    return peer->client;
254}
255
256void tr_peerSetPrivate( tr_peer_t * peer, int private )
257{
258    if( peer->private == private )
259    {
260        return;
261    }
262
263    peer->private = private;
264
265    if( !private )
266    {
267        peer->lastPex = 0;
268    }
269
270    if( EXTENDED_HANDSHAKE == peer->extStatus )
271    {
272        sendExtended( peer->tor, peer, EXTENDED_HANDSHAKE_ID );
273    }
274}
275
276void tr_peerSetTorrent( tr_peer_t * peer, tr_torrent_t * tor )
277{
278    peer->tor = tor;
279}
280
281/***********************************************************************
282 * tr_peerRead
283 ***********************************************************************
284 *
285 **********************************************************************/
286int tr_peerRead( tr_peer_t * peer )
287{
288    tr_torrent_t * tor = peer->tor;
289    int ret;
290    uint64_t date;
291
292    /* Try to read */
293    for( ;; )
294    {
295        if( tor )
296        {
297            if( tor->customDownloadLimit
298                ? !tr_rcCanTransfer( tor->download )
299                : !tr_rcCanTransfer( tor->handle->download ) )
300            {
301                break;
302            }
303        }
304
305        if( peer->size < 1 )
306        {
307            peer->size = 1024;
308            peer->buf  = malloc( peer->size );
309        }
310        else if( peer->pos >= peer->size )
311        {
312            peer->size *= 2;
313            peer->buf   = realloc( peer->buf, peer->size );
314        }
315        /* Never read more than 1K each time, otherwise the rate
316           control is no use */
317        ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
318                          MIN( 1024, peer->size - peer->pos ) );
319        if( ret & TR_NET_CLOSE )
320        {
321            peer_dbg( "connection closed" );
322            return TR_ERROR;
323        }
324        else if( ret & TR_NET_BLOCK )
325        {
326            break;
327        }
328        date        = tr_date();
329        peer->date  = date;
330        peer->pos  += ret;
331        if( NULL != tor )
332        {
333            tr_rcTransferred( peer->download, ret );
334            tr_rcTransferred( tor->download, ret );
335            if ( !tor->customDownloadLimit )
336            {
337                tr_rcTransferred( tor->handle->download, ret );
338            }
339           
340            if( tr_peerAmInterested( peer ) && !tr_peerIsChoking( peer ) )
341            {
342                tor->activityDate = date;
343            }
344           
345            if( ( ret = parseBuf( tor, peer ) ) )
346            {
347                return ret;
348            }
349        }
350        else
351        {
352            if( ( ret = parseBufHeader( peer ) ) )
353            {
354                return ret;
355            }
356        }
357    }
358
359    return TR_OK;
360}
361
362uint64_t tr_peerDate( tr_peer_t * peer )
363{
364    return peer->date;
365}
366
367/***********************************************************************
368 * tr_peerId
369 ***********************************************************************
370 *
371 **********************************************************************/
372uint8_t * tr_peerId( tr_peer_t * peer )
373{
374    return & peer->id[0];
375}
376
377/***********************************************************************
378 * tr_peerAddress
379 ***********************************************************************
380 *
381 **********************************************************************/
382struct in_addr * tr_peerAddress( tr_peer_t * peer )
383{
384    return &peer->addr;
385}
386
387/***********************************************************************
388 * tr_peerHash
389 ***********************************************************************
390 *
391 **********************************************************************/
392uint8_t * tr_peerHash( tr_peer_t * peer )
393{
394    return parseBufHash( peer );
395}
396
397/***********************************************************************
398 * tr_peerPulse
399 ***********************************************************************
400 *
401 **********************************************************************/
402int tr_peerPulse( tr_peer_t * peer )
403{
404    tr_torrent_t * tor = peer->tor;
405    int ret, size;
406    uint8_t * p;
407    uint64_t date;
408
409    if( ( ret = checkPeer( peer ) ) )
410    {
411        return ret;
412    }
413
414    /* Connect */
415    if( PEER_STATUS_IDLE == peer->status )
416    {
417        peer->socket = tr_netOpenTCP( peer->addr, peer->port, 0 );
418        if( peer->socket < 0 )
419        {
420            return TR_ERROR;
421        }
422        peer->status = PEER_STATUS_CONNECTING;
423    }
424   
425    /* Disconnect if seeder and torrent is seeding */
426    if(   ( peer->progress >= 1.0 )
427       && ( peer->tor->status & (TR_STATUS_SEED|TR_STATUS_DONE) ) )
428    {
429        return TR_ERROR;
430    }
431
432    /* Try to send handshake */
433    if( PEER_STATUS_CONNECTING == peer->status )
434    {
435        uint8_t buf[68];
436        tr_info_t * inf = &tor->info;
437
438        buf[0] = 19;
439        memcpy( &buf[1], "BitTorrent protocol", 19 );
440        memset( &buf[20], 0, 8 );
441        buf[20] = 0x80;         /* azureus protocol */
442        buf[25] = 0x10;         /* extended messages */
443        memcpy( &buf[28], inf->hash, 20 );
444        memcpy( &buf[48], tor->id, 20 );
445
446        switch( tr_netSend( peer->socket, buf, 68 ) )
447        {
448            case 68:
449                peer_dbg( "SEND handshake" );
450                peer->status = PEER_STATUS_HANDSHAKE;
451                break;
452            case TR_NET_BLOCK:
453                break;
454            default:
455                peer_dbg( "connection closed" );
456                return TR_ERROR;
457        }
458    }
459    if( peer->status < PEER_STATUS_HANDSHAKE )
460    {
461        /* Nothing more we can do till we sent the handshake */
462        return TR_OK;
463    }
464
465    /* Read incoming messages */
466    if( ( ret = tr_peerRead( peer ) ) )
467    {
468        return ret;
469    }
470
471    /* Try to send Azureus handshake */
472    if( PEER_STATUS_AZ_GIVER == peer->status )
473    {
474        switch( sendAZHandshake( tor, peer ) )
475        {
476            case TR_NET_BLOCK:
477                break;
478            case TR_NET_CLOSE:
479                peer_dbg( "connection closed" );
480                return TR_ERROR;
481            default:
482                peer->status = PEER_STATUS_AZ_RECEIVER;
483                break;
484        }
485    }
486
487    if( peer->status < PEER_STATUS_CONNECTED )
488    {
489        /* Nothing more we can do till we got the other guy's handshake */
490        return TR_OK;
491    }
492
493    /* Try to write */
494writeBegin:
495
496    /* Send all smaller messages regardless of the upload cap */
497    while( ( p = messagesPending( peer, &size ) ) )
498    {
499        ret = tr_netSend( peer->socket, p, size );
500        if( ret & TR_NET_CLOSE )
501        {
502            return TR_ERROR;
503        }
504        else if( ret & TR_NET_BLOCK )
505        {
506            goto writeEnd;
507        }
508        messagesSent( peer, ret );
509    }
510
511    /* Send pieces if we can */
512    while( ( p = blockPending( tor, peer, &size ) ) )
513    {
514        if( tor->customUploadLimit
515            ? !tr_rcCanTransfer( tor->upload )
516            : !tr_rcCanTransfer( tor->handle->upload ) )
517        {
518            break;
519        }
520
521        ret = tr_netSend( peer->socket, p, size );
522        if( ret & TR_NET_CLOSE )
523        {
524            return TR_ERROR;
525        }
526        else if( ret & TR_NET_BLOCK )
527        {
528            break;
529        }
530
531        blockSent( peer, ret );
532        tr_rcTransferred( peer->upload, ret );
533        tr_rcTransferred( tor->upload, ret );
534        if ( !tor->customUploadLimit )
535        {
536            tr_rcTransferred( tor->handle->upload, ret );
537        }
538
539        tor->uploadedCur += ret;
540        peer->outTotal   += ret;
541       
542        date              = tr_date();
543        peer->outDate     = date;
544       
545        if( !tr_peerAmChoking( peer ) )
546        {
547            tor->activityDate = date;
548        }
549
550        /* In case this block is done, you may have messages
551           pending. Send them before we start the next block */
552        goto writeBegin;
553    }
554writeEnd:
555
556    /* Ask for a block whenever possible */
557    if( tr_cpGetStatus( tor->completion ) == TR_CP_INCOMPLETE
558        && !peer->amInterested
559        && tor->peerCount > TR_MAX_PEER_COUNT - 2 )
560    {
561        /* This peer is no use to us, and it seems there are
562           more */
563        peer_dbg( "not interesting" );
564        return TR_ERROR;
565    }
566
567    if(     peer->amInterested
568        && !peer->peerChoking
569        && !peer->banned
570        &&  peer->inRequestCount < OUR_REQUEST_COUNT )
571    {
572        int i;
573        int poolSize=0, endgame=0;
574        int * pool = getPreferredPieces ( tor, peer, &poolSize, &endgame );
575
576        /* TODO: add some asserts to see if this bitfield is really necessary */
577        tr_bitfield_t * blocksAlreadyRequested = tr_bitfieldNew( tor->blockCount );
578        for( i=0; i<peer->inRequestCount; ++i) {
579            const tr_request_t * r = &peer->inRequests[i];
580            const int block = tr_block( r->index, r->begin );
581            tr_bitfieldAdd( blocksAlreadyRequested, block );
582        }
583
584        for( i=0; i<poolSize && peer->inRequestCount<OUR_REQUEST_COUNT;  )
585        {
586            int unused;
587            const int piece = pool[i];
588            const int block = endgame
589                ? tr_cpMostMissingBlockInPiece( tor->completion, piece, &unused)
590                : tr_cpMissingBlockInPiece ( tor->completion, piece );
591
592            if( block>=0 && (endgame || !tr_bitfieldHas( blocksAlreadyRequested, block ) ) )
593            {
594                tr_bitfieldAdd( blocksAlreadyRequested, block );
595                sendRequest( tor, peer, block );
596            }
597            else ++i;
598        }
599
600        tr_bitfieldFree( blocksAlreadyRequested );
601        free( pool );
602    }
603
604    return TR_OK;
605}
606
607/***********************************************************************
608 * tr_peerIsConnected
609 ***********************************************************************
610 *
611 **********************************************************************/
612int tr_peerIsConnected( tr_peer_t * peer )
613{
614    return PEER_STATUS_CONNECTED == peer->status;
615}
616
617/***********************************************************************
618 * tr_peerIsIncoming
619 ***********************************************************************
620 *
621 **********************************************************************/
622int tr_peerIsFrom( tr_peer_t * peer )
623{
624    return peer->from;
625}
626
627int tr_peerAmChoking( tr_peer_t * peer )
628{
629    return peer->amChoking;
630}
631int tr_peerAmInterested( tr_peer_t * peer )
632{
633    return peer->amInterested;
634}
635int tr_peerIsChoking( tr_peer_t * peer )
636{
637    return peer->peerChoking;
638}
639int tr_peerIsInterested( tr_peer_t * peer )
640{
641    return peer->peerInterested;
642}
643
644/***********************************************************************
645 * tr_peerProgress
646 ***********************************************************************
647 *
648 **********************************************************************/
649float tr_peerProgress( tr_peer_t * peer )
650{
651    return peer->progress;
652}
653
654/***********************************************************************
655 * tr_peerPort
656 ***********************************************************************
657 * Returns peer's listening port in host byte order
658 **********************************************************************/
659int tr_peerPort( tr_peer_t * peer )
660{
661    return ntohs( peer->port );
662}
663
664/***********************************************************************
665 * tr_peerBitfield
666 ***********************************************************************
667 *
668 **********************************************************************/
669tr_bitfield_t * tr_peerBitfield( tr_peer_t * peer )
670{
671    return peer->bitfield;
672}
673
674float tr_peerDownloadRate( tr_peer_t * peer )
675{
676    return tr_rcRate( peer->download );
677}
678
679float tr_peerUploadRate( tr_peer_t * peer )
680{
681    return tr_rcRate( peer->upload );
682}
683
684void tr_peerChoke( tr_peer_t * peer )
685{
686    sendChoke( peer, 1 );
687    peer->lastChoke = tr_date();
688}
689
690void tr_peerUnchoke( tr_peer_t * peer )
691{
692    sendChoke( peer, 0 );
693    peer->lastChoke = tr_date();
694}
695
696uint64_t tr_peerLastChoke( tr_peer_t * peer )
697{
698    return peer->lastChoke;
699}
700
701void tr_peerSetOptimistic( tr_peer_t * peer, int o )
702{
703    peer->optimistic = o;
704}
705
706int tr_peerIsOptimistic( tr_peer_t * peer )
707{
708    return peer->optimistic;
709}
710
711static inline int peerIsBad( tr_peer_t * peer )
712{
713    return ( peer->badPcs > 4 + 2 * peer->goodPcs );
714}
715
716static inline int peerIsGood( tr_peer_t * peer )
717{
718    return ( peer->goodPcs > 3 * peer->badPcs );
719}
720
721void tr_peerBlame( tr_peer_t * peer, int piece, int success )
722{
723    tr_torrent_t * tor = peer->tor;
724
725    if( !peer->blamefield || !tr_bitfieldHas( peer->blamefield, piece ) )
726    {
727        return;
728    }
729
730    if( success )
731    {
732        peer->goodPcs++;
733
734        if( peer->banfield && peerIsGood( peer ) )
735        {
736            /* Assume the peer wasn't responsible for the bad pieces
737               we was banned for */
738            tr_bitfieldClear( peer->banfield );
739        }
740    }
741    else
742    {
743        peer->badPcs++;
744
745        /* Ban the peer for this piece */
746        if( !peer->banfield )
747        {
748            peer->banfield = tr_bitfieldNew( tor->info.pieceCount );
749        }
750        tr_bitfieldAdd( peer->banfield, piece );
751
752        if( peerIsBad( peer ) )
753        {
754            /* Full ban */
755            peer_dbg( "banned (%d / %d)", peer->goodPcs, peer->badPcs );
756            peer->banned = 1;
757            peer->peerInterested = 0;
758        }
759    }
760    tr_bitfieldRem( peer->blamefield, piece );
761}
762
763int tr_peerGetConnectable( const tr_torrent_t * tor, uint8_t ** _buf )
764{
765    int count = 0;
766    uint8_t * buf;
767    tr_peer_t * peer;
768    int i;
769
770    if( tor->peerCount < 1 )
771    {
772        *_buf = NULL;
773        return 0;
774    }
775
776    buf = malloc( 6 * tor->peerCount );
777    for( i = 0; i < tor->peerCount; i++ )
778    {
779        peer = tor->peers[i];
780
781        /* Skip peers with no known listening port */
782        if( 0 == peer->port )
783            continue;
784
785        memcpy( &buf[count*6], &peer->addr, 4 );
786        memcpy( &buf[count*6+4], &peer->port, 2 );
787        count++;
788    }
789
790    if( count < 1 )
791    {
792        free( buf ); buf = NULL;
793    }
794    *_buf = buf;
795
796    return count * 6;
797}
Note: See TracBrowser for help on using the repository browser.