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#ifndef _WIN32 29# include <unistd.h> /* close */ 30#else 31# include <fcntl.h> 32#endif 33 34static uv_pipe_t pipe_client; 35static uv_pipe_t pipe_server; 36static uv_connect_t connect_req; 37 38static int pipe_close_cb_called = 0; 39static int pipe_client_connect_cb_called = 0; 40 41 42static void pipe_close_cb(uv_handle_t* handle) { 43 ASSERT_NE(handle == (uv_handle_t*) &pipe_client || 44 handle == (uv_handle_t*) &pipe_server, 0); 45 pipe_close_cb_called++; 46} 47 48 49static void pipe_client_connect_cb(uv_connect_t* req, int status) { 50 char buf[1024]; 51 size_t len; 52 int r; 53 54 ASSERT_PTR_EQ(req, &connect_req); 55 ASSERT_OK(status); 56 57 len = sizeof buf; 58 r = uv_pipe_getpeername(&pipe_client, buf, &len); 59 ASSERT_OK(r); 60 61 if (*buf == '\0') { /* Linux abstract socket. */ 62 const char expected[] = "\0" TEST_PIPENAME; 63 ASSERT_EQ(len, sizeof(expected) - 1); 64 ASSERT_MEM_EQ(buf, expected, len); 65 } else { 66 ASSERT_NE(0, buf[len - 1]); 67 ASSERT_MEM_EQ(buf, TEST_PIPENAME, len); 68 } 69 70 len = sizeof buf; 71 r = uv_pipe_getsockname(&pipe_client, buf, &len); 72 ASSERT(r == 0 && len == 0); 73 74 pipe_client_connect_cb_called++; 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_OK(status); 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 namebuf[256]; 95 char buf[1024]; 96 size_t namelen; 97 size_t len; 98 int r; 99 100 snprintf(namebuf, sizeof(namebuf), "%s-oob", TEST_PIPENAME); 101 namelen = sizeof(TEST_PIPENAME) - 1; 102 103 loop = uv_default_loop(); 104 ASSERT_NOT_NULL(loop); 105 106 r = uv_pipe_init(loop, &pipe_server, 0); 107 ASSERT_OK(r); 108 109 r = uv_pipe_bind2(&pipe_server, "bad\0path", 8, 0); 110 ASSERT_EQ(r, UV_EINVAL); 111 112 len = sizeof buf; 113 r = uv_pipe_getsockname(&pipe_server, buf, &len); 114 ASSERT_EQ(r, UV_EBADF); 115 116 len = sizeof buf; 117 r = uv_pipe_getpeername(&pipe_server, buf, &len); 118 ASSERT_EQ(r, UV_EBADF); 119 120 r = uv_pipe_bind2(&pipe_server, namebuf, namelen, 0); 121 ASSERT_OK(r); 122 123#ifndef _WIN32 124 ASSERT_STR_EQ(pipe_server.pipe_fname, TEST_PIPENAME); 125#endif 126 127 len = sizeof buf; 128 r = uv_pipe_getsockname(&pipe_server, buf, &len); 129 ASSERT_OK(r); 130 131 ASSERT_NE(0, buf[len - 1]); 132 ASSERT_EQ(buf[len], '\0'); 133 ASSERT_OK(memcmp(buf, TEST_PIPENAME, len)); 134 135 len = sizeof buf; 136 r = uv_pipe_getpeername(&pipe_server, buf, &len); 137 ASSERT_EQ(r, UV_ENOTCONN); 138 139 r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); 140 ASSERT_OK(r); 141 142 r = uv_pipe_init(loop, &pipe_client, 0); 143 ASSERT_OK(r); 144 145 len = sizeof buf; 146 r = uv_pipe_getsockname(&pipe_client, buf, &len); 147 ASSERT_EQ(r, UV_EBADF); 148 149 len = sizeof buf; 150 r = uv_pipe_getpeername(&pipe_client, buf, &len); 151 ASSERT_EQ(r, UV_EBADF); 152 153 r = uv_pipe_connect2(&connect_req, 154 &pipe_client, 155 namebuf, 156 namelen, 157 0, 158 pipe_client_connect_cb); 159 ASSERT_OK(r); 160 161 len = sizeof buf; 162 r = uv_pipe_getsockname(&pipe_client, buf, &len); 163 ASSERT(r == 0 && len == 0); 164 165 len = sizeof buf; 166 r = uv_pipe_getpeername(&pipe_client, buf, &len); 167 ASSERT_OK(r); 168 169 ASSERT_NE(0, buf[len - 1]); 170 ASSERT_OK(memcmp(buf, TEST_PIPENAME, len)); 171 172 r = uv_run(loop, UV_RUN_DEFAULT); 173 ASSERT_OK(r); 174 ASSERT_EQ(1, pipe_client_connect_cb_called); 175 ASSERT_EQ(2, pipe_close_cb_called); 176 177 MAKE_VALGRIND_HAPPY(loop); 178 return 0; 179} 180 181 182TEST_IMPL(pipe_getsockname_abstract) { 183 /* TODO(bnoordhuis) Use unique name, susceptible to concurrent test runs. */ 184 static const char name[] = "\0" TEST_PIPENAME; 185#if defined(__linux__) 186 char buf[256]; 187 size_t buflen; 188 189 buflen = sizeof(buf); 190 memset(buf, 0, sizeof(buf)); 191 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_server, 0)); 192 ASSERT_OK(uv_pipe_bind2(&pipe_server, name, sizeof(name) - 1, 0)); 193 ASSERT_OK(uv_pipe_getsockname(&pipe_server, buf, &buflen)); 194 ASSERT_UINT64_EQ(sizeof(name) - 1, buflen); 195 ASSERT_MEM_EQ(name, buf, buflen); 196 ASSERT_OK(uv_listen((uv_stream_t*) &pipe_server, 197 0, 198 pipe_server_connection_cb)); 199 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_client, 0)); 200 ASSERT_OK(uv_pipe_connect2(&connect_req, 201 &pipe_client, 202 name, 203 sizeof(name) - 1, 204 0, 205 pipe_client_connect_cb)); 206 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 207 ASSERT_EQ(1, pipe_client_connect_cb_called); 208 ASSERT_EQ(2, pipe_close_cb_called); 209 MAKE_VALGRIND_HAPPY(uv_default_loop()); 210 return 0; 211#else 212 /* On other platforms it should simply fail with UV_EINVAL. */ 213 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_server, 0)); 214 ASSERT_EQ(UV_EINVAL, uv_pipe_bind2(&pipe_server, name, sizeof(name), 0)); 215 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_client, 0)); 216 uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); 217 ASSERT_EQ(UV_EINVAL, uv_pipe_connect2(&connect_req, 218 &pipe_client, 219 name, 220 sizeof(name), 221 0, 222 (uv_connect_cb) abort)); 223 uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); 224 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 225 ASSERT_EQ(2, pipe_close_cb_called); 226 MAKE_VALGRIND_HAPPY(uv_default_loop()); 227 return 0; 228#endif 229} 230 231TEST_IMPL(pipe_getsockname_blocking) { 232#ifdef _WIN32 233 HANDLE readh, writeh; 234 int readfd; 235 char buf1[1024], buf2[1024]; 236 size_t len1, len2; 237 int r; 238 239 r = CreatePipe(&readh, &writeh, NULL, 65536); 240 ASSERT(r); 241 242 r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); 243 ASSERT_OK(r); 244 readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); 245 ASSERT_NE(r, -1); 246 r = uv_pipe_open(&pipe_client, readfd); 247 ASSERT_OK(r); 248 r = uv_read_start((uv_stream_t*) &pipe_client, 249 (uv_alloc_cb) abort, 250 (uv_read_cb) abort); 251 ASSERT_OK(r); 252 Sleep(100); 253 r = uv_read_stop((uv_stream_t*)&pipe_client); 254 ASSERT_OK(r); 255 256 len1 = sizeof buf1; 257 r = uv_pipe_getsockname(&pipe_client, buf1, &len1); 258 ASSERT_OK(r); 259 ASSERT_OK(len1); /* It's an annonymous pipe. */ 260 261 r = uv_read_start((uv_stream_t*)&pipe_client, 262 (uv_alloc_cb) abort, 263 (uv_read_cb) abort); 264 ASSERT_OK(r); 265 Sleep(100); 266 267 len2 = sizeof buf2; 268 r = uv_pipe_getsockname(&pipe_client, buf2, &len2); 269 ASSERT_OK(r); 270 ASSERT_OK(len2); /* It's an annonymous pipe. */ 271 272 r = uv_read_stop((uv_stream_t*)&pipe_client); 273 ASSERT_OK(r); 274 275 ASSERT_EQ(len1, len2); 276 ASSERT_OK(memcmp(buf1, buf2, len1)); 277 278 pipe_close_cb_called = 0; 279 uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); 280 281 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 282 283 ASSERT_EQ(1, pipe_close_cb_called); 284 285 CloseHandle(writeh); 286#endif 287 288 MAKE_VALGRIND_HAPPY(uv_default_loop()); 289 return 0; 290} 291