Rizin
unix-like reverse engineering framework and cli tools
tcp.c File Reference
#include "uv.h"
#include "internal.h"
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

Go to the source code of this file.

Functions

static int new_socket (uv_tcp_t *handle, int domain, unsigned long flags)
 
static int maybe_new_socket (uv_tcp_t *handle, int domain, unsigned long flags)
 
int uv_tcp_init_ex (uv_loop_t *loop, uv_tcp_t *tcp, unsigned int flags)
 
int uv_tcp_init (uv_loop_t *loop, uv_tcp_t *tcp)
 
int uv__tcp_bind (uv_tcp_t *tcp, const struct sockaddr *addr, unsigned int addrlen, unsigned int flags)
 
int uv__tcp_connect (uv_connect_t *req, uv_tcp_t *handle, const struct sockaddr *addr, unsigned int addrlen, uv_connect_cb cb)
 
int uv_tcp_open (uv_tcp_t *handle, uv_os_sock_t sock)
 
int uv_tcp_getsockname (const uv_tcp_t *handle, struct sockaddr *name, int *namelen)
 
int uv_tcp_getpeername (const uv_tcp_t *handle, struct sockaddr *name, int *namelen)
 
int uv_tcp_close_reset (uv_tcp_t *handle, uv_close_cb close_cb)
 
int uv_tcp_listen (uv_tcp_t *tcp, int backlog, uv_connection_cb cb)
 
int uv__tcp_nodelay (int fd, int on)
 
int uv__tcp_keepalive (int fd, int on, unsigned int delay)
 
int uv_tcp_nodelay (uv_tcp_t *handle, int on)
 
int uv_tcp_keepalive (uv_tcp_t *handle, int on, unsigned int delay)
 
int uv_tcp_simultaneous_accepts (uv_tcp_t *handle, int enable)
 
void uv__tcp_close (uv_tcp_t *handle)
 

Function Documentation

◆ maybe_new_socket()

static int maybe_new_socket ( uv_tcp_t handle,
int  domain,
unsigned long  flags 
)
static

Definition at line 67 of file tcp.c.

67  {
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 }
static mcore_handle handle
Definition: asm_mcore.c:8
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd domain
Definition: sflib.h:79
#define UV__ERR(x)
Definition: errno.h:29
return memset(p, 0, total)
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static bind
Definition: sfsocketcall.h:114
unsigned int socklen_t
Definition: sftypes.h:219
#define AF_INET
Definition: sftypes.h:287
#define AF_INET6
Definition: sftypes.h:295
#define AF_UNSPEC
Definition: sftypes.h:283
#define uv__stream_fd(handle)
Definition: internal.h:282
static int new_socket(uv_tcp_t *handle, int domain, unsigned long flags)
Definition: tcp.c:31
@ UV_HANDLE_BOUND
Definition: uv-common.h:91

References AF_INET, AF_INET6, AF_UNSPEC, bind, domain, flags, handle, memset(), new_socket(), UV__ERR, uv__stream_fd, and UV_HANDLE_BOUND.

Referenced by uv__tcp_bind(), uv__tcp_connect(), uv_tcp_init_ex(), and uv_tcp_listen().

◆ new_socket()

static int new_socket ( uv_tcp_t handle,
int  domain,
unsigned long  flags 
)
static

Definition at line 31 of file tcp.c.

31  {
32  struct sockaddr_storage saddr;
33  socklen_t slen;
34  int sockfd;
35  int err;
36 
38  if (err < 0)
39  return err;
40  sockfd = err;
41 
43  if (err) {
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)) {
54  return UV__ERR(errno);
55  }
56 
57  if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
59  return UV__ERR(errno);
60  }
61  }
62 
63  return 0;
64 }
static bool err
Definition: armass.c:435
static sockfd
Definition: sfsocketcall.h:114
@ SOCK_STREAM
Definition: sftypes.h:224
int uv__socket(int domain, int type, int protocol)
Definition: core.c:436
int uv__close(int fd)
Definition: core.c:569
int uv__stream_open(uv_stream_t *, int fd, int flags)
Definition: stream.c:406

References bind, domain, err, flags, handle, memset(), SOCK_STREAM, sockfd, uv__close(), UV__ERR, uv__socket(), uv__stream_fd, uv__stream_open(), and UV_HANDLE_BOUND.

Referenced by maybe_new_socket().

◆ uv__tcp_bind()

int uv__tcp_bind ( uv_tcp_t tcp,
const struct sockaddr addr,
unsigned int  addrlen,
unsigned int  flags 
)

Definition at line 148 of file tcp.c.

151  {
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 }
static const void static count static fd struct stat static buf struct pollfd unsigned static timeout void static offset void static length char static len const struct iovec static count unsigned long static filedes static sched_yield static flags static oldfd static pause unsigned static seconds static protocol struct sockaddr addrlen
Definition: sflib.h:75
#define EOPNOTSUPP
Definition: sftypes.h:155
#define EAFNOSUPPORT
Definition: sftypes.h:157
#define SO_REUSEADDR
Definition: sftypes.h:430
#define EADDRINUSE
Definition: sftypes.h:158
#define SOL_SOCKET
Definition: sftypes.h:427
static int maybe_new_socket(uv_tcp_t *handle, int domain, unsigned long flags)
Definition: tcp.c:67
@ UV_HANDLE_IPV6
Definition: uv-common.h:102
@ UV_TCP_IPV6ONLY
Definition: uv.h:564
#define IPV6_V6ONLY
Definition: winsock.h:46
static int addr
Definition: z80asm.c:58

