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 27 28 static int connect_cb_called = 0; 29 static int close_cb_called = 0; 30 31 32 static void close_cb(uv_handle_t* handle) { 33 ASSERT_NOT_NULL(handle); 34 close_cb_called++; 35 } 36 37 38 static void connect_cb(uv_connect_t* req, int status) { 39 ASSERT(status == UV_EADDRINUSE); 40 uv_close((uv_handle_t*) req->handle, close_cb); 41 connect_cb_called++; 42 } 43 44 45 TEST_IMPL(tcp_bind_error_addrinuse_connect) { 46 struct sockaddr_in addr; 47 int addrlen; 48 uv_connect_t req; 49 uv_tcp_t conn; 50 51 /* 127.0.0.1:<TEST_PORT> is already taken by tcp4_echo_server running in 52 * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed 53 * (greatest common denominator across platforms) but the connect callback 54 * should receive an UV_EADDRINUSE error. 55 */ 56 ASSERT(0 == uv_tcp_init(uv_default_loop(), &conn)); 57 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 58 ASSERT(0 == uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0)); 59 60 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr)); 61 ASSERT(0 == uv_tcp_connect(&req, 62 &conn, 63 (const struct sockaddr*) &addr, 64 connect_cb)); 65 66 addrlen = sizeof(addr); 67 ASSERT(UV_EADDRINUSE == uv_tcp_getsockname(&conn, 68 (struct sockaddr*) &addr, 69 &addrlen)); 70 71 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 72 ASSERT(connect_cb_called == 1); 73 ASSERT(close_cb_called == 1); 74 75 MAKE_VALGRIND_HAPPY(); 76 return 0; 77 } 78 79 80 TEST_IMPL(tcp_bind_error_addrinuse_listen) { 81 struct sockaddr_in addr; 82 uv_tcp_t server1, server2; 83 int r; 84 85 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 86 r = uv_tcp_init(uv_default_loop(), &server1); 87 ASSERT(r == 0); 88 r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); 89 ASSERT(r == 0); 90 91 r = uv_tcp_init(uv_default_loop(), &server2); 92 ASSERT(r == 0); 93 r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); 94 ASSERT(r == 0); 95 96 r = uv_listen((uv_stream_t*)&server1, 128, NULL); 97 ASSERT(r == 0); 98 r = uv_listen((uv_stream_t*)&server2, 128, NULL); 99 ASSERT(r == UV_EADDRINUSE); 100 101 uv_close((uv_handle_t*)&server1, close_cb); 102 uv_close((uv_handle_t*)&server2, close_cb); 103 104 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 105 106 ASSERT(close_cb_called == 2); 107 108 MAKE_VALGRIND_HAPPY(); 109 return 0; 110 } 111 112 113 TEST_IMPL(tcp_bind_error_addrnotavail_1) { 114 struct sockaddr_in addr; 115 uv_tcp_t server; 116 int r; 117 118 ASSERT(0 == uv_ip4_addr("127.255.255.255", TEST_PORT, &addr)); 119 120 r = uv_tcp_init(uv_default_loop(), &server); 121 ASSERT(r == 0); 122 123 /* It seems that Linux is broken here - bind succeeds. */ 124 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 125 ASSERT(r == 0 || r == UV_EADDRNOTAVAIL); 126 127 uv_close((uv_handle_t*)&server, close_cb); 128 129 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 130 131 ASSERT(close_cb_called == 1); 132 133 MAKE_VALGRIND_HAPPY(); 134 return 0; 135 } 136 137 138 TEST_IMPL(tcp_bind_error_addrnotavail_2) { 139 struct sockaddr_in addr; 140 uv_tcp_t server; 141 int r; 142 143 ASSERT(0 == uv_ip4_addr("4.4.4.4", TEST_PORT, &addr)); 144 145 r = uv_tcp_init(uv_default_loop(), &server); 146 ASSERT(r == 0); 147 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 148 ASSERT(r == UV_EADDRNOTAVAIL); 149 150 uv_close((uv_handle_t*)&server, close_cb); 151 152 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 153 154 ASSERT(close_cb_called == 1); 155 156 MAKE_VALGRIND_HAPPY(); 157 return 0; 158 } 159 160 161 TEST_IMPL(tcp_bind_error_fault) { 162 char garbage[] = 163 "blah blah blah blah blah blah blah blah blah blah blah blah"; 164 struct sockaddr_in* garbage_addr; 165 uv_tcp_t server; 166 int r; 167 168 garbage_addr = (struct sockaddr_in*) &garbage; 169 170 r = uv_tcp_init(uv_default_loop(), &server); 171 ASSERT(r == 0); 172 r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); 173 ASSERT(r == UV_EINVAL); 174 175 uv_close((uv_handle_t*)&server, close_cb); 176 177 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 178 179 ASSERT(close_cb_called == 1); 180 181 MAKE_VALGRIND_HAPPY(); 182 return 0; 183 } 184 185 /* Notes: On Linux uv_bind(server, NULL) will segfault the program. */ 186 187 TEST_IMPL(tcp_bind_error_inval) { 188 struct sockaddr_in addr1; 189 struct sockaddr_in addr2; 190 uv_tcp_t server; 191 int r; 192 193 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1)); 194 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2)); 195 196 r = uv_tcp_init(uv_default_loop(), &server); 197 ASSERT(r == 0); 198 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); 199 ASSERT(r == 0); 200 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); 201 ASSERT(r == UV_EINVAL); 202 203 uv_close((uv_handle_t*)&server, close_cb); 204 205 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 206 207 ASSERT(close_cb_called == 1); 208 209 MAKE_VALGRIND_HAPPY(); 210 return 0; 211 } 212 213 214 TEST_IMPL(tcp_bind_localhost_ok) { 215 struct sockaddr_in addr; 216 uv_tcp_t server; 217 int r; 218 219 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 220 221 r = uv_tcp_init(uv_default_loop(), &server); 222 ASSERT(r == 0); 223 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 224 ASSERT(r == 0); 225 226 MAKE_VALGRIND_HAPPY(); 227 return 0; 228 } 229 230 231 TEST_IMPL(tcp_bind_invalid_flags) { 232 struct sockaddr_in addr; 233 uv_tcp_t server; 234 int r; 235 236 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 237 238 r = uv_tcp_init(uv_default_loop(), &server); 239 ASSERT(r == 0); 240 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); 241 ASSERT(r == UV_EINVAL); 242 243 MAKE_VALGRIND_HAPPY(); 244 return 0; 245 } 246 247 248 TEST_IMPL(tcp_listen_without_bind) { 249 int r; 250 uv_tcp_t server; 251 252 r = uv_tcp_init(uv_default_loop(), &server); 253 ASSERT(r == 0); 254 r = uv_listen((uv_stream_t*)&server, 128, NULL); 255 ASSERT(r == 0); 256 257 MAKE_VALGRIND_HAPPY(); 258 return 0; 259 } 260 261 262 TEST_IMPL(tcp_bind_writable_flags) { 263 struct sockaddr_in addr; 264 uv_tcp_t server; 265 uv_buf_t buf; 266 uv_write_t write_req; 267 uv_shutdown_t shutdown_req; 268 int r; 269 270 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 271 r = uv_tcp_init(uv_default_loop(), &server); 272 ASSERT(r == 0); 273 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 274 ASSERT(r == 0); 275 r = uv_listen((uv_stream_t*)&server, 128, NULL); 276 ASSERT(r == 0); 277 278 ASSERT(0 == uv_is_writable((uv_stream_t*) &server)); 279 ASSERT(0 == uv_is_readable((uv_stream_t*) &server)); 280 281 buf = uv_buf_init("PING", 4); 282 r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); 283 ASSERT(r == UV_EPIPE); 284 r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); 285 ASSERT(r == UV_ENOTCONN); 286 r = uv_read_start((uv_stream_t*) &server, 287 (uv_alloc_cb) abort, 288 (uv_read_cb) abort); 289 ASSERT(r == UV_ENOTCONN); 290 291 uv_close((uv_handle_t*)&server, close_cb); 292 293 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 294 295 ASSERT(close_cb_called == 1); 296 297 MAKE_VALGRIND_HAPPY(); 298 return 0; 299 } 300 301 TEST_IMPL(tcp_bind_or_listen_error_after_close) { 302 uv_tcp_t tcp; 303 struct sockaddr_in addr; 304 305 memset(&addr, 0, sizeof(addr)); 306 addr.sin_addr.s_addr = htonl(INADDR_ANY); 307 addr.sin_port = htons(9999); 308 addr.sin_family = AF_INET; 309 310 ASSERT_EQ(uv_tcp_init(uv_default_loop(), &tcp), 0); 311 uv_close((uv_handle_t*) &tcp, NULL); 312 ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL); 313 ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL); 314 ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0); 315 MAKE_VALGRIND_HAPPY(); 316 return 0; 317 } 318