xref: /netbsd-src/external/mit/libuv/dist/src/unix/tcp.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
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 
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 
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 
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 
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 
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   if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
188     if (errno == EAFNOSUPPORT)
189       /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
190        * socket created with AF_INET to an AF_INET6 address or vice versa. */
191       return UV_EINVAL;
192     return UV__ERR(errno);
193   }
194   tcp->delayed_error = UV__ERR(errno);
195 
196   tcp->flags |= UV_HANDLE_BOUND;
197   if (addr->sa_family == AF_INET6)
198     tcp->flags |= UV_HANDLE_IPV6;
199 
200   return 0;
201 }
202 
203 
204 int uv__tcp_connect(uv_connect_t* req,
205                     uv_tcp_t* handle,
206                     const struct sockaddr* addr,
207                     unsigned int addrlen,
208                     uv_connect_cb cb) {
209   int err;
210   int r;
211 
212   assert(handle->type == UV_TCP);
213 
214   if (handle->connect_req != NULL)
215     return UV_EALREADY;  /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
216 
217   err = maybe_new_socket(handle,
218                          addr->sa_family,
219                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
220   if (err)
221     return err;
222 
223   handle->delayed_error = 0;
224 
225   do {
226     errno = 0;
227     r = connect(uv__stream_fd(handle), addr, addrlen);
228   } while (r == -1 && errno == EINTR);
229 
230   /* We not only check the return value, but also check the errno != 0.
231    * Because in rare cases connect() will return -1 but the errno
232    * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
233    * and actually the tcp three-way handshake is completed.
234    */
235   if (r == -1 && errno != 0) {
236     if (errno == EINPROGRESS)
237       ; /* not an error */
238     else if (errno == ECONNREFUSED
239 #if defined(__OpenBSD__)
240       || errno == EINVAL
241 #endif
242       )
243     /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
244      * next tick to report the error. Solaris and OpenBSD wants to report
245      * immediately -- other unixes want to wait.
246      */
247       handle->delayed_error = UV__ERR(ECONNREFUSED);
248     else
249       return UV__ERR(errno);
250   }
251 
252   uv__req_init(handle->loop, req, UV_CONNECT);
253   req->cb = cb;
254   req->handle = (uv_stream_t*) handle;
255   QUEUE_INIT(&req->queue);
256   handle->connect_req = req;
257 
258   uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
259 
260   if (handle->delayed_error)
261     uv__io_feed(handle->loop, &handle->io_watcher);
262 
263   return 0;
264 }
265 
266 
267 int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
268   int err;
269 
270   if (uv__fd_exists(handle->loop, sock))
271     return UV_EEXIST;
272 
273   err = uv__nonblock(sock, 1);
274   if (err)
275     return err;
276 
277   return uv__stream_open((uv_stream_t*)handle,
278                          sock,
279                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
280 }
281 
282 
283 int uv_tcp_getsockname(const uv_tcp_t* handle,
284                        struct sockaddr* name,
285                        int* namelen) {
286 
287   if (handle->delayed_error)
288     return handle->delayed_error;
289 
290   return uv__getsockpeername((const uv_handle_t*) handle,
291                              getsockname,
292                              name,
293                              namelen);
294 }
295 
296 
297 int uv_tcp_getpeername(const uv_tcp_t* handle,
298                        struct sockaddr* name,
299                        int* namelen) {
300 
301   if (handle->delayed_error)
302     return handle->delayed_error;
303 
304   return uv__getsockpeername((const uv_handle_t*) handle,
305                              getpeername,
306                              name,
307                              namelen);
308 }
309 
310 
311 int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
312   int fd;
313   struct linger l = { 1, 0 };
314 
315   /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
316   if (handle->flags & UV_HANDLE_SHUTTING)
317     return UV_EINVAL;
318 
319   fd = uv__stream_fd(handle);
320   if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
321     return UV__ERR(errno);
322 
323   uv_close((uv_handle_t*) handle, close_cb);
324   return 0;
325 }
326 
327 
328 int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
329   static int single_accept = -1;
330   unsigned long flags;
331   int err;
332 
333   if (tcp->delayed_error)
334     return tcp->delayed_error;
335 
336   if (single_accept == -1) {
337     const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
338     single_accept = (val != NULL && atoi(val) != 0);  /* Off by default. */
339   }
340 
341   if (single_accept)
342     tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
343 
344   flags = 0;
345 #if defined(__MVS__)
346   /* on zOS the listen call does not bind automatically
347      if the socket is unbound. Hence the manual binding to
348      an arbitrary port is required to be done manually
349   */
350   flags |= UV_HANDLE_BOUND;
351 #endif
352   err = maybe_new_socket(tcp, AF_INET, flags);
353   if (err)
354     return err;
355 
356   if (listen(tcp->io_watcher.fd, backlog))
357     return UV__ERR(errno);
358 
359   tcp->connection_cb = cb;
360   tcp->flags |= UV_HANDLE_BOUND;
361 
362   /* Start listening for connections. */
363   tcp->io_watcher.cb = uv__server_io;
364   uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
365 
366   return 0;
367 }
368 
369 
370 int uv__tcp_nodelay(int fd, int on) {
371   if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
372     return UV__ERR(errno);
373   return 0;
374 }
375 
376 
377 int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
378   if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
379     return UV__ERR(errno);
380 
381 #ifdef TCP_KEEPIDLE
382   if (on) {
383     int intvl = 1;  /*  1 second; same as default on Win32 */
384     int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
385     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
386       return UV__ERR(errno);
387     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
388       return UV__ERR(errno);
389     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
390       return UV__ERR(errno);
391   }
392 #endif
393 
394   /* Solaris/SmartOS, if you don't support keep-alive,
395    * then don't advertise it in your system headers...
396    */
397   /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
398 #if defined(TCP_KEEPALIVE) && !defined(__sun)
399   if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
400     return UV__ERR(errno);
401 #endif
402 
403   return 0;
404 }
405 
406 
407 int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
408   int err;
409 
410   if (uv__stream_fd(handle) != -1) {
411     err = uv__tcp_nodelay(uv__stream_fd(handle), on);
412     if (err)
413       return err;
414   }
415 
416   if (on)
417     handle->flags |= UV_HANDLE_TCP_NODELAY;
418   else
419     handle->flags &= ~UV_HANDLE_TCP_NODELAY;
420 
421   return 0;
422 }
423 
424 
425 int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
426   int err;
427 
428   if (uv__stream_fd(handle) != -1) {
429     err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
430     if (err)
431       return err;
432   }
433 
434   if (on)
435     handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
436   else
437     handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
438 
439   /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
440    *      uv_tcp_t with an int that's almost never used...
441    */
442 
443   return 0;
444 }
445 
446 
447 int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
448   if (enable)
449     handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
450   else
451     handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
452   return 0;
453 }
454 
455 
456 void uv__tcp_close(uv_tcp_t* handle) {
457   uv__stream_close((uv_stream_t*)handle);
458 }
459