References addr, addrlen, AF_INET6, bind, EADDRINUSE, EAFNOSUPPORT, EOPNOTSUPP, err, flags, IPV6_V6ONLY, maybe_new_socket(), SO_REUSEADDR, SOL_SOCKET, UV__ERR, UV_HANDLE_BOUND, UV_HANDLE_IPV6, and UV_TCP_IPV6ONLY.

Referenced by uv_tcp_bind().

◆ uv__tcp_close()

void uv__tcp_close ( uv_tcp_t handle)

Definition at line 459 of file tcp.c.

459  {
461 }
void uv__stream_close(uv_stream_t *handle)
Definition: stream.c:1633

References handle, and uv__stream_close().

Referenced by uv_close().

◆ uv__tcp_connect()

int uv__tcp_connect ( uv_connect_t req,
uv_tcp_t handle,
const struct sockaddr addr,
unsigned int  addrlen,
uv_connect_cb  cb 
)

Definition at line 204 of file tcp.c.

208  {
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 
218  addr->sa_family,
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 }
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
assert(limit<=UINT32_MAX/2)
#define QUEUE_INIT(q)
Definition: queue.h:45
#define EINVAL
Definition: sftypes.h:132
#define EINTR
Definition: sftypes.h:114
#define EINPROGRESS
Definition: sftypes.h:175
#define ECONNREFUSED
Definition: sftypes.h:171
void uv__io_start(uv_loop_t *loop, uv__io_t *w, unsigned int events)
Definition: core.c:882
void uv__io_feed(uv_loop_t *loop, uv__io_t *w)
Definition: core.c:952
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:93
@ UV_HANDLE_READABLE
Definition: uv-common.h:92
#define uv__req_init(loop, req, typ)
Definition: uv-common.h:329
static const char * cb[]
Definition: z80_tab.h:176

References addr, addrlen, assert(), cb, ECONNREFUSED, EINPROGRESS, EINTR, EINVAL, err, handle, maybe_new_socket(), NULL, QUEUE_INIT, r, req, UV__ERR, uv__io_feed(), uv__io_start(), uv__req_init, uv__stream_fd, UV_HANDLE_READABLE, and UV_HANDLE_WRITABLE.

Referenced by uv_tcp_connect().

◆ uv__tcp_keepalive()

int uv__tcp_keepalive ( int  fd,
int  on,
unsigned int  delay 
)

Definition at line 380 of file tcp.c.

380  {
381  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
382  return UV__ERR(errno);
383 
384 #ifdef TCP_KEEPIDLE
385  if (on) {
386  int intvl = 1; /* 1 second; same as default on Win32 */
387  int cnt = 10; /* 10 retries; same as hardcoded on Win32 */
388  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
389  return UV__ERR(errno);
390  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
391  return UV__ERR(errno);
392  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
393  return UV__ERR(errno);
394  }
395 #endif
396 
397  /* Solaris/SmartOS, if you don't support keep-alive,
398  * then don't advertise it in your system headers...
399  */
400  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
401 #if defined(TCP_KEEPALIVE) && !defined(__sun)
402  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
403  return UV__ERR(errno);
404 #endif
405 
406  return 0;
407 }
#define SO_KEEPALIVE
Definition: sftypes.h:437
#define TCP_KEEPALIVE
Definition: winsock.h:42
static const z80_opcode fd[]
Definition: z80_tab.h:997

References fd, SO_KEEPALIVE, SOL_SOCKET, TCP_KEEPALIVE, and UV__ERR.

Referenced by uv__stream_open(), uv_tcp_keepalive(), and uv_tcp_set_socket().

◆ uv__tcp_nodelay()

int uv__tcp_nodelay ( int  fd,
int  on 
)

Definition at line 373 of file tcp.c.

373  {
374  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
375  return UV__ERR(errno);
376  return 0;
377 }

References fd, and UV__ERR.

Referenced by uv__stream_open(), uv_tcp_nodelay(), and uv_tcp_set_socket().

◆ uv_tcp_close_reset()

int uv_tcp_close_reset ( uv_tcp_t handle,
uv_close_cb  close_cb 
)

Definition at line 311 of file tcp.c.

311  {
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 
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 }
#define SO_LINGER
Definition: sftypes.h:441
@ UV_HANDLE_SHUTTING
Definition: uv-common.h:84
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: core.c:108

◆ uv_tcp_getpeername()

int uv_tcp_getpeername ( const uv_tcp_t handle,
struct sockaddr name,
int namelen 
)

Definition at line 297 of file tcp.c.

