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 28static int connect_cb_called = 0; 29static int close_cb_called = 0; 30 31 32static void close_cb(uv_handle_t* handle) { 33 ASSERT_NOT_NULL(handle); 34 close_cb_called++; 35} 36 37 38static void connect_cb(uv_connect_t* req, int status) { 39 ASSERT_EQ(status, UV_EADDRINUSE); 40 uv_close((uv_handle_t*) req->handle, close_cb); 41 connect_cb_called++; 42} 43 44 45TEST_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_OK(uv_tcp_init(uv_default_loop(), &conn)); 57 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 58 ASSERT_OK(uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0)); 59 60 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr)); 61 ASSERT_OK(uv_tcp_connect(&req, 62 &conn, 63 (const struct sockaddr*) &addr, 64 connect_cb)); 65 66 addrlen = sizeof(addr); 67 ASSERT_EQ(UV_EADDRINUSE, uv_tcp_getsockname(&conn, 68 (struct sockaddr*) &addr, 69 &addrlen)); 70 71 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 72 ASSERT_EQ(1, connect_cb_called); 73 ASSERT_EQ(1, close_cb_called); 74 75 MAKE_VALGRIND_HAPPY(uv_default_loop()); 76 return 0; 77} 78 79 80TEST_IMPL(tcp_bind_error_addrinuse_listen) { 81 struct sockaddr_in addr; 82 uv_tcp_t server1, server2; 83 int r; 84 85 ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 86 r = uv_tcp_init(uv_default_loop(), &server1); 87 ASSERT_OK(r); 88 r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); 89 ASSERT_OK(r); 90 91 r = uv_tcp_init(uv_default_loop(), &server2); 92 ASSERT_OK(r); 93 r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); 94 ASSERT_OK(r); 95 96 r = uv_listen((uv_stream_t*)&server1, 128, NULL); 97 ASSERT_OK(r); 98 r = uv_listen((uv_stream_t*)&server2, 128, NULL); 99 ASSERT_EQ(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_EQ(2, close_cb_called); 107 108 MAKE_VALGRIND_HAPPY(uv_default_loop()); 109 return 0; 110} 111 112 113TEST_IMPL(tcp_bind_error_addrnotavail_1) { 114 struct sockaddr_in addr; 115 uv_tcp_t server; 116 int r; 117 118 ASSERT_OK(uv_ip4_addr("127.255.255.255", TEST_PORT, &addr)); 119 120 r = uv_tcp_init(uv_default_loop(), &server); 121 ASSERT_OK(r); 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_EQ(1, close_cb_called); 132 133 MAKE_VALGRIND_HAPPY(uv_default_loop()); 134 return 0; 135} 136 137 138TEST_IMPL(tcp_bind_error_addrnotavail_2) { 139 struct sockaddr_in addr; 140 uv_tcp_t server; 141 int r; 142 143 ASSERT_OK(uv_ip4_addr("4.4.4.4", TEST_PORT, &addr)); 144 145 r = uv_tcp_init(uv_default_loop(), &server); 146 ASSERT_OK(r); 147 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 148 ASSERT_EQ(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_EQ(1, close_cb_called); 155 156 MAKE_VALGRIND_HAPPY(uv_default_loop()); 157 return 0; 158} 159 160 161TEST_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_OK(r); 172 r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); 173 ASSERT_EQ(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_EQ(1, close_cb_called); 180 181 MAKE_VALGRIND_HAPPY(uv_default_loop()); 182 return 0; 183} 184 185/* Notes: On Linux uv_bind(server, NULL) will segfault the program. */ 186 187TEST_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_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1)); 194 ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2)); 195 196 r = uv_tcp_init(uv_default_loop(), &server); 197 ASSERT_OK(r); 198 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); 199 ASSERT_OK(r); 200 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); 201 ASSERT_EQ(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_EQ(1, close_cb_called); 208 209 MAKE_VALGRIND_HAPPY(uv_default_loop()); 210 return 0; 211} 212 213 214TEST_IMPL(tcp_bind_localhost_ok) { 215 struct sockaddr_in addr; 216 uv_tcp_t server; 217 int r; 218 219 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 220 221 r = uv_tcp_init(uv_default_loop(), &server); 222 ASSERT_OK(r); 223 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 224 ASSERT_OK(r); 225 226 MAKE_VALGRIND_HAPPY(uv_default_loop()); 227 return 0; 228} 229 230 231TEST_IMPL(tcp_bind_invalid_flags) { 232 struct sockaddr_in addr; 233 uv_tcp_t server; 234 int r; 235 236 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 237 238 r = uv_tcp_init(uv_default_loop(), &server); 239 ASSERT_OK(r); 240 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); 241 ASSERT_EQ(r, UV_EINVAL); 242 243 MAKE_VALGRIND_HAPPY(uv_default_loop()); 244 return 0; 245} 246 247 248TEST_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_OK(r); 254 r = uv_listen((uv_stream_t*)&server, 128, NULL); 255 ASSERT_OK(r); 256 257 MAKE_VALGRIND_HAPPY(uv_default_loop()); 258 return 0; 259} 260 261 262TEST_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_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 271 r = uv_tcp_init(uv_default_loop(), &server); 272 ASSERT_OK(r); 273 r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 274 ASSERT_OK(r); 275 r = uv_listen((uv_stream_t*)&server, 128, NULL); 276 ASSERT_OK(r); 277 278 ASSERT_OK(uv_is_writable((uv_stream_t*) &server)); 279 ASSERT_OK(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_EQ(r, UV_EPIPE); 284 r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); 285 ASSERT_EQ(r, UV_ENOTCONN); 286 r = uv_read_start((uv_stream_t*) &server, 287 (uv_alloc_cb) abort, 288 (uv_read_cb) abort); 289 ASSERT_EQ(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_EQ(1, close_cb_called); 296 297 MAKE_VALGRIND_HAPPY(uv_default_loop()); 298 return 0; 299} 300 301TEST_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_OK(uv_tcp_init(uv_default_loop(), &tcp)); 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_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 315 MAKE_VALGRIND_HAPPY(uv_default_loop()); 316 return 0; 317} 318