xref: /libuv/src/win/udp.c (revision 7c491bde)
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