From 7e5aeac28f06ab17bcdfd4fd8ede6a7bcd95dbaf Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 30 Jun 2012 03:27:54 +0200 Subject: deps: upgrade libuv to 3b8c0da --- deps/uv/src/unix/tcp.c | 163 +++++++++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 61 deletions(-) (limited to 'deps/uv/src/unix/tcp.c') diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 07ad2d9eca..1aeba0efcf 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -34,6 +34,26 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { } +static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) { + int sockfd; + + if (handle->fd != -1) + return 0; + + sockfd = uv__socket(domain, SOCK_STREAM, 0); + + if (sockfd == -1) + return uv__set_sys_error(handle->loop, errno); + + if (uv__stream_open((uv_stream_t*)handle, sockfd, flags)) { + close(sockfd); + return -1; + } + + return 0; +} + + static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, @@ -44,23 +64,8 @@ static int uv__bind(uv_tcp_t* tcp, saved_errno = errno; status = -1; - if (tcp->fd < 0) { - if ((tcp->fd = uv__socket(domain, SOCK_STREAM, 0)) == -1) { - uv__set_sys_error(tcp->loop, errno); - goto out; - } - - if (uv__stream_open((uv_stream_t*)tcp, - tcp->fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE)) { - close(tcp->fd); - tcp->fd = -1; - status = -2; - goto out; - } - } - - assert(tcp->fd >= 0); + if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE)) + return -1; tcp->delayed_error = 0; if (bind(tcp->fd, addr, addrsize) == -1) { @@ -79,6 +84,67 @@ out: } +static int uv__connect(uv_connect_t* req, + uv_tcp_t* handle, + struct sockaddr* addr, + socklen_t addrlen, + uv_connect_cb cb) { + int r; + + assert(handle->type == UV_TCP); + + if (handle->connect_req) + return uv__set_sys_error(handle->loop, EALREADY); + + if (maybe_new_socket(handle, + addr->sa_family, + UV_STREAM_READABLE|UV_STREAM_WRITABLE)) { + return -1; + } + + handle->delayed_error = 0; + + do + r = connect(handle->fd, addr, addrlen); + while (r == -1 && errno == EINTR); + + if (r == -1) { + if (errno == EINPROGRESS) { + /* Not an error. However, we need to keep the event loop from spinning + * while the connection is in progress. Artificially start the handle + * and stop it again in uv__stream_connect() in stream.c. Yes, it's a + * hack but there's no good alternative, the v0.8 ABI is frozen. + */ + if (!uv__is_active(handle)) { + handle->flags |= UV_TCP_CONNECTING; + uv__handle_start(handle); + } + } + else if (errno == ECONNREFUSED) + /* If we get a ECONNREFUSED wait until the next tick to report the + * error. Solaris wants to report immediately--other unixes want to + * wait. + */ + handle->delayed_error = errno; + else + return uv__set_sys_error(handle->loop, errno); + } + + uv__req_init(handle->loop, req, UV_CONNECT); + req->cb = cb; + req->handle = (uv_stream_t*) handle; + ngx_queue_init(&req->queue); + handle->connect_req = req; + + uv__io_start(handle->loop, &handle->write_watcher); + + if (handle->delayed_error) + uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE); + + return 0; +} + + int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) { return uv__bind(handle, AF_INET, @@ -170,33 +236,14 @@ out: int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { - int r; + if (tcp->delayed_error) + return uv__set_sys_error(tcp->loop, tcp->delayed_error); - if (tcp->delayed_error) { - uv__set_sys_error(tcp->loop, tcp->delayed_error); + if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE)) return -1; - } - - if (tcp->fd < 0) { - if ((tcp->fd = uv__socket(AF_INET, SOCK_STREAM, 0)) == -1) { - uv__set_sys_error(tcp->loop, errno); - return -1; - } - - if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_STREAM_READABLE)) { - close(tcp->fd); - tcp->fd = -1; - return -1; - } - } - assert(tcp->fd >= 0); - - r = listen(tcp->fd, backlog); - if (r < 0) { - uv__set_sys_error(tcp->loop, errno); - return -1; - } + if (listen(tcp->fd, backlog)) + return uv__set_sys_error(tcp->loop, errno); tcp->connection_cb = cb; @@ -209,37 +256,31 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - struct sockaddr_in address, - uv_connect_cb cb) { - int saved_errno = errno; + uv_tcp_t* handle, + struct sockaddr_in addr, + uv_connect_cb cb) { + int saved_errno; int status; - status = uv__connect(req, - (uv_stream_t*)handle, - (struct sockaddr*)&address, - sizeof address, - cb); - + saved_errno = errno; + status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb); errno = saved_errno; + return status; } int uv__tcp_connect6(uv_connect_t* req, - uv_tcp_t* handle, - struct sockaddr_in6 address, - uv_connect_cb cb) { - int saved_errno = errno; + uv_tcp_t* handle, + struct sockaddr_in6 addr, + uv_connect_cb cb) { + int saved_errno; int status; - status = uv__connect(req, - (uv_stream_t*)handle, - (struct sockaddr*)&address, - sizeof address, - cb); - + saved_errno = errno; + status = uv__connect(req, handle, (struct sockaddr*)&addr, sizeof addr, cb); errno = saved_errno; + return status; } -- cgit v1.2.3