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 /* There is no SO_REUSEPORT on Windows, Windows only knows SO_REUSEADDR.
204 * so we just return an error directly when UV_UDP_REUSEPORT is requested
205 * for binding the socket. */
206 if (flags & UV_UDP_REUSEPORT)
207 return ERROR_NOT_SUPPORTED;
208
209 if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
210 /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
211 return ERROR_INVALID_PARAMETER;
212 }
213
214 if (handle->socket == INVALID_SOCKET) {
215 SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);
216 if (sock == INVALID_SOCKET) {
217 return WSAGetLastError();
218 }
219
220 err = uv__udp_set_socket(handle->loop, handle, sock, addr->sa_family);
221 if (err) {
222 closesocket(sock);
223 return err;
224 }
225 }
226
227 if (flags & UV_UDP_REUSEADDR) {
228 DWORD yes = 1;
229 /* Set SO_REUSEADDR on the socket. */
230 if (setsockopt(handle->socket,
231 SOL_SOCKET,
232 SO_REUSEADDR,
233 (char*) &yes,
234 sizeof yes) == SOCKET_ERROR) {
235 err = WSAGetLastError();
236 return err;
237 }
238 }
239
240 if (addr->sa_family == AF_INET6)
241 handle->flags |= UV_HANDLE_IPV6;
242
243 if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
244 /* On windows IPV6ONLY is on by default. If the user doesn't specify it
245 * libuv turns it off. */
246
247 /* TODO: how to handle errors? This may fail if there is no ipv4 stack
248 * available, or when run on XP/2003 which have no support for dualstack
249 * sockets. For now we're silently ignoring the error. */
250 setsockopt(handle->socket,
251 IPPROTO_IPV6,
252 IPV6_V6ONLY,
253 (char*) &no,
254 sizeof no);
255 }
256
257 r = bind(handle->socket, addr, addrlen);
258 if (r == SOCKET_ERROR) {
259 return WSAGetLastError();
260 }
261
262 handle->flags |= UV_HANDLE_BOUND;
263
264 return 0;
265 }
266
267
uv__udp_queue_recv(uv_loop_t * loop,uv_udp_t * handle)268 static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
269 uv_req_t* req;
270 uv_buf_t buf;
271 DWORD bytes, flags;
272 int result;
273
274 assert(handle->flags & UV_HANDLE_READING);
275 assert(!(handle->flags & UV_HANDLE_READ_PENDING));
276
277 req = &handle->recv_req;
278 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
279
280 handle->flags |= UV_HANDLE_ZERO_READ;
281
282 buf.base = (char*) uv_zero_;
283 buf.len = 0;
284 flags = MSG_PEEK;
285
286 result = handle->func_wsarecv(handle->socket,
287 (WSABUF*) &buf,
288 1,
289 &bytes,
290 &flags,
291 &req->u.io.overlapped,
292 NULL);
293
294 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
295 /* Process the req without IOCP. */
296 handle->flags |= UV_HANDLE_READ_PENDING;
297 req->u.io.overlapped.InternalHigh = bytes;
298 handle->reqs_pending++;
299 uv__insert_pending_req(loop, req);
300 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
301 /* The req will be processed with IOCP. */
302 handle->flags |= UV_HANDLE_READ_PENDING;
303 handle->reqs_pending++;
304 } else {
305 /* Make this req pending reporting an error. */
306 SET_REQ_ERROR(req, WSAGetLastError());
307 uv__insert_pending_req(loop, req);
308 handle->reqs_pending++;
309 }
310 }
311
312
uv__udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)313 int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
314 uv_udp_recv_cb recv_cb) {
315 uv_loop_t* loop = handle->loop;
316 int err;
317
318 if (handle->flags & UV_HANDLE_READING) {
319 return UV_EALREADY;
320 }
321
322 err = uv__udp_maybe_bind(handle,
323 (const struct sockaddr*) &uv_addr_ip4_any_,
324 sizeof(uv_addr_ip4_any_),
325 0);
326 if (err)
327 return uv_translate_sys_error(err);
328
329 handle->flags |= UV_HANDLE_READING;
330 INCREASE_ACTIVE_COUNT(loop, handle);
331
332 handle->recv_cb = recv_cb;
333 handle->alloc_cb = alloc_cb;
334
335 /* If reading was stopped and then started again, there could still be a recv
336 * request pending. */
337 if (!(handle->flags & UV_HANDLE_READ_PENDING))
338 uv__udp_queue_recv(loop, handle);
339
340 return 0;
341 }
342
343
uv__udp_recv_stop(uv_udp_t * handle)344 int uv__udp_recv_stop(uv_udp_t* handle) {
345 if (handle->flags & UV_HANDLE_READING) {
346 handle->flags &= ~UV_HANDLE_READING;
347 DECREASE_ACTIVE_COUNT(loop, handle);
348 }
349
350 return 0;
351 }
352
353
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)354 static int uv__send(uv_udp_send_t* req,
355 uv_udp_t* handle,
356 const uv_buf_t bufs[],
357 unsigned int nbufs,
358 const struct sockaddr* addr,
359 unsigned int addrlen,
360 uv_udp_send_cb cb) {
361 uv_loop_t* loop = handle->loop;
362 DWORD result, bytes;
363
364 UV_REQ_INIT(req, UV_UDP_SEND);
365 req->handle = handle;
366 req->cb = cb;
367 memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
368
369 result = WSASendTo(handle->socket,
370 (WSABUF*)bufs,
371 nbufs,
372 &bytes,
373 0,
374 addr,
375 addrlen,
376 &req->u.io.overlapped,
377 NULL);
378
379 if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
380 /* Request completed immediately. */
381 req->u.io.queued_bytes = 0;
382 handle->reqs_pending++;
383 handle->send_queue_size += req->u.io.queued_bytes;
384 handle->send_queue_count++;
385 REGISTER_HANDLE_REQ(loop, handle);
386 uv__insert_pending_req(loop, (uv_req_t*)req);
387 } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
388 /* Request queued by the kernel. */
389 req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
390 handle->reqs_pending++;
391 handle->send_queue_size += req->u.io.queued_bytes;
392 handle->send_queue_count++;
393 REGISTER_HANDLE_REQ(loop, handle);
394 } else {
395 /* Send failed due to an error. */
396 return WSAGetLastError();
397 }
398
399 return 0;
400 }
401
402
uv__process_udp_recv_req(uv_loop_t * loop,uv_udp_t * handle,uv_req_t * req)403 void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
404 uv_req_t* req) {
405 uv_buf_t buf;
406 int partial;
407
408 assert(handle->type == UV_UDP);
409
410 handle->flags &= ~UV_HANDLE_READ_PENDING;
411
412 if (!REQ_SUCCESS(req)) {
413 DWORD err = GET_REQ_SOCK_ERROR(req);
414 if (err == WSAEMSGSIZE) {
415 /* Not a real error, it just indicates that the received packet was
416 * bigger than the receive buffer. */
417 } else if (err == WSAECONNRESET || err == WSAENETRESET) {
418 /* A previous sendto operation failed; ignore this error. If zero-reading
419 * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
420 * clear out the error queue. For nonzero reads, immediately queue a new
421 * receive. */
422 if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
423 goto done;
424 }
425 } else {
426 /* A real error occurred. Report the error to the user only if we're
427 * currently reading. */
428 if (handle->flags & UV_HANDLE_READING) {
429 uv_udp_recv_stop(handle);
430 buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
431 uv_buf_init(NULL, 0) : handle->recv_buffer;
432 handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
433 }
434 goto done;
435 }
436 }
437
438 if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
439 /* Successful read */
440 partial = !REQ_SUCCESS(req);
441 handle->recv_cb(handle,
442 req->u.io.overlapped.InternalHigh,
443 &handle->recv_buffer,
444 (const struct sockaddr*) &handle->recv_from,
445 partial ? UV_UDP_PARTIAL : 0);
446 } else if (handle->flags & UV_HANDLE_READING) {
447 DWORD bytes, err, flags;
448 struct sockaddr_storage from;
449 int from_len;
450 int count;
451
452 /* Prevent loop starvation when the data comes in as fast as
453 * (or faster than) we can read it. */
454 count = 32;
455
456 do {
457 /* Do at most `count` nonblocking receive. */
458 buf = uv_buf_init(NULL, 0);
459 handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
460 if (buf.base == NULL || buf.len == 0) {
461 handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
462 goto done;
463 }
464
465 memset(&from, 0, sizeof from);
466 from_len = sizeof from;
467
468 flags = 0;
469
470 if (WSARecvFrom(handle->socket,
471 (WSABUF*)&buf,
472 1,
473 &bytes,
474 &flags,
475 (struct sockaddr*) &from,
476 &from_len,
477 NULL,
478 NULL) != SOCKET_ERROR) {
479
480 /* Message received */
481 err = ERROR_SUCCESS;
482 handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);
483 } else {
484 err = WSAGetLastError();
485 if (err == WSAEMSGSIZE) {
486 /* Message truncated */
487 handle->recv_cb(handle,
488 bytes,
489 &buf,
490 (const struct sockaddr*) &from,
491 UV_UDP_PARTIAL);
492 } else if (err == WSAEWOULDBLOCK) {
493 /* Kernel buffer empty */
494 handle->recv_cb(handle, 0, &buf, NULL, 0);
495 } else if (err == WSAECONNRESET || err == WSAENETRESET) {
496 /* WSAECONNRESET/WSANETRESET is ignored because this just indicates
497 * that a previous sendto operation failed.
498 */
499 handle->recv_cb(handle, 0, &buf, NULL, 0);
500 } else {
501 /* Any other error that we want to report back to the user. */
502 uv_udp_recv_stop(handle);
503 handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
504 }
505 }
506 }
507 while (err == ERROR_SUCCESS &&
508 count-- > 0 &&
509 /* The recv_cb callback may decide to pause or close the handle. */
510 (handle->flags & UV_HANDLE_READING) &&
511 !(handle->flags & UV_HANDLE_READ_PENDING));
512 }
513
514 done:
515 /* Post another read if still reading and not closing. */
516 if ((handle->flags & UV_HANDLE_READING) &&
517 !(handle->flags & UV_HANDLE_READ_PENDING)) {
518 uv__udp_queue_recv(loop, handle);
519 }
520
521 DECREASE_PENDING_REQ_COUNT(handle);
522 }
523
524
uv__process_udp_send_req(uv_loop_t * loop,uv_udp_t * handle,uv_udp_send_t * req)525 void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
526 uv_udp_send_t* req) {
527 int err;
528
529 assert(handle->type == UV_UDP);
530
531 assert(handle->send_queue_size >= req->u.io.queued_bytes);
532 assert(handle->send_queue_count >= 1);
533 handle->send_queue_size -= req->u.io.queued_bytes;
534 handle->send_queue_count--;
535
536 UNREGISTER_HANDLE_REQ(loop, handle);
537
538 if (req->cb) {
539 err = 0;
540 if (!REQ_SUCCESS(req)) {
541 err = GET_REQ_SOCK_ERROR(req);
542 }
543 req->cb(req, uv_translate_sys_error(err));
544 }
545
546 DECREASE_PENDING_REQ_COUNT(handle);
547 }
548
549
uv__udp_set_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,uv_membership membership)550 static int uv__udp_set_membership4(uv_udp_t* handle,
551 const struct sockaddr_in* multicast_addr,
552 const char* interface_addr,
553 uv_membership membership) {
554 int err;
555 int optname;
556 struct ip_mreq mreq;
557
558 if (handle->flags & UV_HANDLE_IPV6)
559 return UV_EINVAL;
560
561 /* If the socket is unbound, bind to inaddr_any. */
562 err = uv__udp_maybe_bind(handle,
563 (const struct sockaddr*) &uv_addr_ip4_any_,
564 sizeof(uv_addr_ip4_any_),
565 UV_UDP_REUSEADDR);
566 if (err)
567 return uv_translate_sys_error(err);
568
569 memset(&mreq, 0, sizeof mreq);
570
571 if (interface_addr) {
572 err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
573 if (err)
574 return err;
575 } else {
576 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
577 }
578
579 mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
580
581 switch (membership) {
582 case UV_JOIN_GROUP:
583 optname = IP_ADD_MEMBERSHIP;
584 break;
585 case UV_LEAVE_GROUP:
586 optname = IP_DROP_MEMBERSHIP;
587 break;
588 default:
589 return UV_EINVAL;
590 }
591
592 if (setsockopt(handle->socket,
593 IPPROTO_IP,
594 optname,
595 (char*) &mreq,
596 sizeof mreq) == SOCKET_ERROR) {
597 return uv_translate_sys_error(WSAGetLastError());
598 }
599
600 return 0;
601 }
602
603
uv__udp_set_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,uv_membership membership)604 int uv__udp_set_membership6(uv_udp_t* handle,
605 const struct sockaddr_in6* multicast_addr,
606 const char* interface_addr,
607 uv_membership membership) {
608 int optname;
609 int err;
610 struct ipv6_mreq mreq;
611 struct sockaddr_in6 addr6;
612
613 if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
614 return UV_EINVAL;
615
616 err = uv__udp_maybe_bind(handle,
617 (const struct sockaddr*) &uv_addr_ip6_any_,
618 sizeof(uv_addr_ip6_any_),
619 UV_UDP_REUSEADDR);
620
621 if (err)
622 return uv_translate_sys_error(err);
623
624 memset(&mreq, 0, sizeof(mreq));
625
626 if (interface_addr) {
627 if (uv_ip6_addr(interface_addr, 0, &addr6))
628 return UV_EINVAL;
629 mreq.ipv6mr_interface = addr6.sin6_scope_id;
630 } else {
631 mreq.ipv6mr_interface = 0;
632 }
633
634 mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
635
636 switch (membership) {
637 case UV_JOIN_GROUP:
638 optname = IPV6_ADD_MEMBERSHIP;
639 break;
640 case UV_LEAVE_GROUP:
641 optname = IPV6_DROP_MEMBERSHIP;
642 break;
643 default:
644 return UV_EINVAL;
645 }
646
647 if (setsockopt(handle->socket,
648 IPPROTO_IPV6,
649 optname,
650 (char*) &mreq,
651 sizeof mreq) == SOCKET_ERROR) {
652 return uv_translate_sys_error(WSAGetLastError());
653 }
654
655 return 0;
656 }
657
658
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)659 static int uv__udp_set_source_membership4(uv_udp_t* handle,
660 const struct sockaddr_in* multicast_addr,
661 const char* interface_addr,
662 const struct sockaddr_in* source_addr,
663 uv_membership membership) {
664 struct ip_mreq_source mreq;
665 int optname;
666 int err;
667
668 if (handle->flags & UV_HANDLE_IPV6)
669 return UV_EINVAL;
670
671 /* If the socket is unbound, bind to inaddr_any. */
672 err = uv__udp_maybe_bind(handle,
673 (const struct sockaddr*) &uv_addr_ip4_any_,
674 sizeof(uv_addr_ip4_any_),
675 UV_UDP_REUSEADDR);
676 if (err)
677 return uv_translate_sys_error(err);
678
679 memset(&mreq, 0, sizeof(mreq));
680
681 if (interface_addr != NULL) {
682 err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
683 if (err)
684 return err;
685 } else {
686 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
687 }
688
689 mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
690 mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
691
692 if (membership == UV_JOIN_GROUP)
693 optname = IP_ADD_SOURCE_MEMBERSHIP;
694 else if (membership == UV_LEAVE_GROUP)
695 optname = IP_DROP_SOURCE_MEMBERSHIP;
696 else
697 return UV_EINVAL;
698
699 if (setsockopt(handle->socket,
700 IPPROTO_IP,
701 optname,
702 (char*) &mreq,
703 sizeof(mreq)) == SOCKET_ERROR) {
704 return uv_translate_sys_error(WSAGetLastError());
705 }
706
707 return 0;
708 }
709
710
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)711 int uv__udp_set_source_membership6(uv_udp_t* handle,
712 const struct sockaddr_in6* multicast_addr,
713 const char* interface_addr,
714 const struct sockaddr_in6* source_addr,
715 uv_membership membership) {
716 struct group_source_req mreq;
717 struct sockaddr_in6 addr6;
718 int optname;
719 int err;
720
721 STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr));
722 STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr));
723
724 if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
725 return UV_EINVAL;
726
727 err = uv__udp_maybe_bind(handle,
728 (const struct sockaddr*) &uv_addr_ip6_any_,
729 sizeof(uv_addr_ip6_any_),
730 UV_UDP_REUSEADDR);
731
732 if (err)
733 return uv_translate_sys_error(err);
734
735 memset(&mreq, 0, sizeof(mreq));
736
737 if (interface_addr != NULL) {
738 err = uv_ip6_addr(interface_addr, 0, &addr6);
739 if (err)
740 return err;
741 mreq.gsr_interface = addr6.sin6_scope_id;
742 } else {
743 mreq.gsr_interface = 0;
744 }
745
746 memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr));
747 memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr));
748
749 if (membership == UV_JOIN_GROUP)
750 optname = MCAST_JOIN_SOURCE_GROUP;
751 else if (membership == UV_LEAVE_GROUP)
752 optname = MCAST_LEAVE_SOURCE_GROUP;
753 else
754 return UV_EINVAL;
755
756 if (setsockopt(handle->socket,
757 IPPROTO_IPV6,
758 optname,
759 (char*) &mreq,
760 sizeof(mreq)) == SOCKET_ERROR) {
761 return uv_translate_sys_error(WSAGetLastError());
762 }
763
764 return 0;
765 }
766
767
uv_udp_set_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,uv_membership membership)768 int uv_udp_set_membership(uv_udp_t* handle,
769 const char* multicast_addr,
770 const char* interface_addr,
771 uv_membership membership) {
772 struct sockaddr_in addr4;
773 struct sockaddr_in6 addr6;
774
775 if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)
776 return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
777 else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)
778 return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
779 else
780 return UV_EINVAL;
781 }
782
783
uv_udp_set_source_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,const char * source_addr,uv_membership membership)784 int uv_udp_set_source_membership(uv_udp_t* handle,
785 const char* multicast_addr,
786 const char* interface_addr,
787 const char* source_addr,
788 uv_membership membership) {
789 int err;
790 struct sockaddr_storage mcast_addr;
791 struct sockaddr_in* mcast_addr4;
792 struct sockaddr_in6* mcast_addr6;
793 struct sockaddr_storage src_addr;
794 struct sockaddr_in* src_addr4;
795 struct sockaddr_in6* src_addr6;
796
797 mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
798 mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
799 src_addr4 = (struct sockaddr_in*)&src_addr;
800 src_addr6 = (struct sockaddr_in6*)&src_addr;
801
802 err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
803 if (err) {
804 err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
805 if (err)
806 return err;
807 err = uv_ip6_addr(source_addr, 0, src_addr6);
808 if (err)
809 return err;
810 return uv__udp_set_source_membership6(handle,
811 mcast_addr6,
812 interface_addr,
813 src_addr6,
814 membership);
815 }
816
817 err = uv_ip4_addr(source_addr, 0, src_addr4);
818 if (err)
819 return err;
820 return uv__udp_set_source_membership4(handle,
821 mcast_addr4,
822 interface_addr,
823 src_addr4,
824 membership);
825 }
826
827
uv_udp_set_multicast_interface(uv_udp_t * handle,const char * interface_addr)828 int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
829 struct sockaddr_storage addr_st;
830 struct sockaddr_in* addr4;
831 struct sockaddr_in6* addr6;
832
833 addr4 = (struct sockaddr_in*) &addr_st;
834 addr6 = (struct sockaddr_in6*) &addr_st;
835
836 if (!interface_addr) {
837 memset(&addr_st, 0, sizeof addr_st);
838 if (handle->flags & UV_HANDLE_IPV6) {
839 addr_st.ss_family = AF_INET6;
840 addr6->sin6_scope_id = 0;
841 } else {
842 addr_st.ss_family = AF_INET;
843 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
844 }
845 } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
846 /* nothing, address was parsed */
847 } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
848 /* nothing, address was parsed */
849 } else {
850 return UV_EINVAL;
851 }
852
853 if (handle->socket == INVALID_SOCKET)
854 return UV_EBADF;
855
856 if (addr_st.ss_family == AF_INET) {
857 if (setsockopt(handle->socket,
858 IPPROTO_IP,
859 IP_MULTICAST_IF,
860 (char*) &addr4->sin_addr,
861 sizeof(addr4->sin_addr)) == SOCKET_ERROR) {
862 return uv_translate_sys_error(WSAGetLastError());
863 }
864 } else if (addr_st.ss_family == AF_INET6) {
865 if (setsockopt(handle->socket,
866 IPPROTO_IPV6,
867 IPV6_MULTICAST_IF,
868 (char*) &addr6->sin6_scope_id,
869 sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {
870 return uv_translate_sys_error(WSAGetLastError());
871 }
872 } else {
873 assert(0 && "unexpected address family");
874 abort();
875 }
876
877 return 0;
878 }
879
880
uv_udp_set_broadcast(uv_udp_t * handle,int value)881 int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
882 BOOL optval = (BOOL) value;
883
884 if (handle->socket == INVALID_SOCKET)
885 return UV_EBADF;
886
887 if (setsockopt(handle->socket,
888 SOL_SOCKET,
889 SO_BROADCAST,
890 (char*) &optval,
891 sizeof optval)) {
892 return uv_translate_sys_error(WSAGetLastError());
893 }
894
895 return 0;
896 }
897
898
uv__udp_is_bound(uv_udp_t * handle)899 int uv__udp_is_bound(uv_udp_t* handle) {
900 struct sockaddr_storage addr;
901 int addrlen;
902
903 addrlen = sizeof(addr);
904 if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
905 return 0;
906
907 return addrlen > 0;
908 }
909
910
uv_udp_open(uv_udp_t * handle,uv_os_sock_t sock)911 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
912 WSAPROTOCOL_INFOW protocol_info;
913 int opt_len;
914 int err;
915
916 /* Detect the address family of the socket. */
917 opt_len = (int) sizeof protocol_info;
918 if (getsockopt(sock,
919 SOL_SOCKET,
920 SO_PROTOCOL_INFOW,
921 (char*) &protocol_info,
922 &opt_len) == SOCKET_ERROR) {
923 return uv_translate_sys_error(GetLastError());
924 }
925
926 err = uv__udp_set_socket(handle->loop,
927 handle,
928 sock,
929 protocol_info.iAddressFamily);
930 if (err)
931 return uv_translate_sys_error(err);
932
933 if (uv__udp_is_bound(handle))
934 handle->flags |= UV_HANDLE_BOUND;
935
936 if (uv__udp_is_connected(handle))
937 handle->flags |= UV_HANDLE_UDP_CONNECTED;
938
939 return 0;
940 }
941
942
943 #define SOCKOPT_SETTER(name, option4, option6, validate) \
944 int uv_udp_set_##name(uv_udp_t* handle, int value) { \
945 DWORD optval = (DWORD) value; \
946 \
947 if (!(validate(value))) { \
948 return UV_EINVAL; \
949 } \
950 \
951 if (handle->socket == INVALID_SOCKET) \
952 return UV_EBADF; \
953 \
954 if (!(handle->flags & UV_HANDLE_IPV6)) { \
955 /* Set IPv4 socket option */ \
956 if (setsockopt(handle->socket, \
957 IPPROTO_IP, \
958 option4, \
959 (char*) &optval, \
960 sizeof optval)) { \
961 return uv_translate_sys_error(WSAGetLastError()); \
962 } \
963 } else { \
964 /* Set IPv6 socket option */ \
965 if (setsockopt(handle->socket, \
966 IPPROTO_IPV6, \
967 option6, \
968 (char*) &optval, \
969 sizeof optval)) { \
970 return uv_translate_sys_error(WSAGetLastError()); \
971 } \
972 } \
973 return 0; \
974 }
975
976 #define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)
977 #define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)
978 #define VALIDATE_MULTICAST_LOOP(value) (1)
979
SOCKOPT_SETTER(ttl,IP_TTL,IPV6_HOPLIMIT,VALIDATE_TTL)980 SOCKOPT_SETTER(ttl,
981 IP_TTL,
982 IPV6_HOPLIMIT,
983 VALIDATE_TTL)
984 SOCKOPT_SETTER(multicast_ttl,
985 IP_MULTICAST_TTL,
986 IPV6_MULTICAST_HOPS,
987 VALIDATE_MULTICAST_TTL)
988 SOCKOPT_SETTER(multicast_loop,
989 IP_MULTICAST_LOOP,
990 IPV6_MULTICAST_LOOP,
991 VALIDATE_MULTICAST_LOOP)
992
993 #undef SOCKOPT_SETTER
994 #undef VALIDATE_TTL
995 #undef VALIDATE_MULTICAST_TTL
996 #undef VALIDATE_MULTICAST_LOOP
997
998
999 /* This function is an egress point, i.e. it returns libuv errors rather than
1000 * system errors.
1001 */
1002 int uv__udp_bind(uv_udp_t* handle,
1003 const struct sockaddr* addr,
1004 unsigned int addrlen,
1005 unsigned int flags) {
1006 int err;
1007
1008 err = uv__udp_maybe_bind(handle, addr, addrlen, flags);
1009 if (err)
1010 return uv_translate_sys_error(err);
1011
1012 return 0;
1013 }
1014
1015
uv__udp_connect(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen)1016 int uv__udp_connect(uv_udp_t* handle,
1017 const struct sockaddr* addr,
1018 unsigned int addrlen) {
1019 const struct sockaddr* bind_addr;
1020 int err;
1021
1022 if (!(handle->flags & UV_HANDLE_BOUND)) {
1023 if (addrlen == sizeof(uv_addr_ip4_any_))
1024 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1025 else if (addrlen == sizeof(uv_addr_ip6_any_))
1026 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1027 else
1028 return UV_EINVAL;
1029
1030 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1031 if (err)
1032 return uv_translate_sys_error(err);
1033 }
1034
1035 err = connect(handle->socket, addr, addrlen);
1036 if (err)
1037 return uv_translate_sys_error(WSAGetLastError());
1038
1039 handle->flags |= UV_HANDLE_UDP_CONNECTED;
1040
1041 return 0;
1042 }
1043
1044
uv__udp_disconnect(uv_udp_t * handle)1045 int uv__udp_disconnect(uv_udp_t* handle) {
1046 int err;
1047 struct sockaddr_storage addr;
1048
1049 memset(&addr, 0, sizeof(addr));
1050
1051 err = connect(handle->socket, (struct sockaddr*) &addr, sizeof(addr));
1052 if (err)
1053 return uv_translate_sys_error(WSAGetLastError());
1054
1055 handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
1056 return 0;
1057 }
1058
1059
1060 /* This function is an egress point, i.e. it returns libuv errors rather than
1061 * system errors.
1062 */
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)1063 int uv__udp_send(uv_udp_send_t* req,
1064 uv_udp_t* handle,
1065 const uv_buf_t bufs[],
1066 unsigned int nbufs,
1067 const struct sockaddr* addr,
1068 unsigned int addrlen,
1069 uv_udp_send_cb send_cb) {
1070 const struct sockaddr* bind_addr;
1071 int err;
1072
1073 if (!(handle->flags & UV_HANDLE_BOUND)) {
1074 if (addrlen == sizeof(uv_addr_ip4_any_))
1075 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1076 else if (addrlen == sizeof(uv_addr_ip6_any_))
1077 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1078 else
1079 return UV_EINVAL;
1080
1081 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1082 if (err)
1083 return uv_translate_sys_error(err);
1084 }
1085
1086 err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
1087 if (err)
1088 return uv_translate_sys_error(err);
1089
1090 return 0;
1091 }
1092
1093
uv__udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen)1094 int uv__udp_try_send(uv_udp_t* handle,
1095 const uv_buf_t bufs[],
1096 unsigned int nbufs,
1097 const struct sockaddr* addr,
1098 unsigned int addrlen) {
1099 DWORD bytes;
1100 const struct sockaddr* bind_addr;
1101 struct sockaddr_storage converted;
1102 int err;
1103
1104 assert(nbufs > 0);
1105
1106 if (addr != NULL) {
1107 err = uv__convert_to_localhost_if_unspecified(addr, &converted);
1108 if (err)
1109 return err;
1110 addr = (const struct sockaddr*) &converted;
1111 }
1112
1113 /* Already sending a message.*/
1114 if (handle->send_queue_count != 0)
1115 return UV_EAGAIN;
1116
1117 if (!(handle->flags & UV_HANDLE_BOUND)) {
1118 if (addrlen == sizeof(uv_addr_ip4_any_))
1119 bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
1120 else if (addrlen == sizeof(uv_addr_ip6_any_))
1121 bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
1122 else
1123 return UV_EINVAL;
1124 err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0);
1125 if (err)
1126 return uv_translate_sys_error(err);
1127 }
1128
1129 err = WSASendTo(handle->socket,
1130 (WSABUF*)bufs,
1131 nbufs,
1132 &bytes,
1133 0,
1134 addr,
1135 addrlen,
1136 NULL,
1137 NULL);
1138
1139 if (err)
1140 return uv_translate_sys_error(WSAGetLastError());
1141
1142 return bytes;
1143 }
1144