source: branches/file_selection/libtransmission/peer.c @ 2069

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

assertions for floam

  • Property svn:keywords set to Date Rev Author Id
File size: 22.3 KB
Line 
1/******************************************************************************
2 * $Id: peer.c 2069 2007-06-13 17:25:55Z 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 "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_cpGetState( tor->completion ) == 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.