1 /*
2 Copyright (c) 2010 by Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21
22 */
23
24 #include <string.h> /* memcmp(), memcpy(), memset() */
25 #include <stdlib.h> /* malloc(), free() */
26
27 #ifdef _WIN32
28 #include <io.h> /* dup2() */
29 #else
30 #include <unistd.h> /* dup2() */
31 #endif
32
33 #include <event2/event.h>
34
35 #include <libutp/utp.h>
36
37 #include "transmission.h"
38 #include "log.h"
39 #include "net.h"
40 #include "session.h"
41 #include "tr-assert.h"
42 #include "tr-dht.h"
43 #include "tr-utp.h"
44 #include "tr-udp.h"
45
46 /* Since we use a single UDP socket in order to implement multiple
47 uTP sockets, try to set up huge buffers. */
48
49 #define RECV_BUFFER_SIZE (4 * 1024 * 1024)
50 #define SEND_BUFFER_SIZE (1 * 1024 * 1024)
51 #define SMALL_BUFFER_SIZE (32 * 1024)
52
set_socket_buffers(tr_socket_t fd,bool large)53 static void set_socket_buffers(tr_socket_t fd, bool large)
54 {
55 int size;
56 int rbuf;
57 int sbuf;
58 int rc;
59 socklen_t rbuf_len = sizeof(rbuf);
60 socklen_t sbuf_len = sizeof(sbuf);
61 char err_buf[512];
62
63 size = large ? RECV_BUFFER_SIZE : SMALL_BUFFER_SIZE;
64 rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void const*)&size, sizeof(size));
65
66 if (rc < 0)
67 {
68 tr_logAddNamedError("UDP", "Failed to set receive buffer: %s", tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
69 }
70
71 size = large ? SEND_BUFFER_SIZE : SMALL_BUFFER_SIZE;
72 rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void const*)&size, sizeof(size));
73
74 if (rc < 0)
75 {
76 tr_logAddNamedError("UDP", "Failed to set send buffer: %s", tr_net_strerror(err_buf, sizeof(err_buf), sockerrno));
77 }
78
79 if (large)
80 {
81 rc = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&rbuf, &rbuf_len);
82
83 if (rc < 0)
84 {
85 rbuf = 0;
86 }
87
88 rc = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&sbuf, &sbuf_len);
89
90 if (rc < 0)
91 {
92 sbuf = 0;
93 }
94
95 if (rbuf < RECV_BUFFER_SIZE)
96 {
97 tr_logAddNamedError("UDP", "Failed to set receive buffer: requested %d, got %d", RECV_BUFFER_SIZE, rbuf);
98 #ifdef __linux__
99 tr_logAddNamedInfo("UDP", "Please add the line \"net.core.rmem_max = %d\" to /etc/sysctl.conf", RECV_BUFFER_SIZE);
100 #endif
101 }
102
103 if (sbuf < SEND_BUFFER_SIZE)
104 {
105 tr_logAddNamedError("UDP", "Failed to set send buffer: requested %d, got %d", SEND_BUFFER_SIZE, sbuf);
106 #ifdef __linux__
107 tr_logAddNamedInfo("UDP", "Please add the line \"net.core.wmem_max = %d\" to /etc/sysctl.conf", SEND_BUFFER_SIZE);
108 #endif
109 }
110 }
111 }
112
tr_udpSetSocketBuffers(tr_session * session)113 void tr_udpSetSocketBuffers(tr_session* session)
114 {
115 bool utp = tr_sessionIsUTPEnabled(session);
116
117 if (session->udp_socket != TR_BAD_SOCKET)
118 {
119 set_socket_buffers(session->udp_socket, utp);
120 }
121
122 if (session->udp6_socket != TR_BAD_SOCKET)
123 {
124 set_socket_buffers(session->udp6_socket, utp);
125 }
126 }
127
128 /* BEP-32 has a rather nice explanation of why we need to bind to one
129 IPv6 address, if I may say so myself. */
130
rebind_ipv6(tr_session * ss,bool force)131 static void rebind_ipv6(tr_session* ss, bool force)
132 {
133 bool is_default;
134 struct tr_address const* public_addr;
135 struct sockaddr_in6 sin6;
136 unsigned char const* ipv6 = tr_globalIPv6();
137 tr_socket_t s = TR_BAD_SOCKET;
138 int rc;
139 int one = 1;
140
141 /* We currently have no way to enable or disable IPv6 after initialisation.
142 No way to fix that without some surgery to the DHT code itself. */
143 if (ipv6 == NULL || (!force && ss->udp6_socket == TR_BAD_SOCKET))
144 {
145 if (ss->udp6_bound != NULL)
146 {
147 free(ss->udp6_bound);
148 ss->udp6_bound = NULL;
149 }
150
151 return;
152 }
153
154 if (ss->udp6_bound != NULL && memcmp(ipv6, ss->udp6_bound, 16) == 0)
155 {
156 return;
157 }
158
159 s = socket(PF_INET6, SOCK_DGRAM, 0);
160
161 if (s == TR_BAD_SOCKET)
162 {
163 goto fail;
164 }
165
166 #ifdef IPV6_V6ONLY
167 /* Since we always open an IPv4 socket on the same port, this
168 shouldn't matter. But I'm superstitious. */
169 setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void const*)&one, sizeof(one));
170 #endif
171
172 memset(&sin6, 0, sizeof(sin6));
173 sin6.sin6_family = AF_INET6;
174
175 if (ipv6 != NULL)
176 {
177 memcpy(&sin6.sin6_addr, ipv6, 16);
178 }
179
180 sin6.sin6_port = htons(ss->udp_port);
181 public_addr = tr_sessionGetPublicAddress(ss, TR_AF_INET6, &is_default);
182
183 if (public_addr != NULL && !is_default)
184 {
185 sin6.sin6_addr = public_addr->addr.addr6;
186 }
187
188 rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
189
190 if (rc == -1)
191 {
192 goto fail;
193 }
194
195 if (ss->udp6_socket == TR_BAD_SOCKET)
196 {
197 ss->udp6_socket = s;
198 }
199 else
200 {
201 /* FIXME: dup2 doesn't work for sockets on Windows */
202 rc = dup2(s, ss->udp6_socket);
203
204 if (rc == -1)
205 {
206 goto fail;
207 }
208
209 tr_netCloseSocket(s);
210 }
211
212 if (ss->udp6_bound == NULL)
213 {
214 ss->udp6_bound = malloc(16);
215 }
216
217 if (ss->udp6_bound != NULL)
218 {
219 memcpy(ss->udp6_bound, ipv6, 16);
220 }
221
222 return;
223
224 fail:
225 /* Something went wrong. It's difficult to recover, so let's simply
226 set things up so that we try again next time. */
227 tr_logAddNamedError("UDP", "Couldn't rebind IPv6 socket");
228
229 if (s != TR_BAD_SOCKET)
230 {
231 tr_netCloseSocket(s);
232 }
233
234 if (ss->udp6_bound != NULL)
235 {
236 free(ss->udp6_bound);
237 ss->udp6_bound = NULL;
238 }
239 }
240
event_callback(evutil_socket_t s,short type UNUSED,void * sv)241 static void event_callback(evutil_socket_t s, short type UNUSED, void* sv)
242 {
243 TR_ASSERT(tr_isSession(sv));
244 TR_ASSERT(type == EV_READ);
245
246 int rc;
247 socklen_t fromlen;
248 unsigned char buf[4096];
249 struct sockaddr_storage from;
250 tr_session* ss = sv;
251
252 fromlen = sizeof(from);
253 rc = recvfrom(s, (void*)buf, 4096 - 1, 0, (struct sockaddr*)&from, &fromlen);
254
255 /* Since most packets we receive here are µTP, make quick inline
256 checks for the other protocols. The logic is as follows:
257 - all DHT packets start with 'd';
258 - all UDP tracker packets start with a 32-bit (!) "action", which
259 is between 0 and 3;
260 - the above cannot be µTP packets, since these start with a 4-bit
261 version number (1). */
262 if (rc > 0)
263 {
264 if (buf[0] == 'd')
265 {
266 if (tr_sessionAllowsDHT(ss))
267 {
268 buf[rc] = '\0'; /* required by the DHT code */
269 tr_dhtCallback(buf, rc, (struct sockaddr*)&from, fromlen, sv);
270 }
271 }
272 else if (rc >= 8 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] <= 3)
273 {
274 rc = tau_handle_message(ss, buf, rc);
275
276 if (rc == 0)
277 {
278 tr_logAddNamedDbg("UDP", "Couldn't parse UDP tracker packet.");
279 }
280 }
281 else
282 {
283 if (tr_sessionIsUTPEnabled(ss))
284 {
285 rc = tr_utpPacket(buf, rc, (struct sockaddr*)&from, fromlen, ss);
286
287 if (rc == 0)
288 {
289 tr_logAddNamedDbg("UDP", "Unexpected UDP packet");
290 }
291 }
292 }
293 }
294 }
295
tr_udpInit(tr_session * ss)296 void tr_udpInit(tr_session* ss)
297 {
298 TR_ASSERT(ss->udp_socket == TR_BAD_SOCKET);
299 TR_ASSERT(ss->udp6_socket == TR_BAD_SOCKET);
300
301 bool is_default;
302 struct tr_address const* public_addr;
303 struct sockaddr_in sin;
304 int rc;
305
306 ss->udp_port = tr_sessionGetPeerPort(ss);
307
308 if (ss->udp_port <= 0)
309 {
310 return;
311 }
312
313 ss->udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
314
315 if (ss->udp_socket == TR_BAD_SOCKET)
316 {
317 tr_logAddNamedError("UDP", "Couldn't create IPv4 socket");
318 goto ipv6;
319 }
320
321 memset(&sin, 0, sizeof(sin));
322 sin.sin_family = AF_INET;
323 public_addr = tr_sessionGetPublicAddress(ss, TR_AF_INET, &is_default);
324
325 if (public_addr != NULL && !is_default)
326 {
327 memcpy(&sin.sin_addr, &public_addr->addr.addr4, sizeof(struct in_addr));
328 }
329
330 sin.sin_port = htons(ss->udp_port);
331 rc = bind(ss->udp_socket, (struct sockaddr*)&sin, sizeof(sin));
332
333 if (rc == -1)
334 {
335 tr_logAddNamedError("UDP", "Couldn't bind IPv4 socket");
336 tr_netCloseSocket(ss->udp_socket);
337 ss->udp_socket = TR_BAD_SOCKET;
338 goto ipv6;
339 }
340
341 ss->udp_event = event_new(ss->event_base, ss->udp_socket, EV_READ | EV_PERSIST, event_callback, ss);
342
343 if (ss->udp_event == NULL)
344 {
345 tr_logAddNamedError("UDP", "Couldn't allocate IPv4 event");
346 }
347
348 ipv6:
349 if (tr_globalIPv6() != NULL)
350 {
351 rebind_ipv6(ss, true);
352 }
353
354 if (ss->udp6_socket != TR_BAD_SOCKET)
355 {
356 ss->udp6_event = event_new(ss->event_base, ss->udp6_socket, EV_READ | EV_PERSIST, event_callback, ss);
357
358 if (ss->udp6_event == NULL)
359 {
360 tr_logAddNamedError("UDP", "Couldn't allocate IPv6 event");
361 }
362 }
363
364 tr_udpSetSocketBuffers(ss);
365
366 if (ss->isDHTEnabled)
367 {
368 tr_dhtInit(ss);
369 }
370
371 if (ss->udp_event != NULL)
372 {
373 event_add(ss->udp_event, NULL);
374 }
375
376 if (ss->udp6_event != NULL)
377 {
378 event_add(ss->udp6_event, NULL);
379 }
380 }
381
tr_udpUninit(tr_session * ss)382 void tr_udpUninit(tr_session* ss)
383 {
384 tr_dhtUninit(ss);
385
386 if (ss->udp_socket != TR_BAD_SOCKET)
387 {
388 tr_netCloseSocket(ss->udp_socket);
389 ss->udp_socket = TR_BAD_SOCKET;
390 }
391
392 if (ss->udp_event != NULL)
393 {
394 event_free(ss->udp_event);
395 ss->udp_event = NULL;
396 }
397
398 if (ss->udp6_socket != TR_BAD_SOCKET)
399 {
400 tr_netCloseSocket(ss->udp6_socket);
401 ss->udp6_socket = TR_BAD_SOCKET;
402 }
403
404 if (ss->udp6_event != NULL)
405 {
406 event_free(ss->udp6_event);
407 ss->udp6_event = NULL;
408 }
409
410 if (ss->udp6_bound != NULL)
411 {
412 free(ss->udp6_bound);
413 ss->udp6_bound = NULL;
414 }
415 }
416