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> 30 # include <sys/socket.h> 31 # include <sys/un.h> 32 #endif 33 34 static int send_cb_called = 0; 35 static int close_cb_called = 0; 36 37 static uv_udp_send_t send_req; 38 39 40 static void startup(void) { 41 #ifdef _WIN32 42 struct WSAData wsa_data; 43 int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); 44 ASSERT(r == 0); 45 #endif 46 } 47 48 49 static uv_os_sock_t create_udp_socket(void) { 50 uv_os_sock_t sock; 51 52 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 53 #ifdef _WIN32 54 ASSERT(sock != INVALID_SOCKET); 55 #else 56 ASSERT(sock >= 0); 57 #endif 58 59 #ifndef _WIN32 60 { 61 /* Allow reuse of the port. */ 62 int yes = 1; 63 int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); 64 ASSERT(r == 0); 65 } 66 #endif 67 68 return sock; 69 } 70 71 72 static void close_socket(uv_os_sock_t sock) { 73 int r; 74 #ifdef _WIN32 75 r = closesocket(sock); 76 #else 77 r = close(sock); 78 #endif 79 ASSERT(r == 0); 80 } 81 82 83 static void alloc_cb(uv_handle_t* handle, 84 size_t suggested_size, 85 uv_buf_t* buf) { 86 static char slab[65536]; 87 ASSERT(suggested_size <= sizeof(slab)); 88 buf->base = slab; 89 buf->len = sizeof(slab); 90 } 91 92 93 static void close_cb(uv_handle_t* handle) { 94 ASSERT_NOT_NULL(handle); 95 close_cb_called++; 96 } 97 98 99 static void recv_cb(uv_udp_t* handle, 100 ssize_t nread, 101 const uv_buf_t* buf, 102 const struct sockaddr* addr, 103 unsigned flags) { 104 int r; 105 106 if (nread < 0) { 107 ASSERT(0 && "unexpected error"); 108 } 109 110 if (nread == 0) { 111 /* Returning unused buffer. Don't count towards sv_recv_cb_called */ 112 ASSERT_NULL(addr); 113 return; 114 } 115 116 ASSERT(flags == 0); 117 118 ASSERT_NOT_NULL(addr); 119 ASSERT(nread == 4); 120 ASSERT(memcmp("PING", buf->base, nread) == 0); 121 122 r = uv_udp_recv_stop(handle); 123 ASSERT(r == 0); 124 125 uv_close((uv_handle_t*) handle, close_cb); 126 } 127 128 129 static void send_cb(uv_udp_send_t* req, int status) { 130 ASSERT_NOT_NULL(req); 131 ASSERT(status == 0); 132 133 send_cb_called++; 134 uv_close((uv_handle_t*)req->handle, close_cb); 135 } 136 137 138 TEST_IMPL(udp_open) { 139 struct sockaddr_in addr; 140 uv_buf_t buf = uv_buf_init("PING", 4); 141 uv_udp_t client, client2; 142 uv_os_sock_t sock; 143 int r; 144 145 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 146 147 startup(); 148 sock = create_udp_socket(); 149 150 r = uv_udp_init(uv_default_loop(), &client); 151 ASSERT(r == 0); 152 153 r = uv_udp_open(&client, sock); 154 ASSERT(r == 0); 155 156 r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); 157 ASSERT(r == 0); 158 159 r = uv_udp_recv_start(&client, alloc_cb, recv_cb); 160 ASSERT(r == 0); 161 162 r = uv_udp_send(&send_req, 163 &client, 164 &buf, 165 1, 166 (const struct sockaddr*) &addr, 167 send_cb); 168 ASSERT(r == 0); 169 170 #ifndef _WIN32 171 { 172 r = uv_udp_init(uv_default_loop(), &client2); 173 ASSERT(r == 0); 174 175 r = uv_udp_open(&client2, sock); 176 ASSERT(r == UV_EEXIST); 177 178 uv_close((uv_handle_t*) &client2, NULL); 179 } 180 #else /* _WIN32 */ 181 (void)client2; 182 #endif 183 184 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 185 186 ASSERT(send_cb_called == 1); 187 ASSERT(close_cb_called == 1); 188 189 ASSERT(client.send_queue_size == 0); 190 191 MAKE_VALGRIND_HAPPY(); 192 return 0; 193 } 194 195 196 TEST_IMPL(udp_open_twice) { 197 uv_udp_t client; 198 uv_os_sock_t sock1, sock2; 199 int r; 200 201 startup(); 202 sock1 = create_udp_socket(); 203 sock2 = create_udp_socket(); 204 205 r = uv_udp_init(uv_default_loop(), &client); 206 ASSERT(r == 0); 207 208 r = uv_udp_open(&client, sock1); 209 ASSERT(r == 0); 210 211 r = uv_udp_open(&client, sock2); 212 ASSERT(r == UV_EBUSY); 213 close_socket(sock2); 214 215 uv_close((uv_handle_t*) &client, NULL); 216 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 217 218 MAKE_VALGRIND_HAPPY(); 219 return 0; 220 } 221 222 TEST_IMPL(udp_open_bound) { 223 struct sockaddr_in addr; 224 uv_udp_t client; 225 uv_os_sock_t sock; 226 int r; 227 228 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 229 230 startup(); 231 sock = create_udp_socket(); 232 233 r = bind(sock, (struct sockaddr*) &addr, sizeof(addr)); 234 ASSERT(r == 0); 235 236 r = uv_udp_init(uv_default_loop(), &client); 237 ASSERT(r == 0); 238 239 r = uv_udp_open(&client, sock); 240 ASSERT(r == 0); 241 242 r = uv_udp_recv_start(&client, alloc_cb, recv_cb); 243 ASSERT(r == 0); 244 245 uv_close((uv_handle_t*) &client, NULL); 246 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 247 248 MAKE_VALGRIND_HAPPY(); 249 return 0; 250 } 251 252 TEST_IMPL(udp_open_connect) { 253 struct sockaddr_in addr; 254 uv_buf_t buf = uv_buf_init("PING", 4); 255 uv_udp_t client; 256 uv_udp_t server; 257 uv_os_sock_t sock; 258 int r; 259 260 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 261 262 startup(); 263 sock = create_udp_socket(); 264 265 r = uv_udp_init(uv_default_loop(), &client); 266 ASSERT(r == 0); 267 268 r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr)); 269 ASSERT(r == 0); 270 271 r = uv_udp_open(&client, sock); 272 ASSERT(r == 0); 273 274 r = uv_udp_init(uv_default_loop(), &server); 275 ASSERT(r == 0); 276 277 r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); 278 ASSERT(r == 0); 279 280 r = uv_udp_recv_start(&server, alloc_cb, recv_cb); 281 ASSERT(r == 0); 282 283 r = uv_udp_send(&send_req, 284 &client, 285 &buf, 286 1, 287 NULL, 288 send_cb); 289 ASSERT(r == 0); 290 291 uv_run(uv_default_loop(), UV_RUN_DEFAULT); 292 293 ASSERT(send_cb_called == 1); 294 ASSERT(close_cb_called == 2); 295 296 ASSERT(client.send_queue_size == 0); 297 298 MAKE_VALGRIND_HAPPY(); 299 return 0; 300 } 301 302 #ifndef _WIN32 303 TEST_IMPL(udp_send_unix) { 304 /* Test that "uv_udp_send()" supports sending over 305 a "sockaddr_un" address. */ 306 struct sockaddr_un addr; 307 uv_udp_t handle; 308 uv_udp_send_t req; 309 uv_loop_t* loop; 310 uv_buf_t buf = uv_buf_init("PING", 4); 311 int fd; 312 int r; 313 314 loop = uv_default_loop(); 315 316 memset(&addr, 0, sizeof addr); 317 addr.sun_family = AF_UNIX; 318 ASSERT(strlen(TEST_PIPENAME) < sizeof(addr.sun_path)); 319 memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME)); 320 321 fd = socket(AF_UNIX, SOCK_STREAM, 0); 322 ASSERT(fd >= 0); 323 324 unlink(TEST_PIPENAME); 325 ASSERT(0 == bind(fd, (const struct sockaddr*)&addr, sizeof addr)); 326 ASSERT(0 == listen(fd, 1)); 327 328 r = uv_udp_init(loop, &handle); 329 ASSERT(r == 0); 330 r = uv_udp_open(&handle, fd); 331 ASSERT(r == 0); 332 uv_run(loop, UV_RUN_DEFAULT); 333 334 r = uv_udp_send(&req, 335 &handle, 336 &buf, 337 1, 338 (const struct sockaddr*) &addr, 339 NULL); 340 ASSERT(r == 0); 341 342 uv_close((uv_handle_t*)&handle, NULL); 343 uv_run(loop, UV_RUN_DEFAULT); 344 close(fd); 345 unlink(TEST_PIPENAME); 346 347 MAKE_VALGRIND_HAPPY(); 348 return 0; 349 } 350 #endif 351