/* * This file Copyright (C) 2007-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * * $Id$ */ #ifndef __TRANSMISSION__ #error only libtransmission should #include this header. #endif #ifndef TR_PEER_IO_H #define TR_PEER_IO_H /** *** **/ #include #include "transmission.h" #include "bandwidth.h" #include "crypto.h" #include "net.h" /* tr_address */ #include "utils.h" /* tr_time () */ struct evbuffer; struct tr_bandwidth; struct tr_datatype; struct tr_peerIo; /** * @addtogroup networked_io Networked IO * @{ */ typedef enum { READ_NOW, READ_LATER, READ_ERR } ReadState; typedef enum { /* these match the values in MSE's crypto_select */ PEER_ENCRYPTION_NONE = (1 << 0), PEER_ENCRYPTION_RC4 = (1 << 1) } tr_encryption_type; typedef ReadState (*tr_can_read_cb)(struct tr_peerIo * io, void * user_data, size_t * setme_piece_byte_count); typedef void (*tr_did_write_cb)(struct tr_peerIo * io, size_t bytesWritten, bool wasPieceData, void * userData); typedef void (*tr_net_error_cb)(struct tr_peerIo * io, short what, void * userData); typedef struct tr_peerIo { bool isEncrypted; bool isIncoming; bool peerIdIsSet; bool extendedProtocolSupported; bool fastExtensionSupported; bool dhtSupported; bool utpSupported; tr_priority_t priority; short int pendingEvents; int magicNumber; tr_encryption_type encryption_type; bool isSeed; tr_port port; tr_socket_t socket; struct UTPSocket * utp_socket; int refCount; uint8_t peerId[SHA_DIGEST_LENGTH]; time_t timeCreated; tr_session * session; tr_address addr; tr_can_read_cb canRead; tr_did_write_cb didWrite; tr_net_error_cb gotError; void * userData; struct tr_bandwidth bandwidth; tr_crypto crypto; struct evbuffer * inbuf; struct evbuffer * outbuf; struct tr_datatype * outbuf_datatypes; struct event * event_read; struct event * event_write; } tr_peerIo; /** *** **/ tr_peerIo* tr_peerIoNewOutgoing (tr_session * session, struct tr_bandwidth * parent, const struct tr_address * addr, tr_port port, const uint8_t * torrentHash, bool isSeed, bool utp); tr_peerIo* tr_peerIoNewIncoming (tr_session * session, struct tr_bandwidth * parent, const struct tr_address * addr, tr_port port, tr_socket_t socket, struct UTPSocket * utp_socket); void tr_peerIoRefImpl (const char * file, int line, tr_peerIo * io); #define tr_peerIoRef(io) tr_peerIoRefImpl (__FILE__, __LINE__, (io)); void tr_peerIoUnrefImpl (const char * file, int line, tr_peerIo * io); #define tr_peerIoUnref(io) tr_peerIoUnrefImpl (__FILE__, __LINE__, (io)); #define PEER_IO_MAGIC_NUMBER 206745 static inline bool tr_isPeerIo (const tr_peerIo * io) { return (io != NULL) && (io->magicNumber == PEER_IO_MAGIC_NUMBER) && (io->refCount >= 0) && (tr_isBandwidth (&io->bandwidth)) && (tr_address_is_valid (&io->addr)); } /** *** **/ static inline void tr_peerIoEnableFEXT (tr_peerIo * io, bool flag) { io->fastExtensionSupported = flag; } static inline bool tr_peerIoSupportsFEXT (const tr_peerIo * io) { return io->fastExtensionSupported; } static inline void tr_peerIoEnableLTEP (tr_peerIo * io, bool flag) { io->extendedProtocolSupported = flag; } static inline bool tr_peerIoSupportsLTEP (const tr_peerIo * io) { return io->extendedProtocolSupported; } static inline void tr_peerIoEnableDHT (tr_peerIo * io, bool flag) { io->dhtSupported = flag; } static inline bool tr_peerIoSupportsDHT (const tr_peerIo * io) { return io->dhtSupported; } static inline bool tr_peerIoSupportsUTP (const tr_peerIo * io) { return io->utpSupported; } /** *** **/ static inline tr_session* tr_peerIoGetSession (tr_peerIo * io) { assert (tr_isPeerIo (io)); assert (io->session); return io->session; } const char* tr_peerIoAddrStr (const struct tr_address * addr, tr_port port); const char* tr_peerIoGetAddrStr (const tr_peerIo * io); const struct tr_address * tr_peerIoGetAddress (const tr_peerIo * io, tr_port * port); const uint8_t* tr_peerIoGetTorrentHash (tr_peerIo * io); bool tr_peerIoHasTorrentHash (const tr_peerIo * io); void tr_peerIoSetTorrentHash (tr_peerIo * io, const uint8_t * hash); int tr_peerIoReconnect (tr_peerIo * io); static inline bool tr_peerIoIsIncoming (const tr_peerIo * io) { return io->isIncoming; } static inline int tr_peerIoGetAge (const tr_peerIo * io) { return tr_time () - io->timeCreated; } /** *** **/ void tr_peerIoSetPeersId (tr_peerIo * io, const uint8_t * peer_id); static inline const uint8_t* tr_peerIoGetPeersId (const tr_peerIo * io) { assert (tr_isPeerIo (io)); assert (io->peerIdIsSet); return io->peerId; } /** *** **/ void tr_peerIoSetIOFuncs (tr_peerIo * io, tr_can_read_cb readcb, tr_did_write_cb writecb, tr_net_error_cb errcb, void * user_data); void tr_peerIoClear (tr_peerIo * io); /** *** **/ void tr_peerIoWriteBytes (tr_peerIo * io, const void * writeme, size_t writemeLen, bool isPieceData); void tr_peerIoWriteBuf (tr_peerIo * io, struct evbuffer * buf, bool isPieceData); /** *** **/ static inline tr_crypto * tr_peerIoGetCrypto (tr_peerIo * io) { return &io->crypto; } void tr_peerIoSetEncryption (tr_peerIo * io, tr_encryption_type encryption_type); static inline bool tr_peerIoIsEncrypted (const tr_peerIo * io) { return (io != NULL) && (io->encryption_type == PEER_ENCRYPTION_RC4); } void evbuffer_add_uint8 (struct evbuffer * outbuf, uint8_t byte); void evbuffer_add_uint16 (struct evbuffer * outbuf, uint16_t hs); void evbuffer_add_uint32 (struct evbuffer * outbuf, uint32_t hl); void evbuffer_add_uint64 (struct evbuffer * outbuf, uint64_t hll); static inline void evbuffer_add_hton_16 (struct evbuffer * buf, uint16_t val) { evbuffer_add_uint16 (buf, val); } static inline void evbuffer_add_hton_32 (struct evbuffer * buf, uint32_t val) { evbuffer_add_uint32 (buf, val); } static inline void evbuffer_add_hton_64 (struct evbuffer * buf, uint64_t val) { evbuffer_add_uint64 (buf, val); } void tr_peerIoReadBytesToBuf (tr_peerIo * io, struct evbuffer * inbuf, struct evbuffer * outbuf, size_t byteCount); void tr_peerIoReadBytes (tr_peerIo * io, struct evbuffer * inbuf, void * bytes, size_t byteCount); static inline void tr_peerIoReadUint8 (tr_peerIo * io, struct evbuffer * inbuf, uint8_t * setme) { tr_peerIoReadBytes (io, inbuf, setme, sizeof (uint8_t)); } void tr_peerIoReadUint16 (tr_peerIo * io, struct evbuffer * inbuf, uint16_t * setme); void tr_peerIoReadUint32 (tr_peerIo * io, struct evbuffer * inbuf, uint32_t * setme); void tr_peerIoDrain (tr_peerIo * io, struct evbuffer * inbuf, size_t byteCount); /** *** **/ size_t tr_peerIoGetWriteBufferSpace (const tr_peerIo * io, uint64_t now); static inline void tr_peerIoSetParent (tr_peerIo * io, struct tr_bandwidth * parent) { assert (tr_isPeerIo (io)); tr_bandwidthSetParent (&io->bandwidth, parent); } void tr_peerIoBandwidthUsed (tr_peerIo * io, tr_direction direction, size_t byteCount, int isPieceData); static inline bool tr_peerIoHasBandwidthLeft (const tr_peerIo * io, tr_direction dir) { return tr_bandwidthClamp (&io->bandwidth, dir, 1024) > 0; } static inline unsigned int tr_peerIoGetPieceSpeed_Bps (const tr_peerIo * io, uint64_t now, tr_direction dir) { return tr_bandwidthGetPieceSpeed_Bps (&io->bandwidth, now, dir); } /** *** **/ void tr_peerIoSetEnabled (tr_peerIo * io, tr_direction dir, bool isEnabled); int tr_peerIoFlush (tr_peerIo * io, tr_direction dir, size_t byteLimit); int tr_peerIoFlushOutgoingProtocolMsgs (tr_peerIo * io); /** *** **/ static inline struct evbuffer * tr_peerIoGetReadBuffer (tr_peerIo * io) { return io->inbuf; } /* @} */ #endif