1 1.1 christos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 1.1 christos * 3 1.1 christos * Permission is hereby granted, free of charge, to any person obtaining a copy 4 1.1 christos * of this software and associated documentation files (the "Software"), to 5 1.1 christos * deal in the Software without restriction, including without limitation the 6 1.1 christos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 1.1 christos * sell copies of the Software, and to permit persons to whom the Software is 8 1.1 christos * furnished to do so, subject to the following conditions: 9 1.1 christos * 10 1.1 christos * The above copyright notice and this permission notice shall be included in 11 1.1 christos * all copies or substantial portions of the Software. 12 1.1 christos * 13 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 1.1 christos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 1.1 christos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 1.1 christos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 1.1 christos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 1.1 christos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 1.1 christos * IN THE SOFTWARE. 20 1.1 christos */ 21 1.1 christos 22 1.1 christos #include "uv.h" 23 1.1 christos #include "task.h" 24 1.1 christos #include <stdio.h> 25 1.1 christos #include <stdlib.h> 26 1.1 christos 27 1.1 christos 28 1.1.1.2 christos static int connect_cb_called = 0; 29 1.1 christos static int close_cb_called = 0; 30 1.1 christos 31 1.1 christos 32 1.1 christos static void close_cb(uv_handle_t* handle) { 33 1.1.1.2 christos ASSERT_NOT_NULL(handle); 34 1.1 christos close_cb_called++; 35 1.1 christos } 36 1.1 christos 37 1.1 christos 38 1.1.1.2 christos static void connect_cb(uv_connect_t* req, int status) { 39 1.1.1.3 christos ASSERT_EQ(status, UV_EADDRINUSE); 40 1.1.1.2 christos uv_close((uv_handle_t*) req->handle, close_cb); 41 1.1.1.2 christos connect_cb_called++; 42 1.1.1.2 christos } 43 1.1.1.2 christos 44 1.1.1.2 christos 45 1.1.1.2 christos TEST_IMPL(tcp_bind_error_addrinuse_connect) { 46 1.1.1.2 christos struct sockaddr_in addr; 47 1.1.1.2 christos int addrlen; 48 1.1.1.2 christos uv_connect_t req; 49 1.1.1.2 christos uv_tcp_t conn; 50 1.1.1.2 christos 51 1.1.1.2 christos /* 127.0.0.1:<TEST_PORT> is already taken by tcp4_echo_server running in 52 1.1.1.2 christos * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed 53 1.1.1.2 christos * (greatest common denominator across platforms) but the connect callback 54 1.1.1.2 christos * should receive an UV_EADDRINUSE error. 55 1.1.1.2 christos */ 56 1.1.1.3 christos ASSERT_OK(uv_tcp_init(uv_default_loop(), &conn)); 57 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 58 1.1.1.3 christos ASSERT_OK(uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0)); 59 1.1.1.3 christos 60 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr)); 61 1.1.1.3 christos ASSERT_OK(uv_tcp_connect(&req, 62 1.1.1.3 christos &conn, 63 1.1.1.3 christos (const struct sockaddr*) &addr, 64 1.1.1.3 christos connect_cb)); 65 1.1.1.2 christos 66 1.1.1.2 christos addrlen = sizeof(addr); 67 1.1.1.3 christos ASSERT_EQ(UV_EADDRINUSE, uv_tcp_getsockname(&conn, 68 1.1.1.3 christos (struct sockaddr*) &addr, 69 1.1.1.3 christos &addrlen)); 70 1.1.1.3 christos 71 1.1.1.3 christos ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 72 1.1.1.3 christos ASSERT_EQ(1, connect_cb_called); 73 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 74 1.1.1.2 christos 75 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 76 1.1.1.2 christos return 0; 77 1.1.1.2 christos } 78 1.1.1.2 christos 79 1.1.1.2 christos 80 1.1.1.2 christos TEST_IMPL(tcp_bind_error_addrinuse_listen) { 81 1.1 christos struct sockaddr_in addr; 82 1.1 christos uv_tcp_t server1, server2; 83 1.1 christos int r; 84 1.1 christos 85 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 86 1.1 christos r = uv_tcp_init(uv_default_loop(), &server1); 87 1.1.1.3 christos ASSERT_OK(r); 88 1.1 christos r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); 89 1.1.1.3 christos ASSERT_OK(r); 90 1.1 christos 91 1.1 christos r = uv_tcp_init(uv_default_loop(), &server2); 92 1.1.1.3 christos ASSERT_OK(r); 93 1.1 christos r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); 94 1.1.1.3 christos ASSERT_OK(r); 95 1.1 christos 96 1.1 christos r = uv_listen((uv_stream_t*)&server1, 128, NULL); 97 1.1.1.3 christos ASSERT_OK(r); 98 1.1 christos r = uv_listen((uv_stream_t*)&server2, 128, NULL); 99 1.1.1.3 christos ASSERT_EQ(r, UV_EADDRINUSE); 100 1.1 christos 101 1.1 christos uv_close((uv_handle_t*)&server1, close_cb); 102 1.1 christos uv_close((uv_handle_t*)&server2, close_cb); 103 1.1 christos 104 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 105 1.1 christos 106 1.1.1.3 christos ASSERT_EQ(2, close_cb_called); 107 1.1 christos 108 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 109 1.1 christos return 0; 110 1.1 christos } 111 1.1 christos 112 1.1 christos 113 1.1 christos TEST_IMPL(tcp_bind_error_addrnotavail_1) { 114 1.1 christos struct sockaddr_in addr; 115 1.1 christos uv_tcp_t server; 116 1.1 christos int r; 117 1.1 christos 118 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("127.255.255.255", TEST_PORT, &addr)); 119 1.1 christos 120 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 121 1.1.1.3 christos ASSERT_OK(r); 122 1.1 christos 123 1.1 christos /* It seems that Linux is broken here - bind succeeds. */ 124 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 125 1.1 christos ASSERT(r == 0 || r == UV_EADDRNOTAVAIL); 126 1.1 christos 127 1.1 christos uv_close((uv_handle_t*)&server, close_cb); 128 1.1 christos 129 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 130 1.1 christos 131 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 132 1.1 christos 133 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 134 1.1 christos return 0; 135 1.1 christos } 136 1.1 christos 137 1.1 christos 138 1.1 christos TEST_IMPL(tcp_bind_error_addrnotavail_2) { 139 1.1 christos struct sockaddr_in addr; 140 1.1 christos uv_tcp_t server; 141 1.1 christos int r; 142 1.1 christos 143 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("4.4.4.4", TEST_PORT, &addr)); 144 1.1 christos 145 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 146 1.1.1.3 christos ASSERT_OK(r); 147 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 148 1.1.1.3 christos ASSERT_EQ(r, UV_EADDRNOTAVAIL); 149 1.1 christos 150 1.1 christos uv_close((uv_handle_t*)&server, close_cb); 151 1.1 christos 152 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 153 1.1 christos 154 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 155 1.1 christos 156 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 157 1.1 christos return 0; 158 1.1 christos } 159 1.1 christos 160 1.1 christos 161 1.1 christos TEST_IMPL(tcp_bind_error_fault) { 162 1.1 christos char garbage[] = 163 1.1 christos "blah blah blah blah blah blah blah blah blah blah blah blah"; 164 1.1 christos struct sockaddr_in* garbage_addr; 165 1.1 christos uv_tcp_t server; 166 1.1 christos int r; 167 1.1 christos 168 1.1 christos garbage_addr = (struct sockaddr_in*) &garbage; 169 1.1 christos 170 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 171 1.1.1.3 christos ASSERT_OK(r); 172 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); 173 1.1.1.3 christos ASSERT_EQ(r, UV_EINVAL); 174 1.1 christos 175 1.1 christos uv_close((uv_handle_t*)&server, close_cb); 176 1.1 christos 177 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 178 1.1 christos 179 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 180 1.1 christos 181 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 182 1.1 christos return 0; 183 1.1 christos } 184 1.1 christos 185 1.1 christos /* Notes: On Linux uv_bind(server, NULL) will segfault the program. */ 186 1.1 christos 187 1.1 christos TEST_IMPL(tcp_bind_error_inval) { 188 1.1 christos struct sockaddr_in addr1; 189 1.1 christos struct sockaddr_in addr2; 190 1.1 christos uv_tcp_t server; 191 1.1 christos int r; 192 1.1 christos 193 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1)); 194 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2)); 195 1.1 christos 196 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 197 1.1.1.3 christos ASSERT_OK(r); 198 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); 199 1.1.1.3 christos ASSERT_OK(r); 200 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); 201 1.1.1.3 christos ASSERT_EQ(r, UV_EINVAL); 202 1.1 christos 203 1.1 christos uv_close((uv_handle_t*)&server, close_cb); 204 1.1 christos 205 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 206 1.1 christos 207 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 208 1.1 christos 209 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 210 1.1 christos return 0; 211 1.1 christos } 212 1.1 christos 213 1.1 christos 214 1.1 christos TEST_IMPL(tcp_bind_localhost_ok) { 215 1.1 christos struct sockaddr_in addr; 216 1.1 christos uv_tcp_t server; 217 1.1 christos int r; 218 1.1 christos 219 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 220 1.1 christos 221 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 222 1.1.1.3 christos ASSERT_OK(r); 223 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 224 1.1.1.3 christos ASSERT_OK(r); 225 1.1 christos 226 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 227 1.1 christos return 0; 228 1.1 christos } 229 1.1 christos 230 1.1 christos 231 1.1 christos TEST_IMPL(tcp_bind_invalid_flags) { 232 1.1 christos struct sockaddr_in addr; 233 1.1 christos uv_tcp_t server; 234 1.1 christos int r; 235 1.1 christos 236 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 237 1.1 christos 238 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 239 1.1.1.3 christos ASSERT_OK(r); 240 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); 241 1.1.1.3 christos ASSERT_EQ(r, UV_EINVAL); 242 1.1 christos 243 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 244 1.1 christos return 0; 245 1.1 christos } 246 1.1 christos 247 1.1 christos 248 1.1 christos TEST_IMPL(tcp_listen_without_bind) { 249 1.1 christos int r; 250 1.1 christos uv_tcp_t server; 251 1.1 christos 252 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 253 1.1.1.3 christos ASSERT_OK(r); 254 1.1 christos r = uv_listen((uv_stream_t*)&server, 128, NULL); 255 1.1.1.3 christos ASSERT_OK(r); 256 1.1 christos 257 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 258 1.1 christos return 0; 259 1.1 christos } 260 1.1 christos 261 1.1 christos 262 1.1 christos TEST_IMPL(tcp_bind_writable_flags) { 263 1.1 christos struct sockaddr_in addr; 264 1.1 christos uv_tcp_t server; 265 1.1 christos uv_buf_t buf; 266 1.1 christos uv_write_t write_req; 267 1.1 christos uv_shutdown_t shutdown_req; 268 1.1 christos int r; 269 1.1 christos 270 1.1.1.3 christos ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 271 1.1 christos r = uv_tcp_init(uv_default_loop(), &server); 272 1.1.1.3 christos ASSERT_OK(r); 273 1.1 christos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 274 1.1.1.3 christos ASSERT_OK(r); 275 1.1 christos r = uv_listen((uv_stream_t*)&server, 128, NULL); 276 1.1.1.3 christos ASSERT_OK(r); 277 1.1 christos 278 1.1.1.3 christos ASSERT_OK(uv_is_writable((uv_stream_t*) &server)); 279 1.1.1.3 christos ASSERT_OK(uv_is_readable((uv_stream_t*) &server)); 280 1.1 christos 281 1.1 christos buf = uv_buf_init("PING", 4); 282 1.1 christos r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); 283 1.1.1.3 christos ASSERT_EQ(r, UV_EPIPE); 284 1.1 christos r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); 285 1.1.1.3 christos ASSERT_EQ(r, UV_ENOTCONN); 286 1.1.1.2 christos r = uv_read_start((uv_stream_t*) &server, 287 1.1.1.2 christos (uv_alloc_cb) abort, 288 1.1.1.2 christos (uv_read_cb) abort); 289 1.1.1.3 christos ASSERT_EQ(r, UV_ENOTCONN); 290 1.1 christos 291 1.1 christos uv_close((uv_handle_t*)&server, close_cb); 292 1.1 christos 293 1.1 christos uv_run(uv_default_loop(), UV_RUN_DEFAULT); 294 1.1 christos 295 1.1.1.3 christos ASSERT_EQ(1, close_cb_called); 296 1.1 christos 297 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 298 1.1 christos return 0; 299 1.1 christos } 300 1.1.1.2 christos 301 1.1.1.2 christos TEST_IMPL(tcp_bind_or_listen_error_after_close) { 302 1.1.1.2 christos uv_tcp_t tcp; 303 1.1.1.2 christos struct sockaddr_in addr; 304 1.1.1.2 christos 305 1.1.1.2 christos memset(&addr, 0, sizeof(addr)); 306 1.1.1.2 christos addr.sin_addr.s_addr = htonl(INADDR_ANY); 307 1.1.1.2 christos addr.sin_port = htons(9999); 308 1.1.1.2 christos addr.sin_family = AF_INET; 309 1.1.1.2 christos 310 1.1.1.3 christos ASSERT_OK(uv_tcp_init(uv_default_loop(), &tcp)); 311 1.1.1.2 christos uv_close((uv_handle_t*) &tcp, NULL); 312 1.1.1.2 christos ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL); 313 1.1.1.2 christos ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL); 314 1.1.1.3 christos ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 315 1.1.1.3 christos MAKE_VALGRIND_HAPPY(uv_default_loop()); 316 1.1.1.2 christos return 0; 317 1.1.1.2 christos } 318