From 6b32ebc54f7427c074419afa36e054df4ee9d493 Mon Sep 17 00:00:00 2001 From: Henry Rawas Date: Mon, 11 Jul 2011 13:45:16 -0700 Subject: [PATCH] uv_getsockname --- include/uv.h | 2 + src/uv-unix.c | 5 ++ src/uv-win.c | 23 ++++++ test/test-getsockname.c | 178 ++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 3 + 5 files changed, 211 insertions(+) create mode 100644 test/test-getsockname.c diff --git a/include/uv.h b/include/uv.h index f75c4be2..d86c9fef 100644 --- a/include/uv.h +++ b/include/uv.h @@ -288,6 +288,8 @@ int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6); int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); +int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); + /* * A subclass of uv_stream_t representing a pipe stream or pipe server. diff --git a/src/uv-unix.c b/src/uv-unix.c index 140f0935..9c791bde 100644 --- a/src/uv-unix.c +++ b/src/uv-unix.c @@ -961,6 +961,11 @@ int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6 addr) { } +int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) { + assert(0 && "implement me"); +} + + static size_t uv__buf_count(uv_buf_t bufs[], int bufcnt) { size_t total = 0; int i; diff --git a/src/uv-win.c b/src/uv-win.c index 34d9cf27..f432778e 100644 --- a/src/uv-win.c +++ b/src/uv-win.c @@ -1382,6 +1382,29 @@ int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6 addr) { } +int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) { + int result; + + if (!(handle->flags & UV_HANDLE_CONNECTION)) { + uv_set_sys_error(WSAEINVAL); + return -1; + } + + if (handle->flags & UV_HANDLE_SHUTTING) { + uv_set_sys_error(WSAESHUTDOWN); + return -1; + } + + result = getsockname(handle->socket, name, namelen); + if (result != 0) { + uv_set_sys_error(WSAGetLastError()); + return -1; + } + + return 0; +} + + static size_t uv_count_bufs(uv_buf_t bufs[], int count) { size_t bytes = 0; int i; diff --git a/test/test-getsockname.c b/test/test-getsockname.c new file mode 100644 index 00000000..9d9c0ba0 --- /dev/null +++ b/test/test-getsockname.c @@ -0,0 +1,178 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + +static int getsocknamecount = 0; + + +static uv_tcp_t tcp; +static uv_req_t connect_req; +static uv_tcp_t tcpServer; + + +static uv_buf_t alloc(uv_stream_t* handle, size_t suggested_size) { + uv_buf_t buf; + buf.base = (char*) malloc(suggested_size); + buf.len = suggested_size; + return buf; +} + + +static void on_close(uv_handle_t* peer) { + free(peer); + uv_close((uv_handle_t*)&tcpServer, NULL); +} + + +static void after_shutdown(uv_req_t* req, int status) { + uv_close(req->handle, on_close); + free(req); +} + + +static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { + int i; + uv_req_t* req; + + if (buf.base) { + free(buf.base); + } + + req = (uv_req_t*) malloc(sizeof *req); + uv_req_init(req, (uv_handle_t*)handle, (void *(*)(void *))after_shutdown); + uv_shutdown(req); + +} + +static void on_connection(uv_handle_t* server, int status) { + struct sockaddr sockname; + int namelen = sizeof(sockname); + uv_handle_t* handle; + int r; + + if (status != 0) { + fprintf(stderr, "Connect error %d\n", uv_last_error().code); + } + ASSERT(status == 0); + + handle = (uv_handle_t*) malloc(sizeof(uv_tcp_t)); + ASSERT(handle != NULL); + + uv_tcp_init((uv_tcp_t*)handle); + + /* associate server with stream */ + handle->data = server; + + r = uv_accept(server, (uv_stream_t*)handle); + ASSERT(r == 0); + + status = uv_getsockname((uv_tcp_t*)handle, &sockname, &namelen); + if (status != 0) { + fprintf(stderr, "uv_getsockname error (listener) %d\n", uv_last_error().code); + } + ASSERT(status == 0); + + getsocknamecount++; + + r = uv_read_start((uv_stream_t*)handle, alloc, after_read); + ASSERT(r == 0); + +} + + +static void* on_connect(void* req) { + struct sockaddr sockname; + int namelen = sizeof(sockname); + int status; + + status = uv_getsockname(&tcp, &sockname, &namelen); + if (status != 0) { + fprintf(stderr, "uv_getsockname error (connector) %d\n", uv_last_error().code); + } + ASSERT(status == 0); + + getsocknamecount++; + + 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); + int r; + + r = uv_tcp_init(&tcpServer); + if (r) { + fprintf(stderr, "Socket creation error\n"); + return 1; + } + + r = uv_tcp_bind(&tcpServer, addr); + if (r) { + fprintf(stderr, "Bind error\n"); + return 1; + } + + r = uv_tcp_listen(&tcpServer, 128, on_connection); + if (r) { + fprintf(stderr, "Listen error\n"); + return 1; + } + + return 0; +} + + +static void tcp_connector() { + int r; + struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); + + r = uv_tcp_init(&tcp); + tcp.data = &connect_req; + ASSERT(!r); + + uv_req_init(&connect_req, (uv_handle_t*)(&tcp), on_connect); + + r = uv_tcp_connect(&connect_req, server_addr); + ASSERT(!r); +} + + +TEST_IMPL(getsockname) { + uv_init(); + + if (tcp_listener(TEST_PORT)) + return 1; + + tcp_connector(); + + uv_run(); + + ASSERT(getsocknamecount == 2); + + return 0; +} + diff --git a/test/test-list.h b/test/test-list.h index 0cee34f3..919d7b76 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -53,6 +53,7 @@ TEST_DECLARE (hrtime) TEST_DECLARE (getaddrinfo_basic) TEST_DECLARE (getaddrinfo_concurrent) TEST_DECLARE (gethostbyname) +TEST_DECLARE (getsockname) TEST_DECLARE (fail_always) TEST_DECLARE (pass_always) HELPER_DECLARE (tcp4_echo_server) @@ -121,6 +122,8 @@ TASK_LIST_START TEST_ENTRY (gethostbyname) TEST_HELPER (gethostbyname, tcp4_echo_server) + TEST_ENTRY (getsockname) + #if 0 /* These are for testing the test runner. */ TEST_ENTRY (fail_always)