uv_prepare_t* next_prepare_handle; \
uv_check_t* next_check_handle; \
uv_idle_t* next_idle_handle; \
- ares_channel ares_channel; \
+ ares_channel ares_chan; \
int ares_active_sockets; \
uv_timer_t ares_polling_timer; \
/* Last error code */ \
int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
+int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
+int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
/*
* uv_tcp_connect, uv_tcp_connect6
};
-int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen);
-
-
/*
* UDP support.
*/
* 0 on success, -1 on error.
*/
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);
+int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen);
/*
* Send data. If the socket has not previously been bound with `uv_udp_bind`
}
-int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen) {
- socklen_t socklen;
- int saved_errno;
-
- /* Don't clobber errno. */
- saved_errno = errno;
-
- /* sizeof(socklen_t) != sizeof(int) on some systems. */
- socklen = (socklen_t)*namelen;
-
- if (getsockname(handle->fd, name, &socklen) == -1) {
- uv_err_new(handle->loop, errno);
- } else {
- *namelen = (int)socklen;
- }
-
- errno = saved_errno;
- return 0;
-}
-
-
void uv_ref(uv_loop_t* loop) {
ev_ref(loop->ev);
}
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
/* TODO Expose callback to user to handle fatal error like V8 does. */
case ECONNREFUSED: return UV_ECONNREFUSED;
case EADDRINUSE: return UV_EADDRINUSE;
case EADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
+ case ENOTCONN: return UV_ENOTCONN;
default: return UV_UNKNOWN;
}
}
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/uio.h>
}
+int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ socklen_t socklen;
+ int saved_errno;
+ int rv = 0;
+
+ /* Don't clobber errno. */
+ saved_errno = errno;
+
+ if (handle->delayed_error) {
+ uv_err_new(handle->loop, handle->delayed_error);
+ rv = -1;
+ goto out;
+ }
+
+ if (handle->fd < 0) {
+ uv_err_new(handle->loop, EINVAL);
+ rv = -1;
+ goto out;
+ }
+
+ /* sizeof(socklen_t) != sizeof(int) on some systems. */
+ socklen = (socklen_t)*namelen;
+
+ if (getsockname(handle->fd, name, &socklen) == -1) {
+ uv_err_new(handle->loop, errno);
+ rv = -1;
+ } else {
+ *namelen = (int)socklen;
+ }
+
+out:
+ errno = saved_errno;
+ return rv;
+}
+
+
+int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ socklen_t socklen;
+ int saved_errno;
+ int rv = 0;
+
+ /* Don't clobber errno. */
+ saved_errno = errno;
+
+ if (handle->delayed_error) {
+ uv_err_new(handle->loop, handle->delayed_error);
+ rv = -1;
+ goto out;
+ }
+
+ if (handle->fd < 0) {
+ uv_err_new(handle->loop, EINVAL);
+ rv = -1;
+ goto out;
+ }
+
+ /* sizeof(socklen_t) != sizeof(int) on some systems. */
+ socklen = (socklen_t)*namelen;
+
+ if (getpeername(handle->fd, name, &socklen) == -1) {
+ uv_err_new(handle->loop, errno);
+ rv = -1;
+ } else {
+ *namelen = (int)socklen;
+ }
+
+out:
+ errno = saved_errno;
+ return rv;
+}
+
+
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int r;
}
+int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ socklen_t socklen;
+ int saved_errno;
+ int rv = 0;
+
+ /* Don't clobber errno. */
+ saved_errno = errno;
+
+ if (handle->fd < 0) {
+ uv_err_new(handle->loop, EINVAL);
+ rv = -1;
+ goto out;
+ }
+
+ /* sizeof(socklen_t) != sizeof(int) on some systems. */
+ socklen = (socklen_t)*namelen;
+
+ if (getsockname(handle->fd, name, &socklen) == -1) {
+ uv_err_new(handle->loop, errno);
+ rv = -1;
+ } else {
+ *namelen = (int)socklen;
+ }
+
+out:
+ errno = saved_errno;
+ return rv;
+}
+
+
int uv_udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
/* periodically call ares to check for timeouts */
static void uv_ares_poll(uv_timer_t* handle, int status) {
uv_loop_t* loop = handle->loop;
- if (loop->ares_channel != NULL && loop->ares_active_sockets > 0) {
- ares_process_fd(loop->ares_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+ if (loop->ares_chan != NULL && loop->ares_active_sockets > 0) {
+ ares_process_fd(loop->ares_chan, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
}
}
/* called via uv_poll when ares completion port signaled */
void uv_process_ares_event_req(uv_loop_t* loop, uv_ares_action_t* handle,
uv_req_t* req) {
- ares_process_fd(loop->ares_channel,
+ ares_process_fd(loop->ares_chan,
handle->read ? handle->sock : INVALID_SOCKET,
handle->write ? handle->sock : INVALID_SOCKET);
int rc;
/* only allow single init at a time */
- if (loop->ares_channel != NULL) {
+ if (loop->ares_chan != NULL) {
return UV_EALREADY;
}
/* if success, save channel */
if (rc == ARES_SUCCESS) {
- loop->ares_channel = *channelptr;
+ loop->ares_chan = *channelptr;
}
return rc;
/* release memory */
void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
/* only allow destroy if did init */
- if (loop->ares_channel != NULL) {
+ if (loop->ares_chan != NULL) {
ares_destroy(channel);
- loop->ares_channel = NULL;
+ loop->ares_chan = NULL;
}
}
loop->next_idle_handle = NULL;
loop->ares_active_sockets = 0;
- loop->ares_channel = NULL;
+ loop->ares_chan = NULL;
loop->last_error = uv_ok_;
}
case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH;
case WSAENETUNREACH: return UV_ENETUNREACH;
case ERROR_OUTOFMEMORY: return UV_ENOMEM;
+ case ERROR_NOT_CONNECTED: return UV_ENOTCONN;
+ case WSAENOTCONN: return UV_ENOTCONN;
case ERROR_NOT_SUPPORTED: return UV_ENOTSUP;
case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL;
case ERROR_INVALID_FLAGS: return UV_EBADF;
}
-int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen) {
- uv_loop_t* loop = handle->loop;
-
- switch (handle->type) {
- case UV_TCP:
- return uv_tcp_getsockname(loop, (uv_tcp_t*) handle, name, namelen);
-
- case UV_UDP:
- return uv_udp_getsockname(loop, (uv_udp_t*) handle, name, namelen);
-
- default:
- uv_set_sys_error(loop, WSAENOTSOCK);
- return -1;
- }
-}
-
-
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_tcp_t* tcp;
uv_pipe_t* pipe;
uv_read_cb read_cb);
int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
uv_buf_t bufs[], int bufcnt, uv_write_cb cb);
-int uv_tcp_getsockname(uv_loop_t* loop, uv_tcp_t* handle,
- struct sockaddr* name, int* namelen);
void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);
void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
/*
* UDP
*/
-int uv_udp_getsockname(uv_loop_t* loop, uv_udp_t* handle,
- struct sockaddr* name, int* namelen);
-
void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
uv_udp_send_t* req);
rv = -1;
} else {
uv_connection_init((uv_stream_t*) client);
+ /* AcceptEx() implicitly binds the accepted socket. */
+ client->flags |= UV_HANDLE_BOUND;
}
/* Prepare the req to pick up a new connection */
}
-int uv_tcp_getsockname(uv_loop_t* loop, uv_tcp_t* handle,
- struct sockaddr* name, int* namelen) {
+int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ uv_loop_t* loop = handle->loop;
int result;
- if (handle->flags & UV_HANDLE_SHUTTING) {
- uv_set_sys_error(loop, WSAESHUTDOWN);
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ uv_set_sys_error(loop, WSAEINVAL);
+ return -1;
+ }
+
+ if (handle->flags & UV_HANDLE_BIND_ERROR) {
+ loop->last_error = handle->bind_error;
return -1;
}
}
+int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ uv_loop_t* loop = handle->loop;
+ int result;
+
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ uv_set_sys_error(loop, WSAEINVAL);
+ return -1;
+ }
+
+ if (handle->flags & UV_HANDLE_BIND_ERROR) {
+ loop->last_error = handle->bind_error;
+ return -1;
+ }
+
+ result = getpeername(handle->socket, name, namelen);
+ if (result != 0) {
+ uv_set_sys_error(loop, WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
+
+
int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
uv_buf_t bufs[], int bufcnt, uv_write_cb cb) {
int result;
static unsigned int active_udp_streams = 0;
-int uv_udp_getsockname(uv_loop_t* loop, uv_udp_t* handle,
- struct sockaddr* name, int* namelen) {
+int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
+ int* namelen) {
+ uv_loop_t* loop = handle->loop;
int result;
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ uv_set_sys_error(loop, WSAEINVAL);
+ return -1;
+ }
+
result = getsockname(handle->socket, name, namelen);
if (result != 0) {
uv_set_sys_error(loop, WSAGetLastError());
#include <stdlib.h>
#include <string.h>
+static const int server_port = TEST_PORT;
+/* Will be updated right after making the uv_connect_call */
+static int connect_port = -1;
static int getsocknamecount = 0;
+static int getpeernamecount = 0;
static uv_loop_t* loop;
static uv_tcp_t tcp;
}
+static void check_sockname(struct sockaddr* addr, const char* compare_ip,
+ int compare_port, const char* context) {
+ struct sockaddr_in check_addr = *(struct sockaddr_in*) addr;
+ struct sockaddr_in compare_addr = uv_ip4_addr(compare_ip, compare_port);
+ char check_ip[17];
+ int r;
+
+ /* Both adresses should be ipv4 */
+ ASSERT(check_addr.sin_family == AF_INET);
+ ASSERT(compare_addr.sin_family == AF_INET);
+
+ /* Check if the ip matches */
+ ASSERT(memcmp(&check_addr.sin_addr,
+ &compare_addr.sin_addr,
+ sizeof compare_addr.sin_addr) == 0);
+
+ /* Check if the port matches. If port == 0 anything goes. */
+ ASSERT(compare_port == 0 || check_addr.sin_port == compare_addr.sin_port);
+
+ r = uv_ip4_name(&check_addr, (char*) check_ip, sizeof check_ip);
+ ASSERT(r == 0);
+
+ printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port));
+}
+
+
static void on_connection(uv_stream_t* server, int status) {
- struct sockaddr sockname;
- int namelen = sizeof(sockname);
+ struct sockaddr sockname, peername;
+ int namelen;
uv_handle_t* handle;
int r;
r = uv_accept(server, (uv_stream_t*)handle);
ASSERT(r == 0);
- status = uv_getsockname(handle, &sockname, &namelen);
- if (status != 0) {
- fprintf(stderr, "uv_getsockname error (accepted) %d\n",
- uv_last_error(loop).code);
- }
- ASSERT(status == 0);
-
+ namelen = sizeof sockname;
+ r = uv_tcp_getsockname((uv_tcp_t*) handle, &sockname, &namelen);
+ ASSERT(r == 0);
+ check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket");
getsocknamecount++;
+ namelen = sizeof peername;
+ r = uv_tcp_getpeername((uv_tcp_t*) handle, &peername, &namelen);
+ ASSERT(r == 0);
+ check_sockname(&peername, "127.0.0.1", connect_port, "accepted socket peer");
+ getpeernamecount++;
+
r = uv_read_start((uv_stream_t*)handle, alloc, after_read);
ASSERT(r == 0);
}
static void on_connect(uv_connect_t* req, int status) {
- struct sockaddr sockname;
- int namelen = sizeof(sockname);
- int r;
+ struct sockaddr sockname, peername;
+ int r, namelen;
ASSERT(status == 0);
- r = uv_getsockname((uv_handle_t*)&tcp, &sockname, &namelen);
- if (r != 0) {
- fprintf(stderr, "uv_getsockname error (connector) %d\n",
- uv_last_error(loop).code);
- }
+ namelen = sizeof sockname;
+ r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen);
ASSERT(r == 0);
-
+ check_sockname(&sockname, "127.0.0.1", 0, "connected socket");
getsocknamecount++;
+ namelen = sizeof peername;
+ r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen);
+ ASSERT(r == 0);
+ check_sockname(&peername, "127.0.0.1", server_port, "connected socket peer");
+ getpeernamecount++;
+
uv_close((uv_handle_t*)&tcp, NULL);
}
-static int tcp_listener(int port) {
- struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
- struct sockaddr sockname;
- int namelen = sizeof(sockname);
- char ip[20];
+static int tcp_listener() {
+ struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port);
+ struct sockaddr sockname, peername;
+ int namelen;
int r;
r = uv_tcp_init(loop, &tcpServer);
}
memset(&sockname, -1, sizeof sockname);
-
- r = uv_getsockname((uv_handle_t*)&tcpServer, &sockname, &namelen);
- if (r != 0) {
- fprintf(stderr, "uv_getsockname error (listening) %d\n",
- uv_last_error(loop).code);
- }
+ namelen = sizeof sockname;
+ r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen);
ASSERT(r == 0);
-
- r = uv_ip4_name((struct sockaddr_in*)&sockname, ip, 20);
- ASSERT(r == 0);
- ASSERT(ip[0] == '0');
- ASSERT(ip[1] == '.');
- ASSERT(ip[2] == '0');
- printf("sockname = %s\n", ip);
-
+ check_sockname(&sockname, "0.0.0.0", server_port, "server socket");
getsocknamecount++;
+ namelen = sizeof sockname;
+ r = uv_tcp_getpeername(&tcpServer, &peername, &namelen);
+ ASSERT(r == -1);
+ ASSERT(uv_last_error(loop).code == UV_ENOTCONN);
+ getpeernamecount++;
+
return 0;
}
static void tcp_connector() {
- int r;
- struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
+ struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", server_port);
+ struct sockaddr sockname;
+ int r, namelen;
r = uv_tcp_init(loop, &tcp);
tcp.data = &connect_req;
r = uv_tcp_connect(&connect_req, &tcp, server_addr, on_connect);
ASSERT(!r);
+
+ /* Fetch the actual port used by the connecting socket. */
+ namelen = sizeof sockname;
+ r = uv_tcp_getsockname(&tcp, &sockname, &namelen);
+ ASSERT(!r);
+ ASSERT(sockname.sa_family == AF_INET);
+ connect_port = ntohs(((struct sockaddr_in*) &sockname)->sin_port);
+ ASSERT(connect_port > 0);
}
struct sockaddr* addr,
unsigned flags) {
struct sockaddr sockname;
- char ip[20];
int namelen;
int r;
return;
}
+ memset(&sockname, -1, sizeof sockname);
namelen = sizeof(sockname);
- r = uv_getsockname((uv_handle_t*)&udp, &sockname, &namelen);
- if (r != 0) {
- fprintf(stderr, "uv_getsockname error (connector) %d\n", uv_last_error(loop).code);
- }
+ r = uv_udp_getsockname(&udp, &sockname, &namelen);
ASSERT(r == 0);
-
- r = uv_ip4_name((struct sockaddr_in*)&sockname, ip, 20);
- ASSERT(r == 0);
- printf("sockname = %s\n", ip);
-
+ check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket");
getsocknamecount++;
uv_close((uv_handle_t*) &udp, NULL);
}
-static int udp_listener(int port) {
- struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
+static int udp_listener() {
+ struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port);
struct sockaddr sockname;
- int namelen = sizeof(sockname);
- char ip[20];
+ int namelen;
int r;
r = uv_udp_init(loop, &udpServer);
}
memset(&sockname, -1, sizeof sockname);
-
- r = uv_getsockname((uv_handle_t*)&udpServer, &sockname, &namelen);
- if (r != 0) {
- fprintf(stderr, "uv_getsockname error (listening) %d\n", uv_last_error(loop).code);
- }
+ namelen = sizeof sockname;
+ r = uv_udp_getsockname(&udpServer, &sockname, &namelen);
ASSERT(r == 0);
-
- r = uv_ip4_name((struct sockaddr_in*)&sockname, ip, 20);
- ASSERT(r == 0);
- ASSERT(ip[0] == '0');
- ASSERT(ip[1] == '.');
- ASSERT(ip[2] == '0');
- printf("sockname = %s\n", ip);
-
+ check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket");
getsocknamecount++;
r = uv_udp_recv_start(&udpServer, alloc, udp_recv);
ASSERT(!r);
buf = uv_buf_init("PING", 4);
- server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
+ server_addr = uv_ip4_addr("127.0.0.1", server_port);
r = uv_udp_send(&send_req, &udp, &buf, 1, server_addr, udp_send);
ASSERT(!r);
uv_init();
loop = uv_default_loop();
- if (tcp_listener(TEST_PORT))
+ if (tcp_listener())
return 1;
tcp_connector();
uv_run(loop);
ASSERT(getsocknamecount == 3);
+ ASSERT(getpeernamecount == 3);
return 0;
}
uv_init();
loop = uv_default_loop();
- if (udp_listener(TEST_PORT))
+ if (udp_listener())
return 1;
udp_sender();