From 39a0936fecf59b9898904b80e8a9d60d56f3e1d4 Mon Sep 17 00:00:00 2001 From: Andrius Bentkus Date: Mon, 26 Jan 2015 16:23:06 +0100 Subject: [PATCH] win, unix: add pipe_peername implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/166 Reviewed-By: Saúl Ibarra Corretgé --- docs/src/pipe.rst | 12 +++ include/uv.h | 3 + src/unix/pipe.c | 22 +++++- src/win/pipe.c | 28 ++++++- test/test-pipe-getsockname.c | 144 +++++++++++++++++++++++++++-------- 5 files changed, 174 insertions(+), 35 deletions(-) diff --git a/docs/src/pipe.rst b/docs/src/pipe.rst index 01aea4ac..8f8402c2 100644 --- a/docs/src/pipe.rst +++ b/docs/src/pipe.rst @@ -68,6 +68,18 @@ API .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, and the buffer is not null terminated. +.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) + + Get the name of the Unix domain socket or the named pipe to which the handle + is connected. + + A preallocated buffer must be provided. The size parameter holds the length + of the buffer and it's set to the number of bytes written to the buffer on + output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and + len will contain the required size. + + .. versionadded:: 1.3.0 + .. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count) Set the number of pending pipe instance handles when the pipe server is diff --git a/include/uv.h b/include/uv.h index 72de65e5..191eecac 100644 --- a/include/uv.h +++ b/include/uv.h @@ -677,6 +677,9 @@ UV_EXTERN void uv_pipe_connect(uv_connect_t* req, UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size); +UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle, + char* buffer, + size_t* size); UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count); UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle); UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle); diff --git a/src/unix/pipe.c b/src/unix/pipe.c index c9f0a149..bc8b8563 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -206,23 +206,31 @@ out: } -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { +typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); + + +static int uv__pipe_getsockpeername(const uv_pipe_t* handle, + uv__peersockfunc func, + char* buffer, + size_t* size) { struct sockaddr_un sa; socklen_t addrlen; int err; addrlen = sizeof(sa); memset(&sa, 0, addrlen); - err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); + err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); if (err < 0) { *size = 0; return -errno; } +#if defined(__linux__) if (sa.sun_path[0] == 0) /* Linux abstract namespace */ addrlen -= offsetof(struct sockaddr_un, sun_path); else +#endif addrlen = strlen(sa.sun_path); @@ -238,6 +246,16 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { } +int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { + return uv__pipe_getsockpeername(handle, getsockname, buffer, size); +} + + +int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { + return uv__pipe_getsockpeername(handle, getpeername, buffer, size); +} + + void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { } diff --git a/src/win/pipe.c b/src/win/pipe.c index d82007a1..57fab065 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -1910,7 +1910,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { } -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { +static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_NAME_INFORMATION tmp_name_info; @@ -2031,6 +2031,32 @@ int uv_pipe_pending_count(uv_pipe_t* handle) { } +int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { + if (handle->flags & UV_HANDLE_BOUND) + return uv__pipe_getname(handle, buffer, size); + + if (handle->flags & UV_HANDLE_CONNECTION || + handle->handle != INVALID_HANDLE_VALUE) { + *size = 0; + return 0; + } + + return UV_EBADF; +} + + +int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { + /* emulate unix behaviour */ + if (handle->flags & UV_HANDLE_BOUND) + return UV_ENOTCONN; + + if (handle->handle != INVALID_HANDLE_VALUE) + return uv__pipe_getname(handle, buffer, size); + + return UV_EBADF; +} + + uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (!handle->ipc) return UV_UNKNOWN_HANDLE; diff --git a/test/test-pipe-getsockname.c b/test/test-pipe-getsockname.c index b54b4e55..5e036f9d 100644 --- a/test/test-pipe-getsockname.c +++ b/test/test-pipe-getsockname.c @@ -36,39 +36,121 @@ # include #endif +static uv_pipe_t pipe_client; +static uv_pipe_t pipe_server; +static uv_connect_t connect_req; -static int close_cb_called = 0; +static int pipe_close_cb_called = 0; +static int pipe_client_connect_cb_called = 0; -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; +static void pipe_close_cb(uv_handle_t* handle) { + ASSERT(handle == (uv_handle_t*) &pipe_client || + handle == (uv_handle_t*) &pipe_server); + pipe_close_cb_called++; } -TEST_IMPL(pipe_getsockname) { - uv_pipe_t server; +static void pipe_client_connect_cb(uv_connect_t* req, int status) { char buf[1024]; size_t len; int r; - r = uv_pipe_init(uv_default_loop(), &server, 0); + ASSERT(req == &connect_req); + ASSERT(status == 0); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); ASSERT(r == 0); - r = uv_pipe_bind(&server, TEST_PIPENAME); + + ASSERT(buf[len - 1] != 0); + ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == 0 && len == 0); + + pipe_client_connect_cb_called++; + + + uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); + uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); +} + + +static void pipe_server_connection_cb(uv_stream_t* handle, int status) { + /* This function *may* be called, depending on whether accept or the + * connection callback is called first. + */ + ASSERT(status == 0); +} + + +TEST_IMPL(pipe_getsockname) { + uv_loop_t* loop; + char buf[1024]; + size_t len; + int r; + + loop = uv_default_loop(); + ASSERT(loop != NULL); + + r = uv_pipe_init(loop, &pipe_server, 0); ASSERT(r == 0); len = sizeof buf; - r = uv_pipe_getsockname(&server, buf, &len); - ASSERT(r == 0); - ASSERT(buf[len - 1] != 0); + r = uv_pipe_getsockname(&pipe_server, buf, &len); + ASSERT(r == UV_EBADF); + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_server, buf, &len); + ASSERT(r == UV_EBADF); + + r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); + ASSERT(r == 0); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_server, buf, &len); + ASSERT(r == 0); + + ASSERT(buf[len - 1] != 0); ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); - uv_close((uv_handle_t*)&server, close_cb); + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_server, buf, &len); + ASSERT(r == UV_ENOTCONN); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); + r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); + ASSERT(r == 0); - ASSERT(close_cb_called == 1); + r = uv_pipe_init(loop, &pipe_client, 0); + ASSERT(r == 0); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == UV_EBADF); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); + ASSERT(r == UV_EBADF); + + uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == 0 && len == 0); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); + ASSERT(r == 0); + + ASSERT(buf[len - 1] != 0); + ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(pipe_client_connect_cb_called == 1); + ASSERT(pipe_close_cb_called == 2); MAKE_VALGRIND_HAPPY(); return 0; @@ -77,7 +159,6 @@ TEST_IMPL(pipe_getsockname) { TEST_IMPL(pipe_getsockname_abstract) { #if defined(__linux__) - uv_pipe_t server; char buf[1024]; size_t len; int r; @@ -97,24 +178,24 @@ TEST_IMPL(pipe_getsockname_abstract) { r = bind(sock, (struct sockaddr*)&sun, sun_len); ASSERT(r == 0); - r = uv_pipe_init(uv_default_loop(), &server, 0); + r = uv_pipe_init(uv_default_loop(), &pipe_server, 0); ASSERT(r == 0); - r = uv_pipe_open(&server, sock); + r = uv_pipe_open(&pipe_server, sock); ASSERT(r == 0); len = sizeof buf; - r = uv_pipe_getsockname(&server, buf, &len); + r = uv_pipe_getsockname(&pipe_server, buf, &len); ASSERT(r == 0); ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0); - uv_close((uv_handle_t*)&server, close_cb); + uv_close((uv_handle_t*)&pipe_server, pipe_close_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); close(sock); - ASSERT(close_cb_called == 1); + ASSERT(pipe_close_cb_called == 1); MAKE_VALGRIND_HAPPY(); return 0; #else @@ -125,7 +206,6 @@ TEST_IMPL(pipe_getsockname_abstract) { TEST_IMPL(pipe_getsockname_blocking) { #ifdef _WIN32 - uv_pipe_t reader; HANDLE readh, writeh; int readfd; char buf1[1024], buf2[1024]; @@ -135,44 +215,44 @@ TEST_IMPL(pipe_getsockname_blocking) { r = CreatePipe(&readh, &writeh, NULL, 65536); ASSERT(r != 0); - r = uv_pipe_init(uv_default_loop(), &reader, 0); + r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); ASSERT(r == 0); readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); ASSERT(r != -1); - r = uv_pipe_open(&reader, readfd); + r = uv_pipe_open(&pipe_client, readfd); ASSERT(r == 0); - r = uv_read_start((uv_stream_t*)&reader, NULL, NULL); + r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); ASSERT(r == 0); Sleep(100); - r = uv_read_stop((uv_stream_t*)&reader); + r = uv_read_stop((uv_stream_t*)&pipe_client); ASSERT(r == 0); len1 = sizeof buf1; - r = uv_pipe_getsockname(&reader, buf1, &len1); + r = uv_pipe_getsockname(&pipe_client, buf1, &len1); ASSERT(r == 0); ASSERT(buf1[len1 - 1] != 0); - r = uv_read_start((uv_stream_t*)&reader, NULL, NULL); + r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); ASSERT(r == 0); Sleep(100); len2 = sizeof buf2; - r = uv_pipe_getsockname(&reader, buf2, &len2); + r = uv_pipe_getsockname(&pipe_client, buf2, &len2); ASSERT(r == 0); ASSERT(buf2[len2 - 1] != 0); - r = uv_read_stop((uv_stream_t*)&reader); + r = uv_read_stop((uv_stream_t*)&pipe_client); ASSERT(r == 0); ASSERT(len1 == len2); ASSERT(memcmp(buf1, buf2, len1) == 0); - close_cb_called = 0; - uv_close((uv_handle_t*)&reader, close_cb); + pipe_close_cb_called = 0; + uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); + ASSERT(pipe_close_cb_called == 1); _close(readfd); CloseHandle(writeh);