299  {
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 }
Definition: z80asm.h:102
int uv__getsockpeername(const uv_handle_t *handle, uv__peersockfunc func, struct sockaddr *name, int *namelen)
Definition: core.c:1490

Referenced by uv_tcp_open().

◆ uv_tcp_getsockname()

int uv_tcp_getsockname ( const uv_tcp_t handle,
struct sockaddr name,
int namelen 
)

Definition at line 283 of file tcp.c.

285  {
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 }

Referenced by uv_tcp_open().

◆ uv_tcp_init()

int uv_tcp_init ( uv_loop_t loop,
uv_tcp_t tcp 
)

Definition at line 143 of file tcp.c.

143  {
144  return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
145 }
uv_loop_t * loop
Definition: main.c:7
int uv_tcp_init_ex(uv_loop_t *loop, uv_tcp_t *tcp, unsigned int flags)
Definition: tcp.c:114

◆ uv_tcp_init_ex()

int uv_tcp_init_ex ( uv_loop_t loop,
uv_tcp_t tcp,
unsigned int  flags 
)

Definition at line 114 of file tcp.c.

114  {
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 }
#define QUEUE_REMOVE(q)
Definition: queue.h:101
void uv__stream_init(uv_loop_t *loop, uv_stream_t *stream, uv_handle_type type)
Definition: stream.c:85

Referenced by uv_tcp_init().

◆ uv_tcp_keepalive()

int uv_tcp_keepalive ( uv_tcp_t handle,
int  on,
unsigned int  delay 
)

Definition at line 428 of file tcp.c.

428  {
429  int err;
430 
431  if (uv__stream_fd(handle) != -1) {
433  if (err)
434  return err;
435  }
436 
437  if (on)
439  else
440  handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
441 
442  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
443  * uv_tcp_t with an int that's almost never used...
444  */
445 
446  return 0;
447 }
int uv__tcp_keepalive(int fd, int on, unsigned int delay)
Definition: tcp.c:380
@ UV_HANDLE_TCP_KEEPALIVE
Definition: uv-common.h:106

◆ uv_tcp_listen()

int uv_tcp_listen ( uv_tcp_t tcp,
int  backlog,
uv_connection_cb  cb 
)

Definition at line 328 of file tcp.c.

328  {
329  static int single_accept_cached = -1;
330  unsigned long flags;
331  int single_accept;
332  int err;
333 
334  if (tcp->delayed_error)
335  return tcp->delayed_error;
336 
337  single_accept = uv__load_relaxed(&single_accept_cached);
338  if (single_accept == -1) {
339  const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
340  single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */
341  uv__store_relaxed(&single_accept_cached, single_accept);
342  }
343 
344  if (single_accept)
345  tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
346 
347  flags = 0;
348 #if defined(__MVS__)
349  /* on zOS the listen call does not bind automatically
350  if the socket is unbound. Hence the manual binding to
351  an arbitrary port is required to be done manually
352  */
354 #endif
356  if (err)
357  return err;
358 
359  if (listen(tcp->io_watcher.fd, backlog))
360  return UV__ERR(errno);
361 
362  tcp->connection_cb = cb;
363  tcp->flags |= UV_HANDLE_BOUND;
364 
365  /* Start listening for connections. */
366  tcp->io_watcher.cb = uv__server_io;
367  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
368 
369  return 0;
370 }
ut16 val
Definition: armass64_const.h:6
static struct sockaddr static addrlen listen
Definition: sfsocketcall.h:116
char * getenv()
void uv__server_io(uv_loop_t *loop, uv__io_t *w, unsigned int events)
Definition: stream.c:528
@ UV_HANDLE_TCP_SINGLE_ACCEPT
Definition: uv-common.h:107
#define uv__load_relaxed(p)
Definition: uv-common.h:67
#define uv__store_relaxed(p, v)
Definition: uv-common.h:68

◆ uv_tcp_nodelay()

int uv_tcp_nodelay ( uv_tcp_t handle,
int  on 
)

Definition at line 410 of file tcp.c.

410  {
411  int err;
412 
413  if (uv__stream_fd(handle) != -1) {
415  if (err)
416  return err;
417  }
418 
419  if (on)
420  handle->flags |= UV_HANDLE_TCP_NODELAY;
421  else
422  handle->flags &= ~UV_HANDLE_TCP_NODELAY;
423 
424  return 0;
425 }
int uv__tcp_nodelay(int fd, int on)
Definition: tcp.c:373
@ UV_HANDLE_TCP_NODELAY
Definition: uv-common.h:105

◆ uv_tcp_open()

int uv_tcp_open ( uv_tcp_t handle,
uv_os_sock_t  sock 
)

Definition at line 267 of file tcp.c.

267  {
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 
278  sock,
280 }
int uv__fd_exists(uv_loop_t *loop, int fd)
Definition: core.c:965
#define uv__nonblock
Definition: internal.h:170

◆ uv_tcp_simultaneous_accepts()

int uv_tcp_simultaneous_accepts ( uv_tcp_t handle,
int  enable 
)

Definition at line 450 of file tcp.c.

450  {
451  if (enable)
453  else
455  return 0;
456 }