source: trunk/libtransmission/peer-io.c @ 7125

Last change on this file since 7125 was 7125, checked in by charles, 12 years ago

(libT) better possible fix for #1468: Speed display is very jumpy

  • Property svn:keywords set to Date Rev Author Id
File size: 21.3 KB
Line 
1/*
2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: peer-io.c 7125 2008-11-17 04:00:57Z charles $
11 */
12
13#include <assert.h>
14#include <limits.h> /* INT_MAX */
15#include <string.h>
16#include <stdio.h>
17#include <unistd.h>
18
19#ifdef WIN32
20 #include <winsock2.h>
21#else
22 #include <netinet/in.h> /* struct in_addr */
23 #include <arpa/inet.h> /* inet_ntoa */
24#endif
25
26#include <event.h>
27
28#include "transmission.h"
29#include "crypto.h"
30#include "list.h"
31#include "net.h"
32#include "peer-io.h"
33#include "ratecontrol.h"
34#include "trevent.h"
35#include "utils.h"
36
37#define IO_TIMEOUT_SECS 8
38
39static size_t
40addPacketOverhead( size_t d )
41{
42    /**
43     * http://sd.wareonearth.com/~phil/net/overhead/
44     *
45     * TCP over Ethernet:
46     * Assuming no header compression (e.g. not PPP)
47     * Add 20 IPv4 header or 40 IPv6 header (no options)
48     * Add 20 TCP header
49     * Add 12 bytes optional TCP timestamps
50     * Max TCP Payload data rates over ethernet are thus:
51     *  (1500-40)/(38+1500) = 94.9285 %  IPv4, minimal headers
52     *  (1500-52)/(38+1500) = 94.1482 %  IPv4, TCP timestamps
53     *  (1500-52)/(42+1500) = 93.9040 %  802.1q, IPv4, TCP timestamps
54     *  (1500-60)/(38+1500) = 93.6281 %  IPv6, minimal headers
55     *  (1500-72)/(38+1500) = 92.8479 %  IPv6, TCP timestamps
56     *  (1500-72)/(42+1500) = 92.6070 %  802.1q, IPv6, ICP timestamps
57     */
58    static const double assumed_payload_data_rate = 94.0;
59
60    return (size_t)( d * ( 100.0 / assumed_payload_data_rate ) );
61}
62
63/**
64***
65**/
66
67#define dbgmsg( io, ... ) \
68    do { \
69        if( tr_deepLoggingIsActive( ) ) \
70            tr_deepLog( __FILE__, __LINE__, tr_peerIoGetAddrStr( io ), __VA_ARGS__ ); \
71    } while( 0 )
72
73struct tr_bandwidth
74{
75    unsigned int    isUnlimited : 1;
76    size_t          bytesUsed;
77    size_t          bytesLeft;
78};
79
80struct tr_datatype
81{
82    unsigned int    isPieceData : 1;
83    size_t          length;
84};
85
86struct tr_peerIo
87{
88    unsigned int           isEncrypted               : 1;
89    unsigned int           isIncoming                : 1;
90    unsigned int           peerIdIsSet               : 1;
91    unsigned int           extendedProtocolSupported : 1;
92    unsigned int           fastPeersSupported        : 1;
93
94    uint8_t                encryptionMode;
95    uint8_t                timeout;
96    uint16_t               port;
97    int                    socket;
98
99    uint8_t                peerId[20];
100    time_t                 timeCreated;
101
102    tr_session           * session;
103
104    struct in_addr         in_addr;
105    struct bufferevent   * bufev;
106    struct evbuffer      * output;
107    tr_list              * output_datatypes; /* struct tr_datatype */
108
109    tr_can_read_cb         canRead;
110    tr_did_write_cb        didWrite;
111    tr_net_error_cb        gotError;
112    void *                 userData;
113
114    size_t                 bufferSize[2];
115
116    struct tr_bandwidth    bandwidth[2];
117
118    tr_crypto *            crypto;
119};
120
121/**
122***
123**/
124
125static void
126adjustOutputBuffer( tr_peerIo * io )
127{
128    struct evbuffer * live = EVBUFFER_OUTPUT( io->bufev );
129
130    if( io->bandwidth[TR_UP].isUnlimited )
131    {
132        bufferevent_write_buffer( io->bufev, io->output );
133    }
134    else if( io->bandwidth[TR_UP].bytesLeft > EVBUFFER_LENGTH( live ) )
135    {
136        /* there's free space in bufev's output buffer;
137           try to fill it up */
138        const size_t desiredLength = io->bandwidth[TR_UP].bytesLeft;
139        const size_t under = desiredLength - EVBUFFER_LENGTH( live );
140        const size_t n = MIN( under, EVBUFFER_LENGTH( io->output ) );
141        bufferevent_write( io->bufev, EVBUFFER_DATA( io->output ), n );
142        evbuffer_drain( io->output, n );
143    }
144    else if( io->bandwidth[TR_UP].bytesLeft < EVBUFFER_LENGTH( live ) )
145    {
146        /* bufev's output buffer exceeds our bandwidth allocation;
147           move the excess out of bufev so it can't be sent yet */
148        const size_t      desiredLength = io->bandwidth[TR_UP].bytesLeft;
149        const size_t      over = EVBUFFER_LENGTH( live ) - desiredLength;
150        struct evbuffer * buf = evbuffer_new( );
151        evbuffer_add( buf, EVBUFFER_DATA( live ) + desiredLength, over );
152        evbuffer_add_buffer( buf, io->output );
153        evbuffer_free( io->output );
154        io->output = buf;
155        EVBUFFER_LENGTH( live ) = desiredLength;
156    }
157    else if( EVBUFFER_LENGTH( live ) )
158    {
159        bufferevent_enable( io->bufev, EV_WRITE );
160    }
161
162    io->bufferSize[TR_UP] = EVBUFFER_LENGTH( live );
163
164    dbgmsg( io, "after adjusting the output buffer, its size is now %zu",
165            io->bufferSize[TR_UP] );
166}
167
168static void
169adjustInputBuffer( tr_peerIo * io )
170{
171    if( io->bandwidth[TR_DOWN].isUnlimited )
172    {
173        dbgmsg( io, "unlimited reading..." );
174        bufferevent_setwatermark( io->bufev, EV_READ, 0, 0 );
175        bufferevent_enable( io->bufev, EV_READ );
176    }
177    else
178    {
179        const size_t n = io->bandwidth[TR_DOWN].bytesLeft;
180        if( n == 0 )
181        {
182            dbgmsg( io, "disabling reads because we've hit our limit" );
183            bufferevent_disable( io->bufev, EV_READ );
184        }
185        else
186        {
187            dbgmsg( io, "enabling reading of %zu more bytes", n );
188            bufferevent_setwatermark( io->bufev, EV_READ, 0, n );
189            bufferevent_enable( io->bufev, EV_READ );
190        }
191    }
192}
193
194/***
195****
196***/
197
198static void
199didWriteWrapper( struct bufferevent * e,
200                 void *               vio )
201{
202    tr_peerIo *  io = vio;
203    const size_t len = EVBUFFER_LENGTH( EVBUFFER_OUTPUT( e ) );
204
205    dbgmsg( io, "didWrite... io->outputBufferSize was %zu, is now %zu",
206            io->bufferSize[TR_UP], len );
207
208    if( len < io->bufferSize[TR_UP] )
209    {
210        size_t payload = io->bufferSize[TR_UP] - len;
211
212        while( payload )
213        {
214            struct tr_datatype * next = io->output_datatypes->data;
215            const size_t chunk_length = MIN( next->length, payload );
216            const size_t n = addPacketOverhead( chunk_length );
217
218            if( next->isPieceData )
219            {
220                struct tr_bandwidth * b = &io->bandwidth[TR_UP];
221                b->bytesLeft -= MIN( b->bytesLeft, n );
222                b->bytesUsed += n;
223            }
224
225            if( io->didWrite )
226                io->didWrite( io, n, next->isPieceData, io->userData );
227
228            payload -= chunk_length;
229            next->length -= chunk_length;
230            if( !next->length )
231                tr_free( tr_list_pop_front( &io->output_datatypes ) );
232        }
233    }
234
235    adjustOutputBuffer( io );
236
237}
238
239static void
240canReadWrapper( struct bufferevent * e,
241                void *               vio )
242{
243    int          done = 0;
244    int          err = 0;
245    tr_peerIo *  io = vio;
246    tr_session * session = io->session;
247    const size_t len = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
248
249    dbgmsg( io, "canRead" );
250
251    /* if the input buffer has grown, record the bytes that were read */
252    if( len > io->bufferSize[TR_DOWN] )
253    {
254        const size_t payload = len - io->bufferSize[TR_DOWN];
255        const size_t n = addPacketOverhead( payload );
256        struct tr_bandwidth * b = io->bandwidth + TR_DOWN;
257        b->bytesLeft -= MIN( b->bytesLeft, (size_t)n );
258        b->bytesUsed += n;
259        dbgmsg( io, "%zu new input bytes. bytesUsed is %zu, bytesLeft is %zu", n, b->bytesUsed, b->bytesLeft );
260
261        adjustInputBuffer( io );
262    }
263
264    /* try to consume the input buffer */
265    if( io->canRead )
266    {
267        tr_globalLock( session );
268
269        while( !done && !err )
270        {
271            const int ret = io->canRead( e, io->userData );
272
273            switch( ret )
274            {
275                case READ_NOW:
276                    if( EVBUFFER_LENGTH( e->input ) )
277                        continue;
278                    done = 1;
279                    break;
280
281                case READ_LATER:
282                    done = 1;
283                    break;
284
285                case READ_ERR:
286                    err = 1;
287                    break;
288            }
289        }
290
291        tr_globalUnlock( session );
292    }
293
294    if( !err )
295        io->bufferSize[TR_DOWN] = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
296}
297
298static void
299gotErrorWrapper( struct bufferevent * e,
300                 short                what,
301                 void *               userData )
302{
303    tr_peerIo * c = userData;
304
305    if( c->gotError )
306        c->gotError( e, what, c->userData );
307}
308
309/**
310***
311**/
312
313static void
314bufevNew( tr_peerIo * io )
315{
316    io->bufev = bufferevent_new( io->socket,
317                                 canReadWrapper,
318                                 didWriteWrapper,
319                                 gotErrorWrapper,
320                                 io );
321
322    /* tell libevent to call didWriteWrapper after every write,
323     * not just when the write buffer is empty */
324    bufferevent_setwatermark( io->bufev, EV_WRITE, INT_MAX, 0 );
325
326    bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
327
328    bufferevent_enable( io->bufev, EV_READ | EV_WRITE );
329}
330
331static tr_peerIo*
332tr_peerIoNew( tr_session *           session,
333              const struct in_addr * in_addr,
334              uint16_t               port,
335              const uint8_t *        torrentHash,
336              int                    isIncoming,
337              int                    socket )
338{
339    tr_peerIo * io;
340
341    if( socket >= 0 )
342        tr_netSetTOS( socket, session->peerSocketTOS );
343
344    io = tr_new0( tr_peerIo, 1 );
345    io->crypto = tr_cryptoNew( torrentHash, isIncoming );
346    io->session = session;
347    io->in_addr = *in_addr;
348    io->port = port;
349    io->socket = socket;
350    io->isIncoming = isIncoming != 0;
351    io->timeout = IO_TIMEOUT_SECS;
352    io->timeCreated = time( NULL );
353    io->output = evbuffer_new( );
354    io->bandwidth[TR_UP].isUnlimited = 1;
355    io->bandwidth[TR_DOWN].isUnlimited = 1;
356    bufevNew( io );
357    return io;
358}
359
360tr_peerIo*
361tr_peerIoNewIncoming( tr_session *           session,
362                      const struct in_addr * in_addr,
363                      uint16_t               port,
364                      int                    socket )
365{
366    assert( session );
367    assert( in_addr );
368    assert( socket >= 0 );
369
370    return tr_peerIoNew( session, in_addr, port,
371                         NULL, 1,
372                         socket );
373}
374
375tr_peerIo*
376tr_peerIoNewOutgoing( tr_session *           session,
377                      const struct in_addr * in_addr,
378                      int                    port,
379                      const uint8_t *        torrentHash )
380{
381    int socket;
382
383    assert( session );
384    assert( in_addr );
385    assert( port >= 0 );
386    assert( torrentHash );
387
388    socket = tr_netOpenTCP( in_addr, port );
389
390    return socket < 0
391           ? NULL
392           : tr_peerIoNew( session, in_addr, port, torrentHash, 0, socket );
393}
394
395static void
396io_dtor( void * vio )
397{
398    tr_peerIo * io = vio;
399
400    evbuffer_free( io->output );
401    bufferevent_free( io->bufev );
402    tr_netClose( io->socket );
403    tr_cryptoFree( io->crypto );
404    tr_list_free( &io->output_datatypes, tr_free );
405    tr_free( io );
406}
407
408void
409tr_peerIoFree( tr_peerIo * io )
410{
411    if( io )
412    {
413        io->canRead = NULL;
414        io->didWrite = NULL;
415        io->gotError = NULL;
416        tr_runInEventThread( io->session, io_dtor, io );
417    }
418}
419
420tr_session*
421tr_peerIoGetSession( tr_peerIo * io )
422{
423    assert( io );
424    assert( io->session );
425
426    return io->session;
427}
428
429const struct in_addr*
430tr_peerIoGetAddress( const tr_peerIo * io,
431                           uint16_t * port )
432{
433    assert( io );
434
435    if( port )
436        *port = io->port;
437
438    return &io->in_addr;
439}
440
441const char*
442tr_peerIoAddrStr( const struct in_addr * addr,
443                  uint16_t               port )
444{
445    static char buf[512];
446
447    tr_snprintf( buf, sizeof( buf ), "%s:%u", inet_ntoa( *addr ),
448                ntohs( port ) );
449    return buf;
450}
451
452const char*
453tr_peerIoGetAddrStr( const tr_peerIo * io )
454{
455    return tr_peerIoAddrStr( &io->in_addr, io->port );
456}
457
458static void
459tr_peerIoTryRead( tr_peerIo * io )
460{
461    if( EVBUFFER_LENGTH( io->bufev->input ) )
462        canReadWrapper( io->bufev, io );
463}
464
465void
466tr_peerIoSetIOFuncs( tr_peerIo *     io,
467                     tr_can_read_cb  readcb,
468                     tr_did_write_cb writecb,
469                     tr_net_error_cb errcb,
470                     void *          userData )
471{
472    io->canRead = readcb;
473    io->didWrite = writecb;
474    io->gotError = errcb;
475    io->userData = userData;
476
477    tr_peerIoTryRead( io );
478}
479
480int
481tr_peerIoIsIncoming( const tr_peerIo * c )
482{
483    return c->isIncoming ? 1 : 0;
484}
485
486int
487tr_peerIoReconnect( tr_peerIo * io )
488{
489    assert( !tr_peerIoIsIncoming( io ) );
490
491    if( io->socket >= 0 )
492        tr_netClose( io->socket );
493
494    io->socket = tr_netOpenTCP( &io->in_addr, io->port );
495
496    if( io->socket >= 0 )
497    {
498        tr_netSetTOS( io->socket, io->session->peerSocketTOS );
499
500        bufferevent_free( io->bufev );
501        bufevNew( io );
502        return 0;
503    }
504
505    return -1;
506}
507
508void
509tr_peerIoSetTimeoutSecs( tr_peerIo * io,
510                         int         secs )
511{
512    io->timeout = secs;
513    bufferevent_settimeout( io->bufev, io->timeout, io->timeout );
514    bufferevent_enable( io->bufev, EV_READ | EV_WRITE );
515}
516
517/**
518***
519**/
520
521void
522tr_peerIoSetTorrentHash( tr_peerIo *     io,
523                         const uint8_t * hash )
524{
525    assert( io );
526
527    tr_cryptoSetTorrentHash( io->crypto, hash );
528}
529
530const uint8_t*
531tr_peerIoGetTorrentHash( tr_peerIo * io )
532{
533    assert( io );
534    assert( io->crypto );
535
536    return tr_cryptoGetTorrentHash( io->crypto );
537}
538
539int
540tr_peerIoHasTorrentHash( const tr_peerIo * io )
541{
542    assert( io );
543    assert( io->crypto );
544
545    return tr_cryptoHasTorrentHash( io->crypto );
546}
547
548/**
549***
550**/
551
552void
553tr_peerIoSetPeersId( tr_peerIo *     io,
554                     const uint8_t * peer_id )
555{
556    assert( io );
557
558    if( ( io->peerIdIsSet = peer_id != NULL ) )
559        memcpy( io->peerId, peer_id, 20 );
560    else
561        memset( io->peerId, 0, 20 );
562}
563
564const uint8_t*
565tr_peerIoGetPeersId( const tr_peerIo * io )
566{
567    assert( io );
568    assert( io->peerIdIsSet );
569
570    return io->peerId;
571}
572
573/**
574***
575**/
576
577void
578tr_peerIoEnableLTEP( tr_peerIo * io,
579                     int         flag )
580{
581    assert( io );
582    assert( flag == 0 || flag == 1 );
583
584    io->extendedProtocolSupported = flag;
585}
586
587void
588tr_peerIoEnableFEXT( tr_peerIo * io,
589                     int         flag )
590{
591    assert( io );
592    assert( flag == 0 || flag == 1 );
593
594    io->fastPeersSupported = flag;
595}
596
597int
598tr_peerIoSupportsLTEP( const tr_peerIo * io )
599{
600    assert( io );
601
602    return io->extendedProtocolSupported;
603}
604
605int
606tr_peerIoSupportsFEXT( const tr_peerIo * io )
607{
608    assert( io );
609
610    return io->fastPeersSupported;
611}
612
613/**
614***
615**/
616
617size_t
618tr_peerIoGetBandwidthUsed( const tr_peerIo * io,
619                           tr_direction      direction )
620{
621    assert( io );
622    assert( direction == TR_UP || direction == TR_DOWN );
623    return io->bandwidth[direction].bytesUsed;
624}
625
626size_t
627tr_peerIoGetWriteBufferSpace( const tr_peerIo * io )
628{
629    const size_t desiredBufferLen = 4096;
630    const size_t currentLiveLen = EVBUFFER_LENGTH( EVBUFFER_OUTPUT( io->bufev ) );
631
632    const size_t currentLbufLen = EVBUFFER_LENGTH( io->output );
633    const size_t desiredLiveLen = io->bandwidth[TR_UP].isUnlimited
634                                ? INT_MAX
635                                : io->bandwidth[TR_UP].bytesLeft;
636
637    const size_t currentLen = currentLiveLen + currentLbufLen;
638    const size_t desiredLen = desiredBufferLen + desiredLiveLen;
639
640    size_t       freeSpace = 0;
641
642    if( desiredLen > currentLen )
643        freeSpace = desiredLen - currentLen;
644    else
645        freeSpace = 0;
646
647    return freeSpace;
648}
649
650void
651tr_peerIoSetBandwidth( tr_peerIo *  io,
652                       tr_direction direction,
653                       size_t       bytesLeft )
654{
655    struct tr_bandwidth * b;
656
657    assert( io );
658    assert( direction == TR_UP || direction == TR_DOWN );
659
660    b = io->bandwidth + direction;
661    b->isUnlimited = 0;
662    b->bytesUsed = 0;
663    b->bytesLeft = bytesLeft;
664
665    adjustOutputBuffer( io );
666    adjustInputBuffer( io );
667}
668
669void
670tr_peerIoSetBandwidthUnlimited( tr_peerIo *  io,
671                                tr_direction direction )
672{
673    struct tr_bandwidth * b;
674
675    assert( io );
676    assert( direction == TR_UP || direction == TR_DOWN );
677
678    b = io->bandwidth + direction;
679    b->isUnlimited = 1;
680    b->bytesUsed = 0;
681    b->bytesLeft = 0;
682
683    adjustInputBuffer( io );
684    adjustOutputBuffer( io );
685}
686
687/**
688***
689**/
690
691tr_crypto*
692tr_peerIoGetCrypto( tr_peerIo * c )
693{
694    return c->crypto;
695}
696
697void
698tr_peerIoSetEncryption( tr_peerIo * io,
699                        int         encryptionMode )
700{
701    assert( io );
702    assert( encryptionMode == PEER_ENCRYPTION_NONE
703          || encryptionMode == PEER_ENCRYPTION_RC4 );
704
705    io->encryptionMode = encryptionMode;
706}
707
708int
709tr_peerIoIsEncrypted( const tr_peerIo * io )
710{
711    return io != NULL && io->encryptionMode == PEER_ENCRYPTION_RC4;
712}
713
714/**
715***
716**/
717
718int
719tr_peerIoWantsBandwidth( const tr_peerIo * io,
720                         tr_direction      direction )
721{
722    assert( direction == TR_UP || direction == TR_DOWN );
723
724    if( direction == TR_DOWN )
725    {
726        return TRUE; /* FIXME -- is there a good way to test for this? */
727    }
728    else
729    {
730        return EVBUFFER_LENGTH( EVBUFFER_OUTPUT( io->bufev ) )
731               || EVBUFFER_LENGTH( io->output );
732    }
733}
734
735void
736tr_peerIoWrite( tr_peerIo   * io,
737                const void  * writeme,
738                size_t        writemeLen,
739                int           isPieceData )
740{
741    struct tr_datatype * datatype;
742    assert( tr_amInEventThread( io->session ) );
743    dbgmsg( io, "adding %zu bytes into io->output", writemeLen );
744
745    if( io->bandwidth[TR_UP].isUnlimited )
746        bufferevent_write( io->bufev, writeme, writemeLen );
747    else
748        evbuffer_add( io->output, writeme, writemeLen );
749
750    datatype = tr_new( struct tr_datatype, 1 );
751    datatype->isPieceData = isPieceData != 0;
752    datatype->length = writemeLen;
753    tr_list_append( &io->output_datatypes, datatype );
754
755    adjustOutputBuffer( io );
756}
757
758void
759tr_peerIoWriteBuf( tr_peerIo         * io,
760                   struct evbuffer   * buf,
761                   int                 isPieceData )
762{
763    const size_t n = EVBUFFER_LENGTH( buf );
764
765    tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n, isPieceData );
766    evbuffer_drain( buf, n );
767}
768
769/**
770***
771**/
772
773void
774tr_peerIoWriteBytes( tr_peerIo *       io,
775                     struct evbuffer * outbuf,
776                     const void *      bytes,
777                     size_t            byteCount )
778{
779    uint8_t * tmp;
780
781    switch( io->encryptionMode )
782    {
783        case PEER_ENCRYPTION_NONE:
784            evbuffer_add( outbuf, bytes, byteCount );
785            break;
786
787        case PEER_ENCRYPTION_RC4:
788            tmp = tr_new( uint8_t, byteCount );
789            tr_cryptoEncrypt( io->crypto, byteCount, bytes, tmp );
790            evbuffer_add( outbuf, tmp, byteCount );
791            tr_free( tmp );
792            break;
793
794        default:
795            assert( 0 );
796    }
797}
798
799void
800tr_peerIoWriteUint8( tr_peerIo *       io,
801                     struct evbuffer * outbuf,
802                     uint8_t           writeme )
803{
804    tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof( uint8_t ) );
805}
806
807void
808tr_peerIoWriteUint16( tr_peerIo *       io,
809                      struct evbuffer * outbuf,
810                      uint16_t          writeme )
811{
812    uint16_t tmp = htons( writeme );
813
814    tr_peerIoWriteBytes( io, outbuf, &tmp, sizeof( uint16_t ) );
815}
816
817void
818tr_peerIoWriteUint32( tr_peerIo *       io,
819                      struct evbuffer * outbuf,
820                      uint32_t          writeme )
821{
822    uint32_t tmp = htonl( writeme );
823
824    tr_peerIoWriteBytes( io, outbuf, &tmp, sizeof( uint32_t ) );
825}
826
827/***
828****
829***/
830
831void
832tr_peerIoReadBytes( tr_peerIo *       io,
833                    struct evbuffer * inbuf,
834                    void *            bytes,
835                    size_t            byteCount )
836{
837    assert( EVBUFFER_LENGTH( inbuf ) >= byteCount );
838
839    switch( io->encryptionMode )
840    {
841        case PEER_ENCRYPTION_NONE:
842            evbuffer_remove( inbuf, bytes, byteCount );
843            break;
844
845        case PEER_ENCRYPTION_RC4:
846            evbuffer_remove( inbuf, bytes, byteCount );
847            tr_cryptoDecrypt( io->crypto, byteCount, bytes, bytes );
848            break;
849
850        default:
851            assert( 0 );
852    }
853}
854
855void
856tr_peerIoReadUint8( tr_peerIo *       io,
857                    struct evbuffer * inbuf,
858                    uint8_t *         setme )
859{
860    tr_peerIoReadBytes( io, inbuf, setme, sizeof( uint8_t ) );
861}
862
863void
864tr_peerIoReadUint16( tr_peerIo *       io,
865                     struct evbuffer * inbuf,
866                     uint16_t *        setme )
867{
868    uint16_t tmp;
869
870    tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint16_t ) );
871    *setme = ntohs( tmp );
872}
873
874void
875tr_peerIoReadUint32( tr_peerIo *       io,
876                     struct evbuffer * inbuf,
877                     uint32_t *        setme )
878{
879    uint32_t tmp;
880
881    tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint32_t ) );
882    *setme = ntohl( tmp );
883}
884
885void
886tr_peerIoDrain( tr_peerIo *       io,
887                struct evbuffer * inbuf,
888                size_t            byteCount )
889{
890    uint8_t * tmp = tr_new( uint8_t, byteCount );
891
892    tr_peerIoReadBytes( io, inbuf, tmp, byteCount );
893    tr_free( tmp );
894}
895
896int
897tr_peerIoGetAge( const tr_peerIo * io )
898{
899    return time( NULL ) - io->timeCreated;
900}
901
Note: See TracBrowser for help on using the repository browser.