1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22#include "uv.h" 23#include "task.h" 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27 28#if defined(__linux__) 29 #include <sys/socket.h> 30 #include <sys/un.h> 31#endif 32 33#ifndef _WIN32 34# include <unistd.h> /* close */ 35#else 36# include <fcntl.h> 37#endif 38 39static uv_pipe_t pipe_client; 40static uv_pipe_t pipe_server; 41static uv_connect_t connect_req; 42 43static int pipe_close_cb_called = 0; 44static int pipe_client_connect_cb_called = 0; 45 46 47static void pipe_close_cb(uv_handle_t* handle) { 48 ASSERT(handle == (uv_handle_t*) &pipe_client || 49 handle == (uv_handle_t*) &pipe_server); 50 pipe_close_cb_called++; 51} 52 53 54static void pipe_client_connect_cb(uv_connect_t* req, int status) { 55 char buf[1024]; 56 size_t len; 57 int r; 58 59 ASSERT(req == &connect_req); 60 ASSERT(status == 0); 61 62 len = sizeof buf; 63 r = uv_pipe_getpeername(&pipe_client, buf, &len); 64 ASSERT(r == 0); 65 66 ASSERT(buf[len - 1] != 0); 67 ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); 68 69 len = sizeof buf; 70 r = uv_pipe_getsockname(&pipe_client, buf, &len); 71 ASSERT(r == 0 && len == 0); 72 73 pipe_client_connect_cb_called++; 74 75 76 uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); 77 uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); 78} 79 80 81static void pipe_server_connection_cb(uv_stream_t* handle, int status) { 82 /* This function *may* be called, depending on whether accept or the 83 * connection callback is called first. 84 */ 85 ASSERT(status == 0); 86} 87 88 89TEST_IMPL(pipe_getsockname) { 90#if defined(NO_SELF_CONNECT) 91 RETURN_SKIP(NO_SELF_CONNECT); 92#endif 93 uv_loop_t* loop; 94 char buf[1024]; 95 size_t len; 96 int r; 97 98 loop = uv_default_loop(); 99 ASSERT_NOT_NULL(loop); 100 101 r = uv_pipe_init(loop, &pipe_server, 0); 102 ASSERT(r == 0); 103 104 len = sizeof buf; 105 r = uv_pipe_getsockname(&pipe_server, buf, &len); 106 ASSERT(r == UV_EBADF); 107 108 len = sizeof buf; 109 r = uv_pipe_getpeername(&pipe_server, buf, &len); 110 ASSERT(r == UV_EBADF); 111 112 r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); 113 ASSERT(r == 0); 114 115 len = sizeof buf; 116 r = uv_pipe_getsockname(&pipe_server, buf, &len); 117 ASSERT(r == 0); 118 119 ASSERT(buf[len - 1] != 0); 120 ASSERT(buf[len] == '\0'); 121 ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); 122 123 len = sizeof buf; 124 r = uv_pipe_getpeername(&pipe_server, buf, &len); 125 ASSERT(r == UV_ENOTCONN); 126 127 r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); 128 ASSERT(r == 0); 129 130 r = uv_pipe_init(loop, &pipe_client, 0); 131 ASSERT(r == 0); 132 133 len = sizeof buf; 134 r = uv_pipe_getsockname(&pipe_client, buf, &len); 135 ASSERT(r == UV_EBADF); 136 137 len = sizeof buf; 138 r = uv_pipe_getpeername(&pipe_client, buf, &len); 139 ASSERT(r == UV_EBADF); 140 141 uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); 142 143 len = sizeof buf; 144 r = uv_pipe_getsockname(&pipe_client, buf, &len); 145 ASSERT(r == 0 && len == 0); 146 147 len = sizeof buf; 148 r = uv_pipe_getpeername(&pipe_client, buf, &len); 149 ASSERT(r == 0); 150 151 ASSERT(buf[len - 1] != 0); 152 ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); 153 154 r = uv_run(loop, UV_RUN_DEFAULT); 155 ASSERT(r == 0); 156 ASSERT(pipe_client_connect_cb_called == 1); 157 ASSERT(pipe_close_cb_called == 2); 158 159 MAKE_VALGRIND_HAPPY(); 160 return 0; 161} 162 163 164TEST_IMPL(pipe_getsockname_abstract) { 165#if defined(__linux__) 166 char buf[1024]; 167 size_t len; 168 int r; 169 int sock; 170 struct sockaddr_un sun; 171 socklen_t sun_len; 172 char abstract_pipe[] = "\0test-pipe"; 173 174 sock = socket(AF_UNIX, SOCK_STREAM, 0); 175 ASSERT(sock != -1); 176 177 sun_len = sizeof sun; 178 memset(&sun, 0, sun_len); 179 sun.sun_family = AF_UNIX; 180 memcpy(sun.sun_path, abstract_pipe, sizeof abstract_pipe); 181 182 r = bind(sock, (struct sockaddr*)&sun, sun_len); 183 ASSERT(r == 0); 184 185 r = uv_pipe_init(uv_default_loop(), &pipe_server, 0); 186 ASSERT(r == 0); 187 r = uv_pipe_open(&pipe_server, sock); 188 ASSERT(r == 0); 189 190 len = sizeof buf; 191 r = uv_pipe_getsockname(&pipe_server, buf, &len); 192 ASSERT(r == 0); 193 194 ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0); 195 196 uv_close((uv_handle_t*)&pipe_server, pipe_close_cb); 197 198 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 199 200 close(sock); 201 202 ASSERT(pipe_close_cb_called == 1); 203 MAKE_VALGRIND_HAPPY(); 204 return 0; 205#else 206 MAKE_VALGRIND_HAPPY(); 207 return 0; 208#endif 209} 210 211TEST_IMPL(pipe_getsockname_blocking) { 212#ifdef _WIN32 213 HANDLE readh, writeh; 214 int readfd; 215 char buf1[1024], buf2[1024]; 216 size_t len1, len2; 217 int r; 218 219 r = CreatePipe(&readh, &writeh, NULL, 65536); 220 ASSERT(r != 0); 221 222 r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); 223 ASSERT(r == 0); 224 readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); 225 ASSERT(r != -1); 226 r = uv_pipe_open(&pipe_client, readfd); 227 ASSERT(r == 0); 228 r = uv_read_start((uv_stream_t*) &pipe_client, 229 (uv_alloc_cb) abort, 230 (uv_read_cb) abort); 231 ASSERT(r == 0); 232 Sleep(100); 233 r = uv_read_stop((uv_stream_t*)&pipe_client); 234 ASSERT(r == 0); 235 236 len1 = sizeof buf1; 237 r = uv_pipe_getsockname(&pipe_client, buf1, &len1); 238 ASSERT(r == 0); 239 ASSERT(len1 == 0); /* It's an annonymous pipe. */ 240 241 r = uv_read_start((uv_stream_t*)&pipe_client, 242 (uv_alloc_cb) abort, 243 (uv_read_cb) abort); 244 ASSERT(r == 0); 245 Sleep(100); 246 247 len2 = sizeof buf2; 248 r = uv_pipe_getsockname(&pipe_client, buf2, &len2); 249 ASSERT(r == 0); 250 ASSERT(len2 == 0); /* It's an annonymous pipe. */ 251 252 r = uv_read_stop((uv_stream_t*)&pipe_client); 253 ASSERT(r == 0); 254 255 ASSERT(len1 == len2); 256 ASSERT(memcmp(buf1, buf2, len1) == 0); 257 258 pipe_close_cb_called = 0; 259 uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); 260 261 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 262 263 ASSERT(pipe_close_cb_called == 1); 264 265 CloseHandle(writeh); 266#endif 267 268 MAKE_VALGRIND_HAPPY(); 269 return 0; 270} 271