summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix/tcp.c
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2012-06-30 03:27:54 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2012-06-30 03:27:54 +0200
commit7e5aeac28f06ab17bcdfd4fd8ede6a7bcd95dbaf (patch)
treec26943b74e8c634a2f44c5ae9eec0776658dd551 /deps/uv/src/unix/tcp.c
parentb9abb64fbb1fcc7476e617dfd1d8bbd6f06f95f0 (diff)
downloadandroid-node-v8-7e5aeac28f06ab17bcdfd4fd8ede6a7bcd95dbaf.tar.gz
android-node-v8-7e5aeac28f06ab17bcdfd4fd8ede6a7bcd95dbaf.tar.bz2
android-node-v8-7e5aeac28f06ab17bcdfd4fd8ede6a7bcd95dbaf.zip
deps: upgrade libuv to 3b8c0da
Diffstat (limited to 'deps/uv/src/unix/tcp.c')
-rw-r--r--deps/uv/src/unix/tcp.c163
1 files changed, 102 insertions, 61 deletions
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;
}