This source file includes following definitions.
- uv_tcp_init
- maybe_new_socket
- uv__bind
- uv__connect
- uv__tcp_bind
- uv__tcp_bind6
- uv_tcp_open
- uv_tcp_getsockname
- uv_tcp_getpeername
- uv_tcp_listen
- uv__tcp_connect
- uv__tcp_connect6
- uv__tcp_nodelay
- uv__tcp_keepalive
- uv_tcp_nodelay
- uv_tcp_keepalive
- uv_tcp_simultaneous_accepts
- uv__tcp_close
#include "uv.h"
#include "internal.h"
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
return 0;
}
static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
int sockfd;
int err;
if (uv__stream_fd(handle) != -1)
return 0;
err = uv__socket(domain, SOCK_STREAM, 0);
if (err < 0)
return err;
sockfd = err;
err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
if (err) {
close(sockfd);
return err;
}
return 0;
}
static int uv__bind(uv_tcp_t* tcp,
int domain,
struct sockaddr* addr,
int addrsize) {
int err;
int on;
err = maybe_new_socket(tcp, domain, UV_STREAM_READABLE | UV_STREAM_WRITABLE);
if (err)
return err;
on = 1;
if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
return -errno;
errno = 0;
if (bind(tcp->io_watcher.fd, addr, addrsize) && errno != EADDRINUSE)
return -errno;
tcp->delayed_error = -errno;
return 0;
}
static int uv__connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr* addr,
socklen_t addrlen,
uv_connect_cb cb) {
int err;
int r;
assert(handle->type == UV_TCP);
if (handle->connect_req != NULL)
return -EALREADY;
err = maybe_new_socket(handle,
addr->sa_family,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
if (err)
return err;
handle->delayed_error = 0;
do
r = connect(uv__stream_fd(handle), addr, addrlen);
while (r == -1 && errno == EINTR);
if (r == -1) {
if (errno == EINPROGRESS)
;
else if (errno == ECONNREFUSED)
handle->delayed_error = -errno;
else
return -errno;
}
uv__req_init(handle->loop, req, UV_CONNECT);
req->cb = cb;
req->handle = (uv_stream_t*) handle;
QUEUE_INIT(&req->queue);
handle->connect_req = req;
uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
if (handle->delayed_error)
uv__io_feed(handle->loop, &handle->io_watcher);
return 0;
}
int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
return uv__bind(handle,
AF_INET,
(struct sockaddr*)&addr,
sizeof(struct sockaddr_in));
}
int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
return uv__bind(handle,
AF_INET6,
(struct sockaddr*)&addr,
sizeof(struct sockaddr_in6));
}
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
return uv__stream_open((uv_stream_t*)handle,
sock,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
}
int uv_tcp_getsockname(uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
return -EINVAL;
socklen = (socklen_t) *namelen;
if (getsockname(uv__stream_fd(handle), name, &socklen))
return -errno;
*namelen = (int) socklen;
return 0;
}
int uv_tcp_getpeername(uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
return -EINVAL;
socklen = (socklen_t) *namelen;
if (getpeername(uv__stream_fd(handle), name, &socklen))
return -errno;
*namelen = (int) socklen;
return 0;
}
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept = -1;
int err;
if (tcp->delayed_error)
return tcp->delayed_error;
if (single_accept == -1) {
const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
single_accept = (val != NULL && atoi(val) != 0);
}
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
err = maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE);
if (err)
return err;
if (listen(tcp->io_watcher.fd, backlog))
return -errno;
tcp->connection_cb = cb;
tcp->io_watcher.cb = uv__server_io;
uv__io_start(tcp->loop, &tcp->io_watcher, UV__POLLIN);
return 0;
}
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in addr,
uv_connect_cb cb) {
return uv__connect(req, handle, (struct sockaddr*) &addr, sizeof addr, cb);
}
int uv__tcp_connect6(uv_connect_t* req,
uv_tcp_t* handle,
struct sockaddr_in6 addr,
uv_connect_cb cb) {
return uv__connect(req, handle, (struct sockaddr*) &addr, sizeof addr, cb);
}
int uv__tcp_nodelay(int fd, int on) {
return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
}
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
return -errno;
#ifdef TCP_KEEPIDLE
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
return -errno;
#endif
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
return -errno;
#endif
return 0;
}
int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
int err;
if (uv__stream_fd(handle) != -1) {
err = uv__tcp_nodelay(uv__stream_fd(handle), on);
if (err)
return err;
}
if (on)
handle->flags |= UV_TCP_NODELAY;
else
handle->flags &= ~UV_TCP_NODELAY;
return 0;
}
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
int err;
if (uv__stream_fd(handle) != -1) {
err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
if (err)
return err;
}
if (on)
handle->flags |= UV_TCP_KEEPALIVE;
else
handle->flags &= ~UV_TCP_KEEPALIVE;
return 0;
}
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
if (enable)
handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
else
handle->flags |= UV_TCP_SINGLE_ACCEPT;
return 0;
}
void uv__tcp_close(uv_tcp_t* handle) {
uv__stream_close((uv_stream_t*)handle);
}