1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22 #include <assert.h>
23 #include <stdlib.h>
24
25 #include "uv.h"
26 #include "internal.h"
27 #include "handle-inl.h"
28 #include "stream-inl.h"
29 #include "req-inl.h"
30
31
32 /* A zero-size buffer for use by uv_udp_read */
33 static char uv_zero_[] = "";
uv_udp_getpeername(const uv_udp_t * handle,struct sockaddr * name,int * namelen)34 int uv_udp_getpeername(const uv_udp_t* handle,
35 struct sockaddr* name,
36 int* namelen) {
37
38 return uv__getsockpeername((const uv_handle_t*) handle,
39 getpeername,
40 name,
41 namelen,
42 0);
43 }
44
45
uv_udp_getsockname(const uv_udp_t * handle,struct sockaddr * name,int * namelen)46 int uv_udp_getsockname(const uv_udp_t* handle,
47 struct sockaddr* name,
48 int* namelen) {
49
50 return uv__getsockpeername((const uv_handle_t*) handle,
51 getsockname,
52 name,
53 namelen,
54 0);
55 }
56
57
uv__udp_set_socket(uv_loop_t * loop,uv_udp_t * handle,SOCKET socket,int family)58 static int uv__udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
59 int family) {
60 DWORD yes = 1;
61 WSAPROTOCOL_INFOW info;
62 int opt_len;
63
64 if (handle->socket != INVALID_SOCKET)
65 return UV_EBUSY;
66
67 /* Set the socket to nonblocking mode */
68 if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
69 return WSAGetLastError();
70 }
71
72 /* Make the socket non-inheritable */
73 if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
74 return GetLastError();
75 }
76
77 /* Associate it with the I/O completion port. Use uv_handle_t pointer as
78 * completion key. */
79 if (CreateIoCompletionPort((HANDLE)socket,
80 loop->iocp,
81 (ULONG_PTR)socket,
82 0) == NULL) {
83 return GetLastError();
84 }
85
86 /* All known Windows that support SetFileCompletionNotificationModes have a
87 * bug that makes it impossible to use this function in conjunction with
88 * datagram sockets. We can work around that but only if the user is using
89 * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
90 * we check whether that is the case. */
91 opt_len = (int) sizeof info;
92 if (getsockopt(
93 socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
94 SOCKET_ERROR) {
95 return GetLastError();
96 }
97
98 if (info.ProtocolChain.ChainLen == 1) {
99 if (SetFileCompletionNotificationModes(
100 (HANDLE) socket,
101 FILE_SKIP_SET_EVENT_ON_HANDLE |
102 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
103 handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
104 handle->func_wsarecv = uv__wsarecv_workaround;
105 handle->func_wsarecvfrom = uv__wsarecvfrom_workaround;
106 } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
107 return GetLastError();
108 }
109 }
110
111 handle->socket = socket;
112
113 if (family == AF_INET6) {
114 handle->flags |= UV_HANDLE_IPV6;
115 } else {
116 assert(!(handle->flags & UV_HANDLE_IPV6));
117 }
118
119 return 0;
120 }
121
122
uv__udp_init_ex(uv_loop_t * loop,uv_udp_t * handle,unsigned flags,int domain)123 int uv__udp_init_ex(uv_loop_t* loop,
124 uv_udp_t* handle,
125 unsigned flags,
126 int domain) {
127 uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
128 handle->socket = INVALID_SOCKET;
129 handle->reqs_pending = 0;
130 handle->activecnt = 0;
131 handle->func_wsarecv = WSARecv;
132 handle->func_wsarecvfrom = WSARecvFrom;
133 handle->send_queue_size = 0;
134 handle->send_queue_count = 0;
135 UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
136 handle->recv_req.data = handle;
137
138 /* If anything fails beyond this point we need to remove the handle from
139 * the handle queue, since it was added by uv__handle_init.
140 */
141
142 if (domain != AF_UNSPEC) {
143 SOCKET sock;
144 DWORD err;
145
146 sock = socket(domain, SOCK_DGRAM, 0);
147 if (sock == INVALID_SOCKET) {
148 err = WSAGetLastError();
149 uv__queue_remove(&handle->handle_queue);
150 return uv_translate_sys_error(err);
151 }
152
153 err = uv__udp_set_socket(handle->loop, handle, sock, domain);
154 if (err) {
155 closesocket(sock);
156 uv__queue_remove(&handle->handle_queue);
157 return uv_translate_sys_error(err);
158 }
159 }
160
161 return 0;
162 }
163
164
uv__udp_close(uv_loop_t * loop,uv_udp_t * handle)165 void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle) {
166 uv_udp_recv_stop(handle);
167 closesocket(handle->socket);
168 handle->socket = INVALID_SOCKET;
169
170 uv__handle_closing(handle);
171
172 if (handle->reqs_pending == 0) {
173 uv__want_endgame(loop, (uv_handle_t*) handle);
174 }
175 }
176
177
uv__udp_endgame(uv_loop_t * loop,uv_udp_t * handle)178 void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
179 if (handle->flags & UV_HANDLE_CLOSING &&
180 handle->reqs_pending == 0) {
181 assert(!(handle->flags & UV_HANDLE_CLOSED));
182 uv__handle_close(handle);
183 }
184 }
185
186
uv_udp_using_recvmmsg(const uv_udp_t * handle)187 int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
188 return 0;
189 }
190
191
uv__udp_maybe_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)192 static int uv__udp_maybe_bind(uv_udp_t* handle,
193 const struct sockaddr* addr,
194 unsigned int addrlen,
195 unsigned int flags) {
196 int r;
197 int err;
198 DWORD no = 0;
199
200 if (handle->flags & UV_HANDLE_BOUND)
201 return 0;
202
203 if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
204 /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
205 return ERROR_INVALID_PARAMETER;
206 }
207
208 if (handle->socket == INVALID_SOCKET) {
209 SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);
210 if (sock == INVALID_SOCKET) {
211 return WSAGetLastError();
212 }
213
214 err = uv__udp_set_socket(handle->loop, handle, sock, addr->sa_family);
215 if (err) {
216 closesocket(sock);
217 return err;
218 }
219 }
220
221 if (flags & UV_UDP_REUSEADDR) {
222 DWORD yes = 1;
223 /* Set SO_REUSEADDR on the socket. */
224 if (setsockopt(handle->socket,
225 SOL_SOCKET,
226 SO_REUSEADDR,
227 (char*) &yes,
228 sizeof yes) == SOCKET_ERROR) {
229 err = WSAGetLastError();
230 return err;
231 }
232 }
233
234 if (addr->sa_family == AF_INET6)
235 handle->flags |= UV_HANDLE_IPV6;
236
237 if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
238 /* On windows IPV6ONLY is on by default. If the user doesn't specify it
239 * libuv turns it off. */
240
241 /* TODO: how to handle errors? This may fail if there is no ipv4 stack
242 * available, or when run on XP/2003 which have no support for dualstack
243 * sockets. For now we're silently ignoring the error. */
244 setsockopt(handle->socket,
245 IPPROTO_IPV6,
246 IPV6_V6ONLY,
247 (char*) &no,
248 sizeof no);
249 }
250
251 r = bind(handle->socket, addr, addrlen);
252 if (r == SOCKET_ERROR) {
253 return WSAGetLastError();
254 }
255
256 handle->flags |= UV_HANDLE_BOUND;
257
258 return 0;
259 }
260
261
uv__udp_queue_recv(uv_loop_t * loop,uv_udp_t * handle)262 static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
263 uv_req_t* req;
264 uv_buf_t buf;
265 DWORD bytes, flags;
266 int result;
267
268 assert(handle->flags & UV_HANDLE_READING);
269 assert(!(handle->flags & UV_HANDLE_READ_PENDING));
270
271 req = &handle->recv_req;
272 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
273
274 handle->flags |= UV_HANDLE_ZERO_READ;
275
276 buf.base = (char*) uv_zero_;
277 buf.len = 0;
278 flags = MSG_PEEK;
279
280 result = handle->func_wsarecv(handle->socket,
281 (WSABUF*) &buf,
282 1,
283 &bytes,
284 &flags,
285 &req->u.io.overlapped,
286 NULL);
287
288 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
289 /* Process the req without IOCP. */
290 handle->flags |= UV_HANDLE_READ_PENDING;
291 req->u.io.overlapped.InternalHigh = bytes;
292 handle->reqs_pending++;
293 uv__insert_pending_req(loop, req);
294 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
295 /* The req will be processed with IOCP. */
296 handle->flags |= UV_HANDLE_READ_PENDING;
297 handle->reqs_pending++;
298 } else {
299 /* Make this req pending reporting an error. */
300 SET_REQ_ERROR(req, WSAGetLastError());
301 uv__insert_pending_req(loop, req);
302 handle->reqs_pending++;
303 }
304 }
305
306
uv__udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)307 int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
308 uv_udp_recv_cb recv_cb) {
309 uv_loop_t* loop = handle->loop;
310 int err;
311
312 if (handle->flags & UV_HANDLE_READING) {
313 return UV_EALREADY;
314 }
315
316 err = uv__udp_maybe_bind(handle,
317 (const struct sockaddr*) &uv_addr_ip4_any_,
318 sizeof(uv_addr_ip4_any_),
319 0);
320 if (err)
321 return uv_translate_sys_error(err);
322
323 handle->flags |= UV_HANDLE_READING;
324 INCREASE_ACTIVE_COUNT(loop, handle);
325
326 handle->recv_cb = recv_cb;
327 handle->alloc_cb = alloc_cb;
328
329 /* If reading was stopped and then started again, there could still be a recv
330 * request pending. */
331 if (!(handle->flags & UV_HANDLE_READ_PENDING))
332 uv__udp_queue_recv(loop, handle);
333
334 return 0;
335 }
336
337
uv__udp_recv_stop(uv_udp_t * handle)338 int uv__udp_recv_stop(uv_udp_t* handle) {
339 if (handle->flags & UV_HANDLE_READING) {
340 handle->flags &= ~UV_HANDLE_READING;
341 DECREASE_ACTIVE_COUNT(loop, handle);
342 }
343
344 return 0;
345 }
346
347
uv__send(uv_udp_send_t * req,uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen,uv_udp_send_cb cb)348 static int uv__send(uv_udp_send_t* req,
349 uv_udp_t* handle,
350 const uv_buf_t bufs[],
351 unsigned int nbufs,
352 const struct sockaddr* addr,
353 unsigned int addrlen,
354 uv_udp_send_cb cb) {
355 uv_loop_t* loop = handle->loop;
356 DWORD result, bytes;
357
358 UV_REQ_INIT(req, UV_UDP_SEND);
359 req->handle = handle;
360 req->cb = cb;
361 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
362
363 result = WSASendTo(handle->socket,
364 (WSABUF*)bufs,
365 nbufs,
366 &bytes,
367 0,
368 addr,
369 addrlen,
370 &req->u.io.overlapped,
371 NULL);
372
373 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
374 /* Request completed immediately. */
375 req->u.io.queued_bytes = 0;
376 handle->reqs_pending++;
377 handle->send_queue_size += req->u.io.queued_bytes;
378 handle->send_queue_count++;
379 REGISTER_HANDLE_REQ(loop, handle, req);
380 uv__insert_pending_req(loop, (uv_req_t*)req);
381 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
382 /* Request queued by the kernel. */
383 req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
384 handle->reqs_pending++;
385 handle->send_queue_size += req->u.io.queued_bytes;
386 handle->send_queue_count++;
387 REGISTER_HANDLE_REQ(loop, handle, req);
388 } else {
389 /* Send failed due to an error. */
390 return WSAGetLastError();
391 }
392
393 return 0;
394 }
395
396
uv__process_udp_recv_req(uv_loop_t * loop,uv_udp_t * handle,uv_req_t * req)397 void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
398 uv_req_t* req) {
399 uv_buf_t buf;
400 int partial;
401
402 assert(handle->type == UV_UDP);
403
404 handle->flags &= ~UV_HANDLE_READ_PENDING;
405
406 if (!REQ_SUCCESS(req)) {
407 DWORD err = GET_REQ_SOCK_ERROR(req);
408 if (err == WSAEMSGSIZE) {
409 /* Not a real error, it just indicates that the received packet was
410 * bigger than the receive buffer. */
411 } else if (err == WSAECONNRESET || err == WSAENETRESET) {
412 /* A previous sendto operation failed; ignore this error. If zero-reading
413 * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
414 * clear out the error queue. For nonzero reads, immediately queue a new
415 * receive. */
416 if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
417 goto done;
418 }
419 } else {
420 /* A real error occurred. Report the error to the user only if we're
421 * currently reading. */
422 if (handle->flags & UV_HANDLE_READING) {
423 uv_udp_recv_stop(handle);
424 buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
425 uv_buf_init(NULL, 0) : handle->recv_buffer;
426 handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
427 }
428 goto done;
429 }
430 }
431
432 if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
433 /* Successful read */
434 partial = !REQ_SUCCESS(req);
435 handle->recv_cb(handle,
436 req->u.io.overlapped.InternalHigh,
437 &handle->recv_buffer,
438 (const struct sockaddr*) &handle->recv_from,
439 partial ? UV_UDP_PARTIAL : 0);
440 } else if (handle->flags & UV_HANDLE_READING) {
441 DWORD bytes, err, flags;
442 struct sockaddr_storage from;
443 int from_len;
444 int count;
445
446 /* Prevent loop starvation when the data comes in as fast as
447 * (or faster than) we can read it. */
448 count = 32;
449
450 do {
451 /* Do at most `count` nonblocking receive. */
452 buf = uv_buf_init(NULL, 0);
453 handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
454 if (buf.base == NULL || buf.len == 0) {
455 handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
456 goto done;
457 }
458
459 memset(&from, 0, sizeof from);
460 from_len = sizeof from;
461
462 flags = 0;
463
464 if (WSARecvFrom(handle->socket,
465 (WSABUF*)&buf,
466 1,
467 &bytes,
468 &flags,
469 (struct sockaddr*) &from,
470 &from_len,
471 NULL,
472 NULL) != SOCKET_ERROR) {
473
474 /* Message received */
475 err = ERROR_SUCCESS;
476 handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);
477 } else {
478 err = WSAGetLastError();
479 if (err == WSAEMSGSIZE) {
480 /* Message truncated */
481 handle->recv_cb(handle,
482 bytes,
483 &buf,
484 (const struct sockaddr*) &from,
485 UV_UDP_PARTIAL);
486 } else if (err == WSAEWOULDBLOCK) {
487 /* Kernel buffer empty */
488 handle->recv_cb(handle, 0, &buf, NULL, 0);
489 } else if (err == WSAECONNRESET || err == WSAENETRESET) {
490 /* WSAECONNRESET/WSANETRESET is ignored because this just indicates
491 * that a previous sendto operation failed.
492 */
493 handle->recv_cb(handle, 0, &buf, NULL, 0);
494 } else {
495 /* Any other error that we want to report back to the user. */
496 uv_udp_recv_stop(handle);
497 handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
498 }
499 }
500 }
501 while (err == ERROR_SUCCESS &&
502 count-- > 0 &&
503 /* The recv_cb callback may decide to pause or close the handle. */
504 (handle->flags & UV_HANDLE_READING) &&
505 !(handle->flags & UV_HANDLE_READ_PENDING));
506 }
507
508 done:
509 /* Post another read if still reading and not closing. */
510 if ((handle->flags & UV_HANDLE_READING) &&
511 !(handle->flags & UV_HANDLE_READ_PENDING)) {
512 uv__udp_queue_recv(loop, handle);
513 }
514
515 DECREASE_PENDING_REQ_COUNT(handle);
516 }
517
518
uv__process_udp_send_req(uv_loop_t * loop,uv_udp_t * handle,uv_udp_send_t * req)519 void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
520 uv_udp_send_t* req) {
521 int err;
522
523 assert(handle->type == UV_UDP);
524
525 assert(handle->send_queue_size >= req->u.io.queued_bytes);
526 assert(handle->send_queue_count >= 1);
527 handle->send_queue_size -= req->u.io.queued_bytes;
528 handle->send_queue_count--;
529
530 UNREGISTER_HANDLE_REQ(loop, handle, req);
531
532 if (req->cb) {
533 err = 0;
534 if (!REQ_SUCCESS(req)) {
535 err = GET_REQ_SOCK_ERROR(req);
536 }
537 req->cb(req, uv_translate_sys_error(err));
538 }
539
540 DECREASE_PENDING_REQ_COUNT(handle);
541 }
542
543
uv__udp_set_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,uv_membership membership)544 static int uv__udp_set_membership4(uv_udp_t* handle,
545 const struct sockaddr_in* multicast_addr,
546 const char* interface_addr,
547 uv_membership membership) {
548 int err;
549 int optname;
550 struct ip_mreq mreq;
551
552 if (handle->flags & UV_HANDLE_IPV6)
553 return UV_EINVAL;
554
555 /* If the socket is unbound, bind to inaddr_any. */
556 err = uv__udp_maybe_bind(handle,
557 (const struct sockaddr*) &uv_addr_ip4_any_,
558 sizeof(uv_addr_ip4_any_),
559 UV_UDP_REUSEADDR);
560 if (err)
561 return uv_translate_sys_error(err);
562
563 memset(&mreq, 0, sizeof mreq);
564
565 if (interface_addr) {
566 err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
567 if (err)
568 return err;
569 } else {
570 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
571 }
572
573 mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
574
575 switch (membership) {
576 case UV_JOIN_GROUP:
577 optname = IP_ADD_MEMBERSHIP;
578 break;
579 case UV_LEAVE_GROUP:
580 optname = IP_DROP_MEMBERSHIP;
581 break;
582 default:
583 return UV_EINVAL;
584 }
585
586 if (setsockopt(handle->socket,
587 IPPROTO_IP,
588 optname,
589 (char*) &mreq,
590 sizeof mreq) == SOCKET_ERROR) {
591 return uv_translate_sys_error(WSAGetLastError());
592 }
593
594 return 0;
595 }
596
597
uv__udp_set_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,uv_membership membership)598 int uv__udp_set_membership6(uv_udp_t* handle,
599 const struct sockaddr_in6* multicast_addr,
600 const char* interface_addr,
601 uv_membership membership) {
602 int optname;
603 int err;
604 struct ipv6_mreq mreq;
605 struct sockaddr_in6 addr6;
606
607 if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
608 return UV_EINVAL;
609
610 err = uv__udp_maybe_bind(handle,
611 (const struct sockaddr*) &uv_addr_ip6_any_,
612 sizeof(uv_addr_ip6_any_),
613 UV_UDP_REUSEADDR);
614
615 if (err)
616 return uv_translate_sys_error(err);
617
618 memset(&mreq, 0, sizeof(mreq));
619
620 if (interface_addr) {
621 if (uv_ip6_addr(interface_addr, 0, &addr6))
622 return UV_EINVAL;
623 mreq.ipv6mr_interface = addr6.sin6_scope_id;
624 } else {
625 mreq.ipv6mr_interface = 0;
626 }
627
628 mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
629
630 switch (membership) {
631 case UV_JOIN_GROUP:
632 optname = IPV6_ADD_MEMBERSHIP;
633 break;
634 case UV_LEAVE_GROUP:
635 optname = IPV6_DROP_MEMBERSHIP;
636 break;
637 default:
638 return UV_EINVAL;
639 }
640
641 if (setsockopt(handle->socket,
642 IPPROTO_IPV6,
643 optname,
644 (char*) &mreq,
645 sizeof mreq) == SOCKET_ERROR) {
646 return uv_translate_sys_error(WSAGetLastError());
647 }
648
649 return 0;
650 }
651
652
uv__udp_set_source_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,const struct sockaddr_in * source_addr,uv_membership membership)653 static int uv__udp_set_source_membership4(uv_udp_t* handle,
654 const struct sockaddr_in* multicast_addr,
655 const char* interface_addr,
656 const struct sockaddr_in* source_addr,
657 uv_membership membership) {
658 struct ip_mreq_source mreq;
659 int optname;
660 int err;
661
662 if (handle->flags & UV_HANDLE_IPV6)
663 return UV_EINVAL;
664
665 /* If the socket is unbound, bind to inaddr_any. */
666 err = uv__udp_maybe_bind(handle,
667 (const struct sockaddr*) &uv_addr_ip4_any_,
668 sizeof(uv_addr_ip4_any_),
669 UV_UDP_REUSEADDR);
670 if (err)
671 return uv_translate_sys_error(err);
672
673 memset(&mreq, 0, sizeof(mreq));
674
675 if (interface_addr != NULL) {
676 err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
677 if (err)
678 return err;
679 } else {
680 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
681 }
682
683 mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
684 mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
685
686 if (membership == UV_JOIN_GROUP)
687 optname = IP_ADD_SOURCE_MEMBERSHIP;
688 else if (membership == UV_LEAVE_GROUP)
689 optname = IP_DROP_SOURCE_MEMBERSHIP;
690 else
691 return UV_EINVAL;
692
693 if (setsockopt(handle->socket,
694 IPPROTO_IP,
695 optname,
696 (char*) &mreq,
697 sizeof(mreq)) == SOCKET_ERROR) {
698 return uv_translate_sys_error(WSAGetLastError());
699 }
700
701 return 0;
702 }
703
704
uv__udp_set_source_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,const struct sockaddr_in6 * source_addr,uv_membership membership)705 int uv__udp_set_source_membership6(uv_udp_t* handle,
706 const struct sockaddr_in6* multicast_addr,
707 const char* interface_addr,
708 const struct sockaddr_in6* source_addr,
709 uv_membership membership) {
710 struct group_source_req mreq;
711 struct sockaddr_in6 addr6;
712 int optname;
713 int err;
714
715 STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr));
716 STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr));
717
718 if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
719 return UV_EINVAL;
720
721 err = uv__udp_maybe_bind(handle,
722 (const struct sockaddr*) &uv_addr_ip6_any_,
723 sizeof(uv_addr_ip6_any_),
724 UV_UDP_REUSEADDR);
725
726 if (err)
727 return uv_translate_sys_error(err);
728
729 memset(&mreq, 0, sizeof(mreq));
730
731 if (interface_addr != NULL) {
732 err = uv_ip6_addr(interface_addr, 0, &addr6);
733 if (err)
734 return err;
735 mreq.gsr_interface = addr6.sin6_scope_id;
736 } else {
737 mreq.gsr_interface = 0;
738 }
739
740 memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr));
741 memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr));
742
743 if (membership == UV_JOIN_GROUP)
744 optname = MCAST_JOIN_SOURCE_GROUP;
745 else if (membership == UV_LEAVE_GROUP)
746 optname = MCAST_LEAVE_SOURCE_GROUP;
747 else
748 return UV_EINVAL;
749
750 if (setsockopt(handle->socket,
751 IPPROTO_IPV6,
752 optname,
753 (char*) &mreq,
754 sizeof(mreq)) == SOCKET_ERROR) {
755 return uv_translate_sys_error(WSAGetLastError());
756 }
757
758 return 0;
759 }
760
761
uv_udp_set_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,uv_membership membership)762 int uv_udp_set_membership(uv_udp_t* handle,
763 const char* multicast_addr,
764 const char* interface_addr,
765 uv_membership membership) {
766 struct sockaddr_in addr4;
767 struct sockaddr_in6 addr6;
768
769 if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)
770 return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
771 else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)
772 return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
773 else
774 return UV_EINVAL;
775 }
776
777
uv_udp_set_source_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,const char * source_addr,uv_membership membership)778 int uv_udp_set_source_membership(uv_udp_t* handle,
779 const char* multicast_addr,
780 const char* interface_addr,
781 const char* source_addr,
782 uv_membership membership) {
783 int err;
784 struct sockaddr_storage mcast_addr;
785 struct sockaddr_in* mcast_addr4;
786 struct sockaddr_in6* mcast_addr6;
787 struct sockaddr_storage src_addr;
788 struct sockaddr_in* src_addr4;
789 struct sockaddr_in6* src_addr6;
790
791 mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
792 mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
793 src_addr4 = (struct sockaddr_in*)&src_addr;
794 src_addr6 = (struct sockaddr_in6*)&src_addr;
795
796 err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
797 if (err) {
798 err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
799 if (err)
800 return err;
801 err = uv_ip6_addr(source_addr, 0, src_addr6);
802 if (err)
803 return err;
804 return uv__udp_set_source_membership6(handle,
805 mcast_addr6,
806 interface_addr,
807 src_addr6,
808 membership);
809 }
810
811 err = uv_ip4_addr(source_addr, 0, src_addr4);
812 if (err)
813 return err;
814 return uv__udp_set_source_membership4(handle,
815 mcast_addr4,
816 interface_addr,
817 src_addr4,
818 membership);
819 }
820
821
uv_udp_set_multicast_interface(uv_udp_t * handle,const char * interface_addr)822 int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
823 struct sockaddr_storage addr_st;
824 struct sockaddr_in* addr4;
825 struct sockaddr_in6* addr6;
826
827 addr4 = (struct sockaddr_in*) &addr_st;
828 addr6 = (struct sockaddr_in6*) &addr_st;
829
830 if (!interface_addr) {
831 memset(&addr_st, 0, sizeof addr_st);
832 if (handle->flags & UV_HANDLE_IPV6) {
833 addr_st.ss_family = AF_INET6;
834 addr6->sin6_scope_id = 0;
835 } else {
836 addr_st.ss_family = AF_INET;
837 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
838 }
839 } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
840 /* nothing, address was parsed */
841 } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
842 /* nothing, address was parsed */
843 } else {
844 return UV_EINVAL;
845 }
846
847 if (handle->socket == INVALID_SOCKET)
848 return UV_EBADF;
849
850 if (addr_st.ss_family == AF_INET) {
851 if (setsockopt(handle->socket,
852 IPPROTO_IP,
853 IP_MULTICAST_IF,
854 (char*) &addr4->sin_addr,
855 sizeof(addr4->sin_addr)) == SOCKET_ERROR) {
856 return uv_translate_sys_error(WSAGetLastError());
857 }
858 } else if (addr_st.ss_family == AF_INET6) {
859 if (setsockopt(handle->socket,
860 IPPROTO_IPV6,
861 IPV6_MULTICAST_IF,
862 (char*) &addr6->sin6_scope_id,
863 sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {
864 return uv_translate_sys_error(WSAGetLastError());
865 }
866 } else {
867 assert(0 && "unexpected address family");
868 abort();
869 }
870
871 return 0;
872 }
873
874
uv_udp_set_broadcast(uv_udp_t * handle,int value)875 int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
876 BOOL optval = (BOOL) value;
877
878 if (handle->socket == INVALID_SOCKET)
879 return UV_EBADF;
880
881 if (setsockopt(handle->socket,
882 SOL_SOCKET,
883 SO_BROADCAST,
884 (char*) &optval,
885 sizeof optval)) {
886 return uv_translate_sys_error(WSAGetLastError());
887 }
888
889 return 0;
890 }
891
892
uv__udp_is_bound(uv_udp_t * handle)893 int uv__udp_is_bound(uv_udp_t* handle) {
894 struct sockaddr_storage addr;
895 int addrlen;
896
897 addrlen = sizeof(addr);
898 if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
899 return 0;
900
901 return addrlen > 0;
902 }
903
904
uv_udp_open(uv_udp_t * handle,uv_os_sock_t sock)905 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
906 WSAPROTOCOL_INFOW protocol_info;
907 int opt_len;
908 int err;
909
910 /* Detect the address family of the socket. */
911 opt_len = (int) sizeof protocol_info;
912 if (getsockopt(sock,
913 SOL_SOCKET,
914 SO_PROTOCOL_INFOW,
915 (char*) &protocol_info,
916 &opt_len) == SOCKET_ERROR) {
917 return uv_translate_sys_error(GetLastError());
918 }
919
920 err = uv__udp_set_socket(handle->loop,
921 handle,
922 sock,
923 protocol_info.iAddressFamily);
924 if (err)
925 return uv_translate_sys_error(err);
926
927 if (uv__udp_is_bound(handle))
928 handle->flags |= UV_HANDLE_BOUND;
929
930 if (uv__udp_is_connected(handle))
931 handle->flags |= UV_HANDLE_UDP_CONNECTED;
932
933 return 0;
934 }
935
936
937 #define SOCKOPT_SETTER(name, option4, option6, validate) \
938 int uv_udp_set_##name(uv_udp_t* handle, int value) { \
939 DWORD optval = (DWORD) value; \
940 \
941 if (!(validate(value))) { \
942 return UV_EINVAL; \
943 } \
944 \
945 if (handle->socket == INVALID_SOCKET) \
946 return UV_EBADF; \
947 \
948 if (!(handle->flags & UV_HANDLE_IPV6)) { \
949 /* Set IPv4 socket option */ \
950 if (setsockopt(handle->socket, \
951 IPPROTO_IP, \
952 option4, \
953 (char*) &optval, \
954 sizeof optval)) { \
955 return uv_translate_sys_error(WSAGetLastError()); \
956 } \
957 } else { \
958 /* Set IPv6 socket option */ \
959 if (setsockopt(handle->socket, \
960 IPPROTO_IPV6, \
961 option6, \
962 (char*) &optval, \
963 sizeof optval)) { \
964 return uv_translate_sys_error(WSAGetLastError()); \
965 } \
966 } \
967 return 0; \
968 }
969
970 #define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)
971 #define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)
972 #define VALIDATE_MULTICAST_LOOP(value) (1)
973
SOCKOPT_SETTER(ttl,IP_TTL,IPV6_HOPLIMIT,VALIDATE_TTL)974 SOCKOPT_SETTER(ttl,
975 IP_TTL,
976 IPV6_HOPLIMIT,
977 VALIDATE_TTL)
978 SOCKOPT_SETTER(multicast_ttl,
979 IP_MULTICAST_TTL,
980 IPV6_MULTICAST_HOPS,
981 VALIDATE_MULTICAST_TTL)
982 SOCKOPT_SETTER(multicast_loop,
983 IP_MULTICAST_LOOP,
984 IPV6_MULTICAST_LOOP,
985 VALIDATE_MULTICAST_LOOP)
986
987 #undef SOCKOPT_SETTER
988 #undef VALIDATE_TTL
989 #undef VALIDATE_MULTICAST_TTL
990 #undef VALIDATE_MULTICAST_LOOP
991
992
993 /* This function is an egress point, i.e. it returns libuv errors rather than
994 * system errors.
995 */
996 int uv__udp_bind(uv_udp_t* handle,
997 const struct sockaddr* addr,
998 unsigned int addrlen,
999 unsigned int flags) {
1000 int err;
1001
1002 err = uv__udp_maybe_bind(handle, addr, addrlen, flags);
1003 if (err)
1004 return uv_translate_sys_error(err);
1005
1006 return 0;
1007 }
1008
1009
uv__udp_connect(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen)1010 int uv__udp_connect(uv_udp_t* handle,
1011 const struct sockaddr* addr,
1012 unsigned int addrlen) {
1013 const struct sockaddr* bind_addr;
1014 int err;
1015
1016 if (!(handle->flags & UV_HANDLE_BOUND)) {
1017 if (addrlen == sizeof(uv_addr_ip4_any_))
1018 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1019 else if (addrlen == sizeof(uv_addr_ip6_any_))
1020 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1021 else
1022 return UV_EINVAL;
1023
1024 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1025 if (err)
1026 return uv_translate_sys_error(err);
1027 }
1028
1029 err = connect(handle->socket, addr, addrlen);
1030 if (err)
1031 return uv_translate_sys_error(WSAGetLastError());
1032
1033 handle->flags |= UV_HANDLE_UDP_CONNECTED;
1034
1035 return 0;
1036 }
1037
1038
uv__udp_disconnect(uv_udp_t * handle)1039 int uv__udp_disconnect(uv_udp_t* handle) {
1040 int err;
1041 struct sockaddr_storage addr;
1042
1043 memset(&addr, 0, sizeof(addr));
1044
1045 err = connect(handle->socket, (struct sockaddr*) &addr, sizeof(addr));
1046 if (err)
1047 return uv_translate_sys_error(WSAGetLastError());
1048
1049 handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
1050 return 0;
1051 }
1052
1053
1054 /* This function is an egress point, i.e. it returns libuv errors rather than
1055 * system errors.
1056 */
uv__udp_send(uv_udp_send_t * req,uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen,uv_udp_send_cb send_cb)1057 int uv__udp_send(uv_udp_send_t* req,
1058 uv_udp_t* handle,
1059 const uv_buf_t bufs[],
1060 unsigned int nbufs,
1061 const struct sockaddr* addr,
1062 unsigned int addrlen,
1063 uv_udp_send_cb send_cb) {
1064 const struct sockaddr* bind_addr;
1065 int err;
1066
1067 if (!(handle->flags & UV_HANDLE_BOUND)) {
1068 if (addrlen == sizeof(uv_addr_ip4_any_))
1069 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1070 else if (addrlen == sizeof(uv_addr_ip6_any_))
1071 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1072 else
1073 return UV_EINVAL;
1074
1075 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1076 if (err)
1077 return uv_translate_sys_error(err);
1078 }
1079
1080 err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
1081 if (err)
1082 return uv_translate_sys_error(err);
1083
1084 return 0;
1085 }
1086
1087
uv__udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen)1088 int uv__udp_try_send(uv_udp_t* handle,
1089 const uv_buf_t bufs[],
1090 unsigned int nbufs,
1091 const struct sockaddr* addr,
1092 unsigned int addrlen) {
1093 DWORD bytes;
1094 const struct sockaddr* bind_addr;
1095 struct sockaddr_storage converted;
1096 int err;
1097
1098 assert(nbufs > 0);
1099
1100 if (addr != NULL) {
1101 err = uv__convert_to_localhost_if_unspecified(addr, &converted);
1102 if (err)
1103 return err;
1104 addr = (const struct sockaddr*) &converted;
1105 }
1106
1107 /* Already sending a message.*/
1108 if (handle->send_queue_count != 0)
1109 return UV_EAGAIN;
1110
1111 if (!(handle->flags & UV_HANDLE_BOUND)) {
1112 if (addrlen == sizeof(uv_addr_ip4_any_))
1113 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1114 else if (addrlen == sizeof(uv_addr_ip6_any_))
1115 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1116 else
1117 return UV_EINVAL;
1118 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1119 if (err)
1120 return uv_translate_sys_error(err);
1121 }
1122
1123 err = WSASendTo(handle->socket,
1124 (WSABUF*)bufs,
1125 nbufs,
1126 &bytes,
1127 0,
1128 addr,
1129 addrlen,
1130 NULL,
1131 NULL);
1132
1133 if (err)
1134 return uv_translate_sys_error(WSAGetLastError());
1135
1136 return bytes;
1137 }
1138