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 /*
33  * Threshold of active udp streams for which to preallocate udp read buffers.
34  */
35 const unsigned int uv_active_udp_streams_threshold = 0;
36 
37 /* A zero-size buffer for use by uv_udp_read */
38 static char uv_zero_[] = "";
39 
uv_udp_getsockname(const uv_udp_t * handle,struct sockaddr * name,int * namelen)40 int uv_udp_getsockname(const uv_udp_t* handle,
41                        struct sockaddr* name,
42                        int* namelen) {
43   int result;
44 
45   if (handle->socket == INVALID_SOCKET) {
46     return UV_EINVAL;
47   }
48 
49   result = getsockname(handle->socket, name, namelen);
50   if (result != 0) {
51     return uv_translate_sys_error(WSAGetLastError());
52   }
53 
54   return 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. */
78   /* Use uv_handle_t pointer as completion key. */
79   if (CreateIoCompletionPort((HANDLE)socket,
80                              loop->iocp,
81                              (ULONG_PTR)socket,
82                              0) == NULL) {
83     return GetLastError();
84   }
85 
86   if (pSetFileCompletionNotificationModes) {
87     /* All known Windows that support SetFileCompletionNotificationModes */
88     /* have a bug that makes it impossible to use this function in */
89     /* conjunction with datagram sockets. We can work around that but only */
90     /* if the user is using the default UDP driver (AFD) and has no other */
91     /* LSPs stacked on top. Here we check whether that is the case. */
92     opt_len = (int) sizeof info;
93     if (getsockopt(socket,
94                    SOL_SOCKET,
95                    SO_PROTOCOL_INFOW,
96                    (char*) &info,
97                    &opt_len) == SOCKET_ERROR) {
98       return GetLastError();
99     }
100 
101     if (info.ProtocolChain.ChainLen == 1) {
102       if (pSetFileCompletionNotificationModes((HANDLE)socket,
103           FILE_SKIP_SET_EVENT_ON_HANDLE |
104           FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
105         handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
106         handle->func_wsarecv = uv_wsarecv_workaround;
107         handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
108       } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
109         return GetLastError();
110       }
111     }
112   }
113 
114   handle->socket = socket;
115 
116   if (family == AF_INET6) {
117     handle->flags |= UV_HANDLE_IPV6;
118   } else {
119     assert(!(handle->flags & UV_HANDLE_IPV6));
120   }
121 
122   return 0;
123 }
124 
125 
uv_udp_init_ex(uv_loop_t * loop,uv_udp_t * handle,unsigned int flags)126 int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
127   int domain;
128 
129   /* Use the lower 8 bits for the domain */
130   domain = flags & 0xFF;
131   if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
132     return UV_EINVAL;
133 
134   if (flags & ~0xFF)
135     return UV_EINVAL;
136 
137   uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
138   handle->socket = INVALID_SOCKET;
139   handle->reqs_pending = 0;
140   handle->activecnt = 0;
141   handle->func_wsarecv = WSARecv;
142   handle->func_wsarecvfrom = WSARecvFrom;
143   handle->send_queue_size = 0;
144   handle->send_queue_count = 0;
145   UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
146   handle->recv_req.data = handle;
147 
148   /* If anything fails beyond this point we need to remove the handle from
149    * the handle queue, since it was added by uv__handle_init.
150    */
151 
152   if (domain != AF_UNSPEC) {
153     SOCKET sock;
154     DWORD err;
155 
156     sock = socket(domain, SOCK_DGRAM, 0);
157     if (sock == INVALID_SOCKET) {
158       err = WSAGetLastError();
159       QUEUE_REMOVE(&handle->handle_queue);
160       return uv_translate_sys_error(err);
161     }
162 
163     err = uv_udp_set_socket(handle->loop, handle, sock, domain);
164     if (err) {
165       closesocket(sock);
166       QUEUE_REMOVE(&handle->handle_queue);
167       return uv_translate_sys_error(err);
168     }
169   }
170 
171   return 0;
172 }
173 
174 
uv_udp_init(uv_loop_t * loop,uv_udp_t * handle)175 int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
176   return uv_udp_init_ex(loop, handle, AF_UNSPEC);
177 }
178 
179 
uv_udp_close(uv_loop_t * loop,uv_udp_t * handle)180 void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
181   uv_udp_recv_stop(handle);
182   closesocket(handle->socket);
183   handle->socket = INVALID_SOCKET;
184 
185   uv__handle_closing(handle);
186 
187   if (handle->reqs_pending == 0) {
188     uv_want_endgame(loop, (uv_handle_t*) handle);
189   }
190 }
191 
192 
uv_udp_endgame(uv_loop_t * loop,uv_udp_t * handle)193 void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
194   if (handle->flags & UV__HANDLE_CLOSING &&
195       handle->reqs_pending == 0) {
196     assert(!(handle->flags & UV_HANDLE_CLOSED));
197     uv__handle_close(handle);
198   }
199 }
200 
201 
uv_udp_maybe_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)202 static int uv_udp_maybe_bind(uv_udp_t* handle,
203                              const struct sockaddr* addr,
204                              unsigned int addrlen,
205                              unsigned int flags) {
206   int r;
207   int err;
208   DWORD no = 0;
209 
210   if (handle->flags & UV_HANDLE_BOUND)
211     return 0;
212 
213   if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
214     /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
215     return ERROR_INVALID_PARAMETER;
216   }
217 
218   if (handle->socket == INVALID_SOCKET) {
219     SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);
220     if (sock == INVALID_SOCKET) {
221       return WSAGetLastError();
222     }
223 
224     err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family);
225     if (err) {
226       closesocket(sock);
227       return err;
228     }
229   }
230 
231   if (flags & UV_UDP_REUSEADDR) {
232     DWORD yes = 1;
233     /* Set SO_REUSEADDR on the socket. */
234     if (setsockopt(handle->socket,
235                    SOL_SOCKET,
236                    SO_REUSEADDR,
237                    (char*) &yes,
238                    sizeof yes) == SOCKET_ERROR) {
239       err = WSAGetLastError();
240       return err;
241     }
242   }
243 
244   if (addr->sa_family == AF_INET6)
245     handle->flags |= UV_HANDLE_IPV6;
246 
247   if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
248     /* On windows IPV6ONLY is on by default. */
249     /* If the user doesn't specify it libuv turns it off. */
250 
251     /* TODO: how to handle errors? This may fail if there is no ipv4 stack */
252     /* available, or when run on XP/2003 which have no support for dualstack */
253     /* sockets. For now we're silently ignoring the error. */
254     setsockopt(handle->socket,
255                IPPROTO_IPV6,
256                IPV6_V6ONLY,
257                (char*) &no,
258                sizeof no);
259   }
260 
261   r = bind(handle->socket, addr, addrlen);
262   if (r == SOCKET_ERROR) {
263     return WSAGetLastError();
264   }
265 
266   handle->flags |= UV_HANDLE_BOUND;
267 
268   return 0;
269 }
270 
271 
uv_udp_queue_recv(uv_loop_t * loop,uv_udp_t * handle)272 static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
273   uv_req_t* req;
274   uv_buf_t buf;
275   DWORD bytes, flags;
276   int result;
277 
278   assert(handle->flags & UV_HANDLE_READING);
279   assert(!(handle->flags & UV_HANDLE_READ_PENDING));
280 
281   req = &handle->recv_req;
282   memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
283 
284   /*
285    * Preallocate a read buffer if the number of active streams is below
286    * the threshold.
287   */
288   if (loop->active_udp_streams < uv_active_udp_streams_threshold) {
289     handle->flags &= ~UV_HANDLE_ZERO_READ;
290 
291     handle->recv_buffer = uv_buf_init(NULL, 0);
292     handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer);
293     if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) {
294       handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0);
295       return;
296     }
297     assert(handle->recv_buffer.base != NULL);
298 
299     buf = handle->recv_buffer;
300     memset(&handle->recv_from, 0, sizeof handle->recv_from);
301     handle->recv_from_len = sizeof handle->recv_from;
302     flags = 0;
303 
304     result = handle->func_wsarecvfrom(handle->socket,
305                                       (WSABUF*) &buf,
306                                       1,
307                                       &bytes,
308                                       &flags,
309                                       (struct sockaddr*) &handle->recv_from,
310                                       &handle->recv_from_len,
311                                       &req->u.io.overlapped,
312                                       NULL);
313 
314     if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
315       /* Process the req without IOCP. */
316       handle->flags |= UV_HANDLE_READ_PENDING;
317       req->u.io.overlapped.InternalHigh = bytes;
318       handle->reqs_pending++;
319       uv_insert_pending_req(loop, req);
320     } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
321       /* The req will be processed with IOCP. */
322       handle->flags |= UV_HANDLE_READ_PENDING;
323       handle->reqs_pending++;
324     } else {
325       /* Make this req pending reporting an error. */
326       SET_REQ_ERROR(req, WSAGetLastError());
327       uv_insert_pending_req(loop, req);
328       handle->reqs_pending++;
329     }
330 
331   } else {
332     handle->flags |= UV_HANDLE_ZERO_READ;
333 
334     buf.base = (char*) uv_zero_;
335     buf.len = 0;
336     flags = MSG_PEEK;
337 
338     result = handle->func_wsarecv(handle->socket,
339                                   (WSABUF*) &buf,
340                                   1,
341                                   &bytes,
342                                   &flags,
343                                   &req->u.io.overlapped,
344                                   NULL);
345 
346     if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
347       /* Process the req without IOCP. */
348       handle->flags |= UV_HANDLE_READ_PENDING;
349       req->u.io.overlapped.InternalHigh = bytes;
350       handle->reqs_pending++;
351       uv_insert_pending_req(loop, req);
352     } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
353       /* The req will be processed with IOCP. */
354       handle->flags |= UV_HANDLE_READ_PENDING;
355       handle->reqs_pending++;
356     } else {
357       /* Make this req pending reporting an error. */
358       SET_REQ_ERROR(req, WSAGetLastError());
359       uv_insert_pending_req(loop, req);
360       handle->reqs_pending++;
361     }
362   }
363 }
364 
365 
uv__udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)366 int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
367     uv_udp_recv_cb recv_cb) {
368   uv_loop_t* loop = handle->loop;
369   int err;
370 
371   if (handle->flags & UV_HANDLE_READING) {
372     return WSAEALREADY;
373   }
374 
375   err = uv_udp_maybe_bind(handle,
376                           (const struct sockaddr*) &uv_addr_ip4_any_,
377                           sizeof(uv_addr_ip4_any_),
378                           0);
379   if (err)
380     return err;
381 
382   handle->flags |= UV_HANDLE_READING;
383   INCREASE_ACTIVE_COUNT(loop, handle);
384   loop->active_udp_streams++;
385 
386   handle->recv_cb = recv_cb;
387   handle->alloc_cb = alloc_cb;
388 
389   /* If reading was stopped and then started again, there could still be a */
390   /* recv request pending. */
391   if (!(handle->flags & UV_HANDLE_READ_PENDING))
392     uv_udp_queue_recv(loop, handle);
393 
394   return 0;
395 }
396 
397 
uv__udp_recv_stop(uv_udp_t * handle)398 int uv__udp_recv_stop(uv_udp_t* handle) {
399   if (handle->flags & UV_HANDLE_READING) {
400     handle->flags &= ~UV_HANDLE_READING;
401     handle->loop->active_udp_streams--;
402     DECREASE_ACTIVE_COUNT(loop, handle);
403   }
404 
405   return 0;
406 }
407 
408 
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)409 static int uv__send(uv_udp_send_t* req,
410                     uv_udp_t* handle,
411                     const uv_buf_t bufs[],
412                     unsigned int nbufs,
413                     const struct sockaddr* addr,
414                     unsigned int addrlen,
415                     uv_udp_send_cb cb) {
416   uv_loop_t* loop = handle->loop;
417   DWORD result, bytes;
418 
419   UV_REQ_INIT(req, UV_UDP_SEND);
420   req->handle = handle;
421   req->cb = cb;
422   memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
423 
424   result = WSASendTo(handle->socket,
425                      (WSABUF*)bufs,
426                      nbufs,
427                      &bytes,
428                      0,
429                      addr,
430                      addrlen,
431                      &req->u.io.overlapped,
432                      NULL);
433 
434   if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
435     /* Request completed immediately. */
436     req->u.io.queued_bytes = 0;
437     handle->reqs_pending++;
438     handle->send_queue_size += req->u.io.queued_bytes;
439     handle->send_queue_count++;
440     REGISTER_HANDLE_REQ(loop, handle, req);
441     uv_insert_pending_req(loop, (uv_req_t*)req);
442   } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
443     /* Request queued by the kernel. */
444     req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
445     handle->reqs_pending++;
446     handle->send_queue_size += req->u.io.queued_bytes;
447     handle->send_queue_count++;
448     REGISTER_HANDLE_REQ(loop, handle, req);
449   } else {
450     /* Send failed due to an error. */
451     return WSAGetLastError();
452   }
453 
454   return 0;
455 }
456 
457 
uv_process_udp_recv_req(uv_loop_t * loop,uv_udp_t * handle,uv_req_t * req)458 void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
459     uv_req_t* req) {
460   uv_buf_t buf;
461   int partial;
462 
463   assert(handle->type == UV_UDP);
464 
465   handle->flags &= ~UV_HANDLE_READ_PENDING;
466 
467   if (!REQ_SUCCESS(req)) {
468     DWORD err = GET_REQ_SOCK_ERROR(req);
469     if (err == WSAEMSGSIZE) {
470       /* Not a real error, it just indicates that the received packet */
471       /* was bigger than the receive buffer. */
472     } else if (err == WSAECONNRESET || err == WSAENETRESET) {
473       /* A previous sendto operation failed; ignore this error. If */
474       /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */
475       /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */
476       /* immediately queue a new receive. */
477       if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
478         goto done;
479       }
480     } else {
481       /* A real error occurred. Report the error to the user only if we're */
482       /* currently reading. */
483       if (handle->flags & UV_HANDLE_READING) {
484         uv_udp_recv_stop(handle);
485         buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
486               uv_buf_init(NULL, 0) : handle->recv_buffer;
487         handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
488       }
489       goto done;
490     }
491   }
492 
493   if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
494     /* Successful read */
495     partial = !REQ_SUCCESS(req);
496     handle->recv_cb(handle,
497                     req->u.io.overlapped.InternalHigh,
498                     &handle->recv_buffer,
499                     (const struct sockaddr*) &handle->recv_from,
500                     partial ? UV_UDP_PARTIAL : 0);
501   } else if (handle->flags & UV_HANDLE_READING) {
502     DWORD bytes, err, flags;
503     struct sockaddr_storage from;
504     int from_len;
505 
506     /* Do a nonblocking receive */
507     /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
508     buf = uv_buf_init(NULL, 0);
509     handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
510     if (buf.base == NULL || buf.len == 0) {
511       handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
512       goto done;
513     }
514     assert(buf.base != NULL);
515 
516     memset(&from, 0, sizeof from);
517     from_len = sizeof from;
518 
519     flags = 0;
520 
521     if (WSARecvFrom(handle->socket,
522                     (WSABUF*)&buf,
523                     1,
524                     &bytes,
525                     &flags,
526                     (struct sockaddr*) &from,
527                     &from_len,
528                     NULL,
529                     NULL) != SOCKET_ERROR) {
530 
531       /* Message received */
532       handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);
533     } else {
534       err = WSAGetLastError();
535       if (err == WSAEMSGSIZE) {
536         /* Message truncated */
537         handle->recv_cb(handle,
538                         bytes,
539                         &buf,
540                         (const struct sockaddr*) &from,
541                         UV_UDP_PARTIAL);
542       } else if (err == WSAEWOULDBLOCK) {
543         /* Kernel buffer empty */
544         handle->recv_cb(handle, 0, &buf, NULL, 0);
545       } else if (err == WSAECONNRESET || err == WSAENETRESET) {
546         /* WSAECONNRESET/WSANETRESET is ignored because this just indicates
547          * that a previous sendto operation failed.
548          */
549         handle->recv_cb(handle, 0, &buf, NULL, 0);
550       } else {
551         /* Any other error that we want to report back to the user. */
552         uv_udp_recv_stop(handle);
553         handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
554       }
555     }
556   }
557 
558 done:
559   /* Post another read if still reading and not closing. */
560   if ((handle->flags & UV_HANDLE_READING) &&
561       !(handle->flags & UV_HANDLE_READ_PENDING)) {
562     uv_udp_queue_recv(loop, handle);
563   }
564 
565   DECREASE_PENDING_REQ_COUNT(handle);
566 }
567 
568 
uv_process_udp_send_req(uv_loop_t * loop,uv_udp_t * handle,uv_udp_send_t * req)569 void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
570     uv_udp_send_t* req) {
571   int err;
572 
573   assert(handle->type == UV_UDP);
574 
575   assert(handle->send_queue_size >= req->u.io.queued_bytes);
576   assert(handle->send_queue_count >= 1);
577   handle->send_queue_size -= req->u.io.queued_bytes;
578   handle->send_queue_count--;
579 
580   UNREGISTER_HANDLE_REQ(loop, handle, req);
581 
582   if (req->cb) {
583     err = 0;
584     if (!REQ_SUCCESS(req)) {
585       err = GET_REQ_SOCK_ERROR(req);
586     }
587     req->cb(req, uv_translate_sys_error(err));
588   }
589 
590   DECREASE_PENDING_REQ_COUNT(handle);
591 }
592 
593 
uv__udp_set_membership4(uv_udp_t * handle,const struct sockaddr_in * multicast_addr,const char * interface_addr,uv_membership membership)594 static int uv__udp_set_membership4(uv_udp_t* handle,
595                                    const struct sockaddr_in* multicast_addr,
596                                    const char* interface_addr,
597                                    uv_membership membership) {
598   int err;
599   int optname;
600   struct ip_mreq mreq;
601 
602   if (handle->flags & UV_HANDLE_IPV6)
603     return UV_EINVAL;
604 
605   /* If the socket is unbound, bind to inaddr_any. */
606   err = uv_udp_maybe_bind(handle,
607                           (const struct sockaddr*) &uv_addr_ip4_any_,
608                           sizeof(uv_addr_ip4_any_),
609                           UV_UDP_REUSEADDR);
610   if (err)
611     return uv_translate_sys_error(err);
612 
613   memset(&mreq, 0, sizeof mreq);
614 
615   if (interface_addr) {
616     err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
617     if (err)
618       return err;
619   } else {
620     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
621   }
622 
623   mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
624 
625   switch (membership) {
626     case UV_JOIN_GROUP:
627       optname = IP_ADD_MEMBERSHIP;
628       break;
629     case UV_LEAVE_GROUP:
630       optname = IP_DROP_MEMBERSHIP;
631       break;
632     default:
633       return UV_EINVAL;
634   }
635 
636   if (setsockopt(handle->socket,
637                  IPPROTO_IP,
638                  optname,
639                  (char*) &mreq,
640                  sizeof mreq) == SOCKET_ERROR) {
641     return uv_translate_sys_error(WSAGetLastError());
642   }
643 
644   return 0;
645 }
646 
647 
uv__udp_set_membership6(uv_udp_t * handle,const struct sockaddr_in6 * multicast_addr,const char * interface_addr,uv_membership membership)648 int uv__udp_set_membership6(uv_udp_t* handle,
649                             const struct sockaddr_in6* multicast_addr,
650                             const char* interface_addr,
651                             uv_membership membership) {
652   int optname;
653   int err;
654   struct ipv6_mreq mreq;
655   struct sockaddr_in6 addr6;
656 
657   if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
658     return UV_EINVAL;
659 
660   err = uv_udp_maybe_bind(handle,
661                           (const struct sockaddr*) &uv_addr_ip6_any_,
662                           sizeof(uv_addr_ip6_any_),
663                           UV_UDP_REUSEADDR);
664 
665   if (err)
666     return uv_translate_sys_error(err);
667 
668   memset(&mreq, 0, sizeof(mreq));
669 
670   if (interface_addr) {
671     if (uv_ip6_addr(interface_addr, 0, &addr6))
672       return UV_EINVAL;
673     mreq.ipv6mr_interface = addr6.sin6_scope_id;
674   } else {
675     mreq.ipv6mr_interface = 0;
676   }
677 
678   mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
679 
680   switch (membership) {
681   case UV_JOIN_GROUP:
682     optname = IPV6_ADD_MEMBERSHIP;
683     break;
684   case UV_LEAVE_GROUP:
685     optname = IPV6_DROP_MEMBERSHIP;
686     break;
687   default:
688     return UV_EINVAL;
689   }
690 
691   if (setsockopt(handle->socket,
692                  IPPROTO_IPV6,
693                  optname,
694                  (char*) &mreq,
695                  sizeof mreq) == SOCKET_ERROR) {
696     return uv_translate_sys_error(WSAGetLastError());
697   }
698 
699   return 0;
700 }
701 
702 
uv_udp_set_membership(uv_udp_t * handle,const char * multicast_addr,const char * interface_addr,uv_membership membership)703 int uv_udp_set_membership(uv_udp_t* handle,
704                           const char* multicast_addr,
705                           const char* interface_addr,
706                           uv_membership membership) {
707   struct sockaddr_in addr4;
708   struct sockaddr_in6 addr6;
709 
710   if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)
711     return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
712   else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)
713     return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
714   else
715     return UV_EINVAL;
716 }
717 
718 
uv_udp_set_multicast_interface(uv_udp_t * handle,const char * interface_addr)719 int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
720   struct sockaddr_storage addr_st;
721   struct sockaddr_in* addr4;
722   struct sockaddr_in6* addr6;
723 
724   addr4 = (struct sockaddr_in*) &addr_st;
725   addr6 = (struct sockaddr_in6*) &addr_st;
726 
727   if (!interface_addr) {
728     memset(&addr_st, 0, sizeof addr_st);
729     if (handle->flags & UV_HANDLE_IPV6) {
730       addr_st.ss_family = AF_INET6;
731       addr6->sin6_scope_id = 0;
732     } else {
733       addr_st.ss_family = AF_INET;
734       addr4->sin_addr.s_addr = htonl(INADDR_ANY);
735     }
736   } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
737     /* nothing, address was parsed */
738   } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
739     /* nothing, address was parsed */
740   } else {
741     return UV_EINVAL;
742   }
743 
744   if (!(handle->flags & UV_HANDLE_BOUND))
745     return UV_EBADF;
746 
747   if (addr_st.ss_family == AF_INET) {
748     if (setsockopt(handle->socket,
749                    IPPROTO_IP,
750                    IP_MULTICAST_IF,
751                    (char*) &addr4->sin_addr,
752                    sizeof(addr4->sin_addr)) == SOCKET_ERROR) {
753       return uv_translate_sys_error(WSAGetLastError());
754     }
755   } else if (addr_st.ss_family == AF_INET6) {
756     if (setsockopt(handle->socket,
757                    IPPROTO_IPV6,
758                    IPV6_MULTICAST_IF,
759                    (char*) &addr6->sin6_scope_id,
760                    sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {
761       return uv_translate_sys_error(WSAGetLastError());
762     }
763   } else {
764     assert(0 && "unexpected address family");
765     abort();
766   }
767 
768   return 0;
769 }
770 
771 
uv_udp_set_broadcast(uv_udp_t * handle,int value)772 int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
773   BOOL optval = (BOOL) value;
774 
775   if (!(handle->flags & UV_HANDLE_BOUND))
776     return UV_EBADF;
777 
778   if (setsockopt(handle->socket,
779                  SOL_SOCKET,
780                  SO_BROADCAST,
781                  (char*) &optval,
782                  sizeof optval)) {
783     return uv_translate_sys_error(WSAGetLastError());
784   }
785 
786   return 0;
787 }
788 
789 
uv_udp_open(uv_udp_t * handle,uv_os_sock_t sock)790 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
791   WSAPROTOCOL_INFOW protocol_info;
792   int opt_len;
793   int err;
794 
795   /* Detect the address family of the socket. */
796   opt_len = (int) sizeof protocol_info;
797   if (getsockopt(sock,
798                  SOL_SOCKET,
799                  SO_PROTOCOL_INFOW,
800                  (char*) &protocol_info,
801                  &opt_len) == SOCKET_ERROR) {
802     return uv_translate_sys_error(GetLastError());
803   }
804 
805   err = uv_udp_set_socket(handle->loop,
806                           handle,
807                           sock,
808                           protocol_info.iAddressFamily);
809   return uv_translate_sys_error(err);
810 }
811 
812 
813 #define SOCKOPT_SETTER(name, option4, option6, validate)                      \
814   int uv_udp_set_##name(uv_udp_t* handle, int value) {                        \
815     DWORD optval = (DWORD) value;                                             \
816                                                                               \
817     if (!(validate(value))) {                                                 \
818       return UV_EINVAL;                                                       \
819     }                                                                         \
820                                                                               \
821     if (!(handle->flags & UV_HANDLE_BOUND))                                   \
822       return UV_EBADF;                                                        \
823                                                                               \
824     if (!(handle->flags & UV_HANDLE_IPV6)) {                                  \
825       /* Set IPv4 socket option */                                            \
826       if (setsockopt(handle->socket,                                          \
827                      IPPROTO_IP,                                              \
828                      option4,                                                 \
829                      (char*) &optval,                                         \
830                      sizeof optval)) {                                        \
831         return uv_translate_sys_error(WSAGetLastError());                     \
832       }                                                                       \
833     } else {                                                                  \
834       /* Set IPv6 socket option */                                            \
835       if (setsockopt(handle->socket,                                          \
836                      IPPROTO_IPV6,                                            \
837                      option6,                                                 \
838                      (char*) &optval,                                         \
839                      sizeof optval)) {                                        \
840         return uv_translate_sys_error(WSAGetLastError());                     \
841       }                                                                       \
842     }                                                                         \
843     return 0;                                                                 \
844   }
845 
846 #define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)
847 #define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)
848 #define VALIDATE_MULTICAST_LOOP(value) (1)
849 
SOCKOPT_SETTER(ttl,IP_TTL,IPV6_HOPLIMIT,VALIDATE_TTL)850 SOCKOPT_SETTER(ttl,
851                IP_TTL,
852                IPV6_HOPLIMIT,
853                VALIDATE_TTL)
854 SOCKOPT_SETTER(multicast_ttl,
855                IP_MULTICAST_TTL,
856                IPV6_MULTICAST_HOPS,
857                VALIDATE_MULTICAST_TTL)
858 SOCKOPT_SETTER(multicast_loop,
859                IP_MULTICAST_LOOP,
860                IPV6_MULTICAST_LOOP,
861                VALIDATE_MULTICAST_LOOP)
862 
863 #undef SOCKOPT_SETTER
864 #undef VALIDATE_TTL
865 #undef VALIDATE_MULTICAST_TTL
866 #undef VALIDATE_MULTICAST_LOOP
867 
868 
869 /* This function is an egress point, i.e. it returns libuv errors rather than
870  * system errors.
871  */
872 int uv__udp_bind(uv_udp_t* handle,
873                  const struct sockaddr* addr,
874                  unsigned int addrlen,
875                  unsigned int flags) {
876   int err;
877 
878   err = uv_udp_maybe_bind(handle, addr, addrlen, flags);
879   if (err)
880     return uv_translate_sys_error(err);
881 
882   return 0;
883 }
884 
885 
886 /* This function is an egress point, i.e. it returns libuv errors rather than
887  * system errors.
888  */
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)889 int uv__udp_send(uv_udp_send_t* req,
890                  uv_udp_t* handle,
891                  const uv_buf_t bufs[],
892                  unsigned int nbufs,
893                  const struct sockaddr* addr,
894                  unsigned int addrlen,
895                  uv_udp_send_cb send_cb) {
896   const struct sockaddr* bind_addr;
897   int err;
898 
899   if (!(handle->flags & UV_HANDLE_BOUND)) {
900     if (addrlen == sizeof(uv_addr_ip4_any_))
901       bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
902     else if (addrlen == sizeof(uv_addr_ip6_any_))
903       bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
904     else
905       return UV_EINVAL;
906     err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
907     if (err)
908       return uv_translate_sys_error(err);
909   }
910 
911   err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
912   if (err)
913     return uv_translate_sys_error(err);
914 
915   return 0;
916 }
917 
918 
uv__udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,unsigned int addrlen)919 int uv__udp_try_send(uv_udp_t* handle,
920                      const uv_buf_t bufs[],
921                      unsigned int nbufs,
922                      const struct sockaddr* addr,
923                      unsigned int addrlen) {
924   DWORD bytes;
925   const struct sockaddr* bind_addr;
926   struct sockaddr_storage converted;
927   int err;
928 
929   assert(nbufs > 0);
930 
931   err = uv__convert_to_localhost_if_unspecified(addr, &converted);
932   if (err)
933     return err;
934 
935   /* Already sending a message.*/
936   if (handle->send_queue_count != 0)
937     return UV_EAGAIN;
938 
939   if (!(handle->flags & UV_HANDLE_BOUND)) {
940     if (addrlen == sizeof(uv_addr_ip4_any_))
941       bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
942     else if (addrlen == sizeof(uv_addr_ip6_any_))
943       bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
944     else
945       return UV_EINVAL;
946     err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
947     if (err)
948       return uv_translate_sys_error(err);
949   }
950 
951   err = WSASendTo(handle->socket,
952                   (WSABUF*)bufs,
953                   nbufs,
954                   &bytes,
955                   0,
956                   (const struct sockaddr*) &converted,
957                   addrlen,
958                   NULL,
959                   NULL);
960 
961   if (err)
962     return uv_translate_sys_error(WSAGetLastError());
963 
964   return bytes;
965 }
966