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