• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "uv.h"
23 #include "internal.h"
24 
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <assert.h>
28 #include <errno.h>
29 
30 
new_socket(uv_tcp_t * handle,int domain,unsigned long flags)31 static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
32   struct sockaddr_storage saddr;
33   socklen_t slen;
34   int sockfd;
35   int err;
36 
37   err = uv__socket(domain, SOCK_STREAM, 0);
38   if (err < 0)
39     return err;
40   sockfd = err;
41 
42   err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
43   if (err) {
44     uv__close(sockfd);
45     return err;
46   }
47 
48   if (flags & UV_HANDLE_BOUND) {
49     /* Bind this new socket to an arbitrary port */
50     slen = sizeof(saddr);
51     memset(&saddr, 0, sizeof(saddr));
52     if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
53       uv__close(sockfd);
54       return UV__ERR(errno);
55     }
56 
57     if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
58       uv__close(sockfd);
59       return UV__ERR(errno);
60     }
61   }
62 
63   return 0;
64 }
65 
66 
maybe_new_socket(uv_tcp_t * handle,int domain,unsigned long flags)67 static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
68   struct sockaddr_storage saddr;
69   socklen_t slen;
70 
71   if (domain == AF_UNSPEC) {
72     handle->flags |= flags;
73     return 0;
74   }
75 
76   if (uv__stream_fd(handle) != -1) {
77 
78     if (flags & UV_HANDLE_BOUND) {
79 
80       if (handle->flags & UV_HANDLE_BOUND) {
81         /* It is already bound to a port. */
82         handle->flags |= flags;
83         return 0;
84       }
85 
86       /* Query to see if tcp socket is bound. */
87       slen = sizeof(saddr);
88       memset(&saddr, 0, sizeof(saddr));
89       if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
90         return UV__ERR(errno);
91 
92       if ((saddr.ss_family == AF_INET6 &&
93           ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
94           (saddr.ss_family == AF_INET &&
95           ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
96         /* Handle is already bound to a port. */
97         handle->flags |= flags;
98         return 0;
99       }
100 
101       /* Bind to arbitrary port */
102       if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
103         return UV__ERR(errno);
104     }
105 
106     handle->flags |= flags;
107     return 0;
108   }
109 
110   return new_socket(handle, domain, flags);
111 }
112 
113 
uv_tcp_init_ex(uv_loop_t * loop,uv_tcp_t * tcp,unsigned int flags)114 int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
115   int domain;
116 
117   /* Use the lower 8 bits for the domain */
118   domain = flags & 0xFF;
119   if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
120     return UV_EINVAL;
121 
122   if (flags & ~0xFF)
123     return UV_EINVAL;
124 
125   uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
126 
127   /* If anything fails beyond this point we need to remove the handle from
128    * the handle queue, since it was added by uv__handle_init in uv_stream_init.
129    */
130 
131   if (domain != AF_UNSPEC) {
132     int err = maybe_new_socket(tcp, domain, 0);
133     if (err) {
134       QUEUE_REMOVE(&tcp->handle_queue);
135       return err;
136     }
137   }
138 
139   return 0;
140 }
141 
142 
uv_tcp_init(uv_loop_t * loop,uv_tcp_t * tcp)143 int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
144   return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
145 }
146 
147 
uv__tcp_bind(uv_tcp_t * tcp,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)148 int uv__tcp_bind(uv_tcp_t* tcp,
149                  const struct sockaddr* addr,
150                  unsigned int addrlen,
151                  unsigned int flags) {
152   int err;
153   int on;
154 
155   /* Cannot set IPv6-only mode on non-IPv6 socket. */
156   if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
157     return UV_EINVAL;
158 
159   err = maybe_new_socket(tcp, addr->sa_family, 0);
160   if (err)
161     return err;
162 
163   on = 1;
164   if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
165     return UV__ERR(errno);
166 
167 #ifndef __OpenBSD__
168 #ifdef IPV6_V6ONLY
169   if (addr->sa_family == AF_INET6) {
170     on = (flags & UV_TCP_IPV6ONLY) != 0;
171     if (setsockopt(tcp->io_watcher.fd,
172                    IPPROTO_IPV6,
173                    IPV6_V6ONLY,
174                    &on,
175                    sizeof on) == -1) {
176 #if defined(__MVS__)
177       if (errno == EOPNOTSUPP)
178         return UV_EINVAL;
179 #endif
180       return UV__ERR(errno);
181     }
182   }
183 #endif
184 #endif
185 
186   errno = 0;
187   err = bind(tcp->io_watcher.fd, addr, addrlen);
188   if (err == -1 && errno != EADDRINUSE) {
189     if (errno == EAFNOSUPPORT)
190       /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
191        * socket created with AF_INET to an AF_INET6 address or vice versa. */
192       return UV_EINVAL;
193     return UV__ERR(errno);
194   }
195   tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0;
196 
197   tcp->flags |= UV_HANDLE_BOUND;
198   if (addr->sa_family == AF_INET6)
199     tcp->flags |= UV_HANDLE_IPV6;
200 
201   return 0;
202 }
203 
204 
uv__tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,uv_connect_cb cb)205 int uv__tcp_connect(uv_connect_t* req,
206                     uv_tcp_t* handle,
207                     const struct sockaddr* addr,
208                     unsigned int addrlen,
209                     uv_connect_cb cb) {
210   int err;
211   int r;
212 
213   assert(handle->type == UV_TCP);
214 
215   if (handle->connect_req != NULL)
216     return UV_EALREADY;  /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
217 
218   if (handle->delayed_error != 0)
219     goto out;
220 
221   err = maybe_new_socket(handle,
222                          addr->sa_family,
223                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
224   if (err)
225     return err;
226 
227   do {
228     errno = 0;
229     r = connect(uv__stream_fd(handle), addr, addrlen);
230   } while (r == -1 && errno == EINTR);
231 
232   /* We not only check the return value, but also check the errno != 0.
233    * Because in rare cases connect() will return -1 but the errno
234    * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
235    * and actually the tcp three-way handshake is completed.
236    */
237   if (r == -1 && errno != 0) {
238     if (errno == EINPROGRESS)
239       ; /* not an error */
240     else if (errno == ECONNREFUSED
241 #if defined(__OpenBSD__)
242       || errno == EINVAL
243 #endif
244       )
245     /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
246      * next tick to report the error. Solaris and OpenBSD wants to report
247      * immediately -- other unixes want to wait.
248      */
249       handle->delayed_error = UV__ERR(ECONNREFUSED);
250     else
251       return UV__ERR(errno);
252   }
253 
254 out:
255 
256   uv__req_init(handle->loop, req, UV_CONNECT);
257   req->cb = cb;
258   req->handle = (uv_stream_t*) handle;
259   QUEUE_INIT(&req->queue);
260   handle->connect_req = req;
261 
262   uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
263 
264   if (handle->delayed_error)
265     uv__io_feed(handle->loop, &handle->io_watcher);
266 
267   return 0;
268 }
269 
270 
uv_tcp_open(uv_tcp_t * handle,uv_os_sock_t sock)271 int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
272   int err;
273 
274   if (uv__fd_exists(handle->loop, sock))
275     return UV_EEXIST;
276 
277   err = uv__nonblock(sock, 1);
278   if (err)
279     return err;
280 
281   return uv__stream_open((uv_stream_t*)handle,
282                          sock,
283                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
284 }
285 
286 
uv_tcp_getsockname(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)287 int uv_tcp_getsockname(const uv_tcp_t* handle,
288                        struct sockaddr* name,
289                        int* namelen) {
290 
291   if (handle->delayed_error)
292     return handle->delayed_error;
293 
294   return uv__getsockpeername((const uv_handle_t*) handle,
295                              getsockname,
296                              name,
297                              namelen);
298 }
299 
300 
uv_tcp_getpeername(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)301 int uv_tcp_getpeername(const uv_tcp_t* handle,
302                        struct sockaddr* name,
303                        int* namelen) {
304 
305   if (handle->delayed_error)
306     return handle->delayed_error;
307 
308   return uv__getsockpeername((const uv_handle_t*) handle,
309                              getpeername,
310                              name,
311                              namelen);
312 }
313 
314 
uv_tcp_close_reset(uv_tcp_t * handle,uv_close_cb close_cb)315 int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
316   int fd;
317   struct linger l = { 1, 0 };
318 
319   /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
320   if (handle->flags & UV_HANDLE_SHUTTING)
321     return UV_EINVAL;
322 
323   fd = uv__stream_fd(handle);
324   if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) {
325     if (errno == EINVAL) {
326       /* Open Group Specifications Issue 7, 2018 edition states that
327        * EINVAL may mean the socket has been shut down already.
328        * Behavior observed on Solaris, illumos and macOS. */
329       errno = 0;
330     } else {
331       return UV__ERR(errno);
332     }
333   }
334 
335   uv_close((uv_handle_t*) handle, close_cb);
336   return 0;
337 }
338 
339 
uv__tcp_listen(uv_tcp_t * tcp,int backlog,uv_connection_cb cb)340 int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
341   static int single_accept_cached = -1;
342   unsigned long flags;
343   int single_accept;
344   int err;
345 
346   if (tcp->delayed_error)
347     return tcp->delayed_error;
348 
349   single_accept = uv__load_relaxed(&single_accept_cached);
350   if (single_accept == -1) {
351     const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
352     single_accept = (val != NULL && atoi(val) != 0);  /* Off by default. */
353     uv__store_relaxed(&single_accept_cached, single_accept);
354   }
355 
356   if (single_accept)
357     tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
358 
359   flags = 0;
360 #if defined(__MVS__)
361   /* on zOS the listen call does not bind automatically
362      if the socket is unbound. Hence the manual binding to
363      an arbitrary port is required to be done manually
364   */
365   flags |= UV_HANDLE_BOUND;
366 #endif
367   err = maybe_new_socket(tcp, AF_INET, flags);
368   if (err)
369     return err;
370 
371   if (listen(tcp->io_watcher.fd, backlog))
372     return UV__ERR(errno);
373 
374   tcp->connection_cb = cb;
375   tcp->flags |= UV_HANDLE_BOUND;
376 
377   /* Start listening for connections. */
378   tcp->io_watcher.cb = uv__server_io;
379   uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
380 
381   return 0;
382 }
383 
384 
uv__tcp_nodelay(int fd,int on)385 int uv__tcp_nodelay(int fd, int on) {
386   if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
387     return UV__ERR(errno);
388   return 0;
389 }
390 
391 
uv__tcp_keepalive(int fd,int on,unsigned int delay)392 int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
393   if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
394     return UV__ERR(errno);
395 
396 #ifdef TCP_KEEPIDLE
397   if (on) {
398     int intvl = 1;  /*  1 second; same as default on Win32 */
399     int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
400     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
401       return UV__ERR(errno);
402     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
403       return UV__ERR(errno);
404     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
405       return UV__ERR(errno);
406   }
407 #endif
408 
409   /* Solaris/SmartOS, if you don't support keep-alive,
410    * then don't advertise it in your system headers...
411    */
412   /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
413 #if defined(TCP_KEEPALIVE) && !defined(__sun)
414   if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
415     return UV__ERR(errno);
416 #endif
417 
418   return 0;
419 }
420 
421 
uv_tcp_nodelay(uv_tcp_t * handle,int on)422 int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
423   int err;
424 
425   if (uv__stream_fd(handle) != -1) {
426     err = uv__tcp_nodelay(uv__stream_fd(handle), on);
427     if (err)
428       return err;
429   }
430 
431   if (on)
432     handle->flags |= UV_HANDLE_TCP_NODELAY;
433   else
434     handle->flags &= ~UV_HANDLE_TCP_NODELAY;
435 
436   return 0;
437 }
438 
439 
uv_tcp_keepalive(uv_tcp_t * handle,int on,unsigned int delay)440 int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
441   int err;
442 
443   if (uv__stream_fd(handle) != -1) {
444     err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
445     if (err)
446       return err;
447   }
448 
449   if (on)
450     handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
451   else
452     handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
453 
454   /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
455    *      uv_tcp_t with an int that's almost never used...
456    */
457 
458   return 0;
459 }
460 
461 
uv_tcp_simultaneous_accepts(uv_tcp_t * handle,int enable)462 int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
463   if (enable)
464     handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
465   else
466     handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
467   return 0;
468 }
469 
470 
uv__tcp_close(uv_tcp_t * handle)471 void uv__tcp_close(uv_tcp_t* handle) {
472   uv__stream_close((uv_stream_t*)handle);
473 }
474 
475 
uv_socketpair(int type,int protocol,uv_os_sock_t fds[2],int flags0,int flags1)476 int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
477   uv_os_sock_t temp[2];
478   int err;
479 #if defined(__FreeBSD__) || defined(__linux__)
480   int flags;
481 
482   flags = type | SOCK_CLOEXEC;
483   if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE))
484     flags |= SOCK_NONBLOCK;
485 
486   if (socketpair(AF_UNIX, flags, protocol, temp))
487     return UV__ERR(errno);
488 
489   if (flags & UV_FS_O_NONBLOCK) {
490     fds[0] = temp[0];
491     fds[1] = temp[1];
492     return 0;
493   }
494 #else
495   if (socketpair(AF_UNIX, type, protocol, temp))
496     return UV__ERR(errno);
497 
498   if ((err = uv__cloexec(temp[0], 1)))
499     goto fail;
500   if ((err = uv__cloexec(temp[1], 1)))
501     goto fail;
502 #endif
503 
504   if (flags0 & UV_NONBLOCK_PIPE)
505     if ((err = uv__nonblock(temp[0], 1)))
506         goto fail;
507   if (flags1 & UV_NONBLOCK_PIPE)
508     if ((err = uv__nonblock(temp[1], 1)))
509       goto fail;
510 
511   fds[0] = temp[0];
512   fds[1] = temp[1];
513   return 0;
514 
515 fail:
516   uv__close(temp[0]);
517   uv__close(temp[1]);
518   return err;
519 }
520