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