1 /*
2  * This file Copyright (C) 2007-2014 Mnemosyne LLC
3  *
4  * It may be used under the GNU GPL versions 2 or 3
5  * or any future license endorsed by Mnemosyne LLC.
6  *
7  */
8 
9 #pragma once
10 
11 #ifndef __TRANSMISSION__
12 #error only libtransmission should #include this header.
13 #endif
14 
15 /**
16 ***
17 **/
18 
19 #include <assert.h>
20 
21 #include "transmission.h"
22 #include "bandwidth.h"
23 #include "crypto.h"
24 #include "net.h" /* tr_address */
25 #include "peer-socket.h"
26 #include "utils.h" /* tr_time() */
27 
28 struct evbuffer;
29 struct tr_bandwidth;
30 struct tr_datatype;
31 struct tr_peerIo;
32 
33 /**
34  * @addtogroup networked_io Networked IO
35  * @{
36  */
37 
38 typedef enum
39 {
40     READ_NOW,
41     READ_LATER,
42     READ_ERR
43 }
44 ReadState;
45 
46 typedef enum
47 {
48     /* these match the values in MSE's crypto_select */
49     PEER_ENCRYPTION_NONE = (1 << 0),
50     PEER_ENCRYPTION_RC4 = (1 << 1)
51 }
52 tr_encryption_type;
53 
54 typedef ReadState (* tr_can_read_cb)(struct tr_peerIo* io, void* user_data, size_t* setme_piece_byte_count);
55 
56 typedef void (* tr_did_write_cb)(struct tr_peerIo* io, size_t bytesWritten, bool wasPieceData, void* userData);
57 
58 typedef void (* tr_net_error_cb)(struct tr_peerIo* io, short what, void* userData);
59 
60 typedef struct tr_peerIo
61 {
62     bool isEncrypted;
63     bool isIncoming;
64     bool peerIdIsSet;
65     bool extendedProtocolSupported;
66     bool fastExtensionSupported;
67     bool dhtSupported;
68     bool utpSupported;
69 
70     tr_priority_t priority;
71 
72     short int pendingEvents;
73 
74     int magicNumber;
75 
76     tr_encryption_type encryption_type;
77     bool isSeed;
78 
79     tr_port port;
80     struct tr_peer_socket socket;
81 
82     int refCount;
83 
84     uint8_t peerId[SHA_DIGEST_LENGTH];
85     time_t timeCreated;
86 
87     tr_session* session;
88 
89     tr_address addr;
90 
91     tr_can_read_cb canRead;
92     tr_did_write_cb didWrite;
93     tr_net_error_cb gotError;
94     void* userData;
95 
96     struct tr_bandwidth bandwidth;
97     tr_crypto crypto;
98 
99     struct evbuffer* inbuf;
100     struct evbuffer* outbuf;
101     struct tr_datatype* outbuf_datatypes;
102 
103     struct event* event_read;
104     struct event* event_write;
105 }
106 tr_peerIo;
107 
108 /**
109 ***
110 **/
111 
112 tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, struct tr_bandwidth* parent, struct tr_address const* addr, tr_port port,
113     uint8_t const* torrentHash, bool isSeed, bool utp);
114 
115 tr_peerIo* tr_peerIoNewIncoming(tr_session* session, struct tr_bandwidth* parent, struct tr_address const* addr, tr_port port,
116     struct tr_peer_socket socket);
117 
118 void tr_peerIoRefImpl(char const* file, int line, tr_peerIo* io);
119 
120 #define tr_peerIoRef(io) tr_peerIoRefImpl(__FILE__, __LINE__, (io));
121 
122 void tr_peerIoUnrefImpl(char const* file, int line, tr_peerIo* io);
123 
124 #define tr_peerIoUnref(io) tr_peerIoUnrefImpl(__FILE__, __LINE__, (io));
125 
126 #define PEER_IO_MAGIC_NUMBER 206745
127 
tr_isPeerIo(tr_peerIo const * io)128 static inline bool tr_isPeerIo(tr_peerIo const* io)
129 {
130     return io != NULL && io->magicNumber == PEER_IO_MAGIC_NUMBER && io->refCount >= 0 && tr_isBandwidth(&io->bandwidth) &&
131         tr_address_is_valid(&io->addr);
132 }
133 
134 /**
135 ***
136 **/
137 
tr_peerIoEnableFEXT(tr_peerIo * io,bool flag)138 static inline void tr_peerIoEnableFEXT(tr_peerIo* io, bool flag)
139 {
140     io->fastExtensionSupported = flag;
141 }
142 
tr_peerIoSupportsFEXT(tr_peerIo const * io)143 static inline bool tr_peerIoSupportsFEXT(tr_peerIo const* io)
144 {
145     return io->fastExtensionSupported;
146 }
147 
tr_peerIoEnableLTEP(tr_peerIo * io,bool flag)148 static inline void tr_peerIoEnableLTEP(tr_peerIo* io, bool flag)
149 {
150     io->extendedProtocolSupported = flag;
151 }
152 
tr_peerIoSupportsLTEP(tr_peerIo const * io)153 static inline bool tr_peerIoSupportsLTEP(tr_peerIo const* io)
154 {
155     return io->extendedProtocolSupported;
156 }
157 
tr_peerIoEnableDHT(tr_peerIo * io,bool flag)158 static inline void tr_peerIoEnableDHT(tr_peerIo* io, bool flag)
159 {
160     io->dhtSupported = flag;
161 }
162 
tr_peerIoSupportsDHT(tr_peerIo const * io)163 static inline bool tr_peerIoSupportsDHT(tr_peerIo const* io)
164 {
165     return io->dhtSupported;
166 }
167 
tr_peerIoSupportsUTP(tr_peerIo const * io)168 static inline bool tr_peerIoSupportsUTP(tr_peerIo const* io)
169 {
170     return io->utpSupported;
171 }
172 
173 /**
174 ***
175 **/
176 
tr_peerIoGetSession(tr_peerIo * io)177 static inline tr_session* tr_peerIoGetSession(tr_peerIo* io)
178 {
179     TR_ASSERT(tr_isPeerIo(io));
180     TR_ASSERT(io->session != NULL);
181 
182     return io->session;
183 }
184 
185 char const* tr_peerIoAddrStr(struct tr_address const* addr, tr_port port);
186 
187 char const* tr_peerIoGetAddrStr(tr_peerIo const* io);
188 
189 struct tr_address const* tr_peerIoGetAddress(tr_peerIo const* io, tr_port* port);
190 
191 uint8_t const* tr_peerIoGetTorrentHash(tr_peerIo* io);
192 
193 bool tr_peerIoHasTorrentHash(tr_peerIo const* io);
194 
195 void tr_peerIoSetTorrentHash(tr_peerIo* io, uint8_t const* hash);
196 
197 int tr_peerIoReconnect(tr_peerIo* io);
198 
tr_peerIoIsIncoming(tr_peerIo const * io)199 static inline bool tr_peerIoIsIncoming(tr_peerIo const* io)
200 {
201     return io->isIncoming;
202 }
203 
tr_peerIoGetAge(tr_peerIo const * io)204 static inline int tr_peerIoGetAge(tr_peerIo const* io)
205 {
206     return tr_time() - io->timeCreated;
207 }
208 
209 /**
210 ***
211 **/
212 
213 void tr_peerIoSetPeersId(tr_peerIo* io, uint8_t const* peer_id);
214 
tr_peerIoGetPeersId(tr_peerIo const * io)215 static inline uint8_t const* tr_peerIoGetPeersId(tr_peerIo const* io)
216 {
217     TR_ASSERT(tr_isPeerIo(io));
218     TR_ASSERT(io->peerIdIsSet);
219 
220     return io->peerId;
221 }
222 
223 /**
224 ***
225 **/
226 
227 void tr_peerIoSetIOFuncs(tr_peerIo* io, tr_can_read_cb readcb, tr_did_write_cb writecb, tr_net_error_cb errcb, void* user_data);
228 
229 void tr_peerIoClear(tr_peerIo* io);
230 
231 /**
232 ***
233 **/
234 
235 void tr_peerIoWriteBytes(tr_peerIo* io, void const* writeme, size_t writemeLen, bool isPieceData);
236 
237 void tr_peerIoWriteBuf(tr_peerIo* io, struct evbuffer* buf, bool isPieceData);
238 
239 /**
240 ***
241 **/
242 
tr_peerIoGetCrypto(tr_peerIo * io)243 static inline tr_crypto* tr_peerIoGetCrypto(tr_peerIo* io)
244 {
245     return &io->crypto;
246 }
247 
248 void tr_peerIoSetEncryption(tr_peerIo* io, tr_encryption_type encryption_type);
249 
tr_peerIoIsEncrypted(tr_peerIo const * io)250 static inline bool tr_peerIoIsEncrypted(tr_peerIo const* io)
251 {
252     return io != NULL && io->encryption_type == PEER_ENCRYPTION_RC4;
253 }
254 
255 void evbuffer_add_uint8(struct evbuffer* outbuf, uint8_t byte);
256 void evbuffer_add_uint16(struct evbuffer* outbuf, uint16_t hs);
257 void evbuffer_add_uint32(struct evbuffer* outbuf, uint32_t hl);
258 void evbuffer_add_uint64(struct evbuffer* outbuf, uint64_t hll);
259 
evbuffer_add_hton_16(struct evbuffer * buf,uint16_t val)260 static inline void evbuffer_add_hton_16(struct evbuffer* buf, uint16_t val)
261 {
262     evbuffer_add_uint16(buf, val);
263 }
264 
evbuffer_add_hton_32(struct evbuffer * buf,uint32_t val)265 static inline void evbuffer_add_hton_32(struct evbuffer* buf, uint32_t val)
266 {
267     evbuffer_add_uint32(buf, val);
268 }
269 
evbuffer_add_hton_64(struct evbuffer * buf,uint64_t val)270 static inline void evbuffer_add_hton_64(struct evbuffer* buf, uint64_t val)
271 {
272     evbuffer_add_uint64(buf, val);
273 }
274 
275 void tr_peerIoReadBytesToBuf(tr_peerIo* io, struct evbuffer* inbuf, struct evbuffer* outbuf, size_t byteCount);
276 
277 void tr_peerIoReadBytes(tr_peerIo* io, struct evbuffer* inbuf, void* bytes, size_t byteCount);
278 
tr_peerIoReadUint8(tr_peerIo * io,struct evbuffer * inbuf,uint8_t * setme)279 static inline void tr_peerIoReadUint8(tr_peerIo* io, struct evbuffer* inbuf, uint8_t* setme)
280 {
281     tr_peerIoReadBytes(io, inbuf, setme, sizeof(uint8_t));
282 }
283 
284 void tr_peerIoReadUint16(tr_peerIo* io, struct evbuffer* inbuf, uint16_t* setme);
285 
286 void tr_peerIoReadUint32(tr_peerIo* io, struct evbuffer* inbuf, uint32_t* setme);
287 
288 void tr_peerIoDrain(tr_peerIo* io, struct evbuffer* inbuf, size_t byteCount);
289 
290 /**
291 ***
292 **/
293 
294 size_t tr_peerIoGetWriteBufferSpace(tr_peerIo const* io, uint64_t now);
295 
tr_peerIoSetParent(tr_peerIo * io,struct tr_bandwidth * parent)296 static inline void tr_peerIoSetParent(tr_peerIo* io, struct tr_bandwidth* parent)
297 {
298     TR_ASSERT(tr_isPeerIo(io));
299 
300     tr_bandwidthSetParent(&io->bandwidth, parent);
301 }
302 
303 void tr_peerIoBandwidthUsed(tr_peerIo* io, tr_direction direction, size_t byteCount, int isPieceData);
304 
tr_peerIoHasBandwidthLeft(tr_peerIo const * io,tr_direction dir)305 static inline bool tr_peerIoHasBandwidthLeft(tr_peerIo const* io, tr_direction dir)
306 {
307     return tr_bandwidthClamp(&io->bandwidth, dir, 1024) > 0;
308 }
309 
tr_peerIoGetPieceSpeed_Bps(tr_peerIo const * io,uint64_t now,tr_direction dir)310 static inline unsigned int tr_peerIoGetPieceSpeed_Bps(tr_peerIo const* io, uint64_t now, tr_direction dir)
311 {
312     return tr_bandwidthGetPieceSpeed_Bps(&io->bandwidth, now, dir);
313 }
314 
315 /**
316 ***
317 **/
318 
319 void tr_peerIoSetEnabled(tr_peerIo* io, tr_direction dir, bool isEnabled);
320 
321 int tr_peerIoFlush(tr_peerIo* io, tr_direction dir, size_t byteLimit);
322 
323 int tr_peerIoFlushOutgoingProtocolMsgs(tr_peerIo* io);
324 
325 /**
326 ***
327 **/
328 
tr_peerIoGetReadBuffer(tr_peerIo * io)329 static inline struct evbuffer* tr_peerIoGetReadBuffer(tr_peerIo* io)
330 {
331     return io->inbuf;
332 }
333 
334 /* @} */
335