1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include "uv.h" 23e66f31c5Sopenharmony_ci#include "task.h" 24e66f31c5Sopenharmony_ci#include <stdio.h> 25e66f31c5Sopenharmony_ci#include <stdlib.h> 26e66f31c5Sopenharmony_ci#include <string.h> 27e66f31c5Sopenharmony_ci 28e66f31c5Sopenharmony_ci#ifndef _WIN32 29e66f31c5Sopenharmony_ci# include <unistd.h> 30e66f31c5Sopenharmony_ci# include <sys/socket.h> 31e66f31c5Sopenharmony_ci# include <sys/un.h> 32e66f31c5Sopenharmony_ci#endif 33e66f31c5Sopenharmony_ci 34e66f31c5Sopenharmony_cistatic int send_cb_called = 0; 35e66f31c5Sopenharmony_cistatic int close_cb_called = 0; 36e66f31c5Sopenharmony_ci 37e66f31c5Sopenharmony_cistatic uv_udp_send_t send_req; 38e66f31c5Sopenharmony_ci 39e66f31c5Sopenharmony_ci 40e66f31c5Sopenharmony_cistatic void startup(void) { 41e66f31c5Sopenharmony_ci#ifdef _WIN32 42e66f31c5Sopenharmony_ci struct WSAData wsa_data; 43e66f31c5Sopenharmony_ci int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); 44e66f31c5Sopenharmony_ci ASSERT_OK(r); 45e66f31c5Sopenharmony_ci#endif 46e66f31c5Sopenharmony_ci} 47e66f31c5Sopenharmony_ci 48e66f31c5Sopenharmony_ci 49e66f31c5Sopenharmony_cistatic uv_os_sock_t create_udp_socket(void) { 50e66f31c5Sopenharmony_ci uv_os_sock_t sock; 51e66f31c5Sopenharmony_ci 52e66f31c5Sopenharmony_ci sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 53e66f31c5Sopenharmony_ci#ifdef _WIN32 54e66f31c5Sopenharmony_ci ASSERT_NE(sock, INVALID_SOCKET); 55e66f31c5Sopenharmony_ci#else 56e66f31c5Sopenharmony_ci ASSERT_GE(sock, 0); 57e66f31c5Sopenharmony_ci#endif 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ci#ifndef _WIN32 60e66f31c5Sopenharmony_ci { 61e66f31c5Sopenharmony_ci /* Allow reuse of the port. */ 62e66f31c5Sopenharmony_ci int yes = 1; 63e66f31c5Sopenharmony_ci int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); 64e66f31c5Sopenharmony_ci ASSERT_OK(r); 65e66f31c5Sopenharmony_ci } 66e66f31c5Sopenharmony_ci#endif 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_ci return sock; 69e66f31c5Sopenharmony_ci} 70e66f31c5Sopenharmony_ci 71e66f31c5Sopenharmony_ci 72e66f31c5Sopenharmony_cistatic void close_socket(uv_os_sock_t sock) { 73e66f31c5Sopenharmony_ci int r; 74e66f31c5Sopenharmony_ci#ifdef _WIN32 75e66f31c5Sopenharmony_ci r = closesocket(sock); 76e66f31c5Sopenharmony_ci#else 77e66f31c5Sopenharmony_ci r = close(sock); 78e66f31c5Sopenharmony_ci#endif 79e66f31c5Sopenharmony_ci ASSERT_OK(r); 80e66f31c5Sopenharmony_ci} 81e66f31c5Sopenharmony_ci 82e66f31c5Sopenharmony_ci 83e66f31c5Sopenharmony_cistatic void alloc_cb(uv_handle_t* handle, 84e66f31c5Sopenharmony_ci size_t suggested_size, 85e66f31c5Sopenharmony_ci uv_buf_t* buf) { 86e66f31c5Sopenharmony_ci static char slab[65536]; 87e66f31c5Sopenharmony_ci ASSERT_LE(suggested_size, sizeof(slab)); 88e66f31c5Sopenharmony_ci buf->base = slab; 89e66f31c5Sopenharmony_ci buf->len = sizeof(slab); 90e66f31c5Sopenharmony_ci} 91e66f31c5Sopenharmony_ci 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_cistatic void close_cb(uv_handle_t* handle) { 94e66f31c5Sopenharmony_ci ASSERT_NOT_NULL(handle); 95e66f31c5Sopenharmony_ci close_cb_called++; 96e66f31c5Sopenharmony_ci} 97e66f31c5Sopenharmony_ci 98e66f31c5Sopenharmony_ci 99e66f31c5Sopenharmony_cistatic void recv_cb(uv_udp_t* handle, 100e66f31c5Sopenharmony_ci ssize_t nread, 101e66f31c5Sopenharmony_ci const uv_buf_t* buf, 102e66f31c5Sopenharmony_ci const struct sockaddr* addr, 103e66f31c5Sopenharmony_ci unsigned flags) { 104e66f31c5Sopenharmony_ci int r; 105e66f31c5Sopenharmony_ci 106e66f31c5Sopenharmony_ci if (nread < 0) { 107e66f31c5Sopenharmony_ci ASSERT(0 && "unexpected error"); 108e66f31c5Sopenharmony_ci } 109e66f31c5Sopenharmony_ci 110e66f31c5Sopenharmony_ci if (nread == 0) { 111e66f31c5Sopenharmony_ci /* Returning unused buffer. Don't count towards sv_recv_cb_called */ 112e66f31c5Sopenharmony_ci ASSERT_NULL(addr); 113e66f31c5Sopenharmony_ci return; 114e66f31c5Sopenharmony_ci } 115e66f31c5Sopenharmony_ci 116e66f31c5Sopenharmony_ci ASSERT_OK(flags); 117e66f31c5Sopenharmony_ci 118e66f31c5Sopenharmony_ci ASSERT_NOT_NULL(addr); 119e66f31c5Sopenharmony_ci ASSERT_EQ(4, nread); 120e66f31c5Sopenharmony_ci ASSERT_OK(memcmp("PING", buf->base, nread)); 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci r = uv_udp_recv_stop(handle); 123e66f31c5Sopenharmony_ci ASSERT_OK(r); 124e66f31c5Sopenharmony_ci 125e66f31c5Sopenharmony_ci uv_close((uv_handle_t*) handle, close_cb); 126e66f31c5Sopenharmony_ci} 127e66f31c5Sopenharmony_ci 128e66f31c5Sopenharmony_ci 129e66f31c5Sopenharmony_cistatic void send_cb(uv_udp_send_t* req, int status) { 130e66f31c5Sopenharmony_ci ASSERT_NOT_NULL(req); 131e66f31c5Sopenharmony_ci ASSERT_OK(status); 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_ci send_cb_called++; 134e66f31c5Sopenharmony_ci uv_close((uv_handle_t*)req->handle, close_cb); 135e66f31c5Sopenharmony_ci} 136e66f31c5Sopenharmony_ci 137e66f31c5Sopenharmony_ci 138e66f31c5Sopenharmony_ciTEST_IMPL(udp_open) { 139e66f31c5Sopenharmony_ci struct sockaddr_in addr; 140e66f31c5Sopenharmony_ci uv_buf_t buf = uv_buf_init("PING", 4); 141e66f31c5Sopenharmony_ci uv_udp_t client, client2; 142e66f31c5Sopenharmony_ci uv_os_sock_t sock; 143e66f31c5Sopenharmony_ci int r; 144e66f31c5Sopenharmony_ci 145e66f31c5Sopenharmony_ci ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_ci startup(); 148e66f31c5Sopenharmony_ci sock = create_udp_socket(); 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &client); 151e66f31c5Sopenharmony_ci ASSERT_OK(r); 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci r = uv_udp_open(&client, sock); 154e66f31c5Sopenharmony_ci ASSERT_OK(r); 155e66f31c5Sopenharmony_ci 156e66f31c5Sopenharmony_ci r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); 157e66f31c5Sopenharmony_ci ASSERT_OK(r); 158e66f31c5Sopenharmony_ci 159e66f31c5Sopenharmony_ci r = uv_udp_recv_start(&client, alloc_cb, recv_cb); 160e66f31c5Sopenharmony_ci ASSERT_OK(r); 161e66f31c5Sopenharmony_ci 162e66f31c5Sopenharmony_ci r = uv_udp_send(&send_req, 163e66f31c5Sopenharmony_ci &client, 164e66f31c5Sopenharmony_ci &buf, 165e66f31c5Sopenharmony_ci 1, 166e66f31c5Sopenharmony_ci (const struct sockaddr*) &addr, 167e66f31c5Sopenharmony_ci send_cb); 168e66f31c5Sopenharmony_ci ASSERT_OK(r); 169e66f31c5Sopenharmony_ci 170e66f31c5Sopenharmony_ci#ifndef _WIN32 171e66f31c5Sopenharmony_ci { 172e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &client2); 173e66f31c5Sopenharmony_ci ASSERT_OK(r); 174e66f31c5Sopenharmony_ci 175e66f31c5Sopenharmony_ci r = uv_udp_open(&client2, sock); 176e66f31c5Sopenharmony_ci ASSERT_EQ(r, UV_EEXIST); 177e66f31c5Sopenharmony_ci 178e66f31c5Sopenharmony_ci uv_close((uv_handle_t*) &client2, NULL); 179e66f31c5Sopenharmony_ci } 180e66f31c5Sopenharmony_ci#else /* _WIN32 */ 181e66f31c5Sopenharmony_ci (void)client2; 182e66f31c5Sopenharmony_ci#endif 183e66f31c5Sopenharmony_ci 184e66f31c5Sopenharmony_ci uv_run(uv_default_loop(), UV_RUN_DEFAULT); 185e66f31c5Sopenharmony_ci 186e66f31c5Sopenharmony_ci ASSERT_EQ(1, send_cb_called); 187e66f31c5Sopenharmony_ci ASSERT_EQ(1, close_cb_called); 188e66f31c5Sopenharmony_ci 189e66f31c5Sopenharmony_ci ASSERT_OK(client.send_queue_size); 190e66f31c5Sopenharmony_ci 191e66f31c5Sopenharmony_ci MAKE_VALGRIND_HAPPY(uv_default_loop()); 192e66f31c5Sopenharmony_ci return 0; 193e66f31c5Sopenharmony_ci} 194e66f31c5Sopenharmony_ci 195e66f31c5Sopenharmony_ci 196e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_twice) { 197e66f31c5Sopenharmony_ci uv_udp_t client; 198e66f31c5Sopenharmony_ci uv_os_sock_t sock1, sock2; 199e66f31c5Sopenharmony_ci int r; 200e66f31c5Sopenharmony_ci 201e66f31c5Sopenharmony_ci startup(); 202e66f31c5Sopenharmony_ci sock1 = create_udp_socket(); 203e66f31c5Sopenharmony_ci sock2 = create_udp_socket(); 204e66f31c5Sopenharmony_ci 205e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &client); 206e66f31c5Sopenharmony_ci ASSERT_OK(r); 207e66f31c5Sopenharmony_ci 208e66f31c5Sopenharmony_ci r = uv_udp_open(&client, sock1); 209e66f31c5Sopenharmony_ci ASSERT_OK(r); 210e66f31c5Sopenharmony_ci 211e66f31c5Sopenharmony_ci r = uv_udp_open(&client, sock2); 212e66f31c5Sopenharmony_ci ASSERT_EQ(r, UV_EBUSY); 213e66f31c5Sopenharmony_ci close_socket(sock2); 214e66f31c5Sopenharmony_ci 215e66f31c5Sopenharmony_ci uv_close((uv_handle_t*) &client, NULL); 216e66f31c5Sopenharmony_ci uv_run(uv_default_loop(), UV_RUN_DEFAULT); 217e66f31c5Sopenharmony_ci 218e66f31c5Sopenharmony_ci MAKE_VALGRIND_HAPPY(uv_default_loop()); 219e66f31c5Sopenharmony_ci return 0; 220e66f31c5Sopenharmony_ci} 221e66f31c5Sopenharmony_ci 222e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_bound) { 223e66f31c5Sopenharmony_ci struct sockaddr_in addr; 224e66f31c5Sopenharmony_ci uv_udp_t client; 225e66f31c5Sopenharmony_ci uv_os_sock_t sock; 226e66f31c5Sopenharmony_ci int r; 227e66f31c5Sopenharmony_ci 228e66f31c5Sopenharmony_ci ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 229e66f31c5Sopenharmony_ci 230e66f31c5Sopenharmony_ci startup(); 231e66f31c5Sopenharmony_ci sock = create_udp_socket(); 232e66f31c5Sopenharmony_ci 233e66f31c5Sopenharmony_ci r = bind(sock, (struct sockaddr*) &addr, sizeof(addr)); 234e66f31c5Sopenharmony_ci ASSERT_OK(r); 235e66f31c5Sopenharmony_ci 236e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &client); 237e66f31c5Sopenharmony_ci ASSERT_OK(r); 238e66f31c5Sopenharmony_ci 239e66f31c5Sopenharmony_ci r = uv_udp_open(&client, sock); 240e66f31c5Sopenharmony_ci ASSERT_OK(r); 241e66f31c5Sopenharmony_ci 242e66f31c5Sopenharmony_ci r = uv_udp_recv_start(&client, alloc_cb, recv_cb); 243e66f31c5Sopenharmony_ci ASSERT_OK(r); 244e66f31c5Sopenharmony_ci 245e66f31c5Sopenharmony_ci uv_close((uv_handle_t*) &client, NULL); 246e66f31c5Sopenharmony_ci uv_run(uv_default_loop(), UV_RUN_DEFAULT); 247e66f31c5Sopenharmony_ci 248e66f31c5Sopenharmony_ci MAKE_VALGRIND_HAPPY(uv_default_loop()); 249e66f31c5Sopenharmony_ci return 0; 250e66f31c5Sopenharmony_ci} 251e66f31c5Sopenharmony_ci 252e66f31c5Sopenharmony_ciTEST_IMPL(udp_open_connect) { 253e66f31c5Sopenharmony_ci struct sockaddr_in addr; 254e66f31c5Sopenharmony_ci uv_buf_t buf = uv_buf_init("PING", 4); 255e66f31c5Sopenharmony_ci uv_udp_t client; 256e66f31c5Sopenharmony_ci uv_udp_t server; 257e66f31c5Sopenharmony_ci uv_os_sock_t sock; 258e66f31c5Sopenharmony_ci int r; 259e66f31c5Sopenharmony_ci 260e66f31c5Sopenharmony_ci ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 261e66f31c5Sopenharmony_ci 262e66f31c5Sopenharmony_ci startup(); 263e66f31c5Sopenharmony_ci sock = create_udp_socket(); 264e66f31c5Sopenharmony_ci 265e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &client); 266e66f31c5Sopenharmony_ci ASSERT_OK(r); 267e66f31c5Sopenharmony_ci 268e66f31c5Sopenharmony_ci r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr)); 269e66f31c5Sopenharmony_ci ASSERT_OK(r); 270e66f31c5Sopenharmony_ci 271e66f31c5Sopenharmony_ci r = uv_udp_open(&client, sock); 272e66f31c5Sopenharmony_ci ASSERT_OK(r); 273e66f31c5Sopenharmony_ci 274e66f31c5Sopenharmony_ci r = uv_udp_init(uv_default_loop(), &server); 275e66f31c5Sopenharmony_ci ASSERT_OK(r); 276e66f31c5Sopenharmony_ci 277e66f31c5Sopenharmony_ci r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); 278e66f31c5Sopenharmony_ci ASSERT_OK(r); 279e66f31c5Sopenharmony_ci 280e66f31c5Sopenharmony_ci r = uv_udp_recv_start(&server, alloc_cb, recv_cb); 281e66f31c5Sopenharmony_ci ASSERT_OK(r); 282e66f31c5Sopenharmony_ci 283e66f31c5Sopenharmony_ci r = uv_udp_send(&send_req, 284e66f31c5Sopenharmony_ci &client, 285e66f31c5Sopenharmony_ci &buf, 286e66f31c5Sopenharmony_ci 1, 287e66f31c5Sopenharmony_ci NULL, 288e66f31c5Sopenharmony_ci send_cb); 289e66f31c5Sopenharmony_ci ASSERT_OK(r); 290e66f31c5Sopenharmony_ci 291e66f31c5Sopenharmony_ci uv_run(uv_default_loop(), UV_RUN_DEFAULT); 292e66f31c5Sopenharmony_ci 293e66f31c5Sopenharmony_ci ASSERT_EQ(1, send_cb_called); 294e66f31c5Sopenharmony_ci ASSERT_EQ(2, close_cb_called); 295e66f31c5Sopenharmony_ci 296e66f31c5Sopenharmony_ci ASSERT_OK(client.send_queue_size); 297e66f31c5Sopenharmony_ci 298e66f31c5Sopenharmony_ci MAKE_VALGRIND_HAPPY(uv_default_loop()); 299e66f31c5Sopenharmony_ci return 0; 300e66f31c5Sopenharmony_ci} 301e66f31c5Sopenharmony_ci 302e66f31c5Sopenharmony_ci#ifndef _WIN32 303e66f31c5Sopenharmony_ciTEST_IMPL(udp_send_unix) { 304e66f31c5Sopenharmony_ci /* Test that "uv_udp_send()" supports sending over 305e66f31c5Sopenharmony_ci a "sockaddr_un" address. */ 306e66f31c5Sopenharmony_ci struct sockaddr_un addr; 307e66f31c5Sopenharmony_ci uv_udp_t handle; 308e66f31c5Sopenharmony_ci uv_udp_send_t req; 309e66f31c5Sopenharmony_ci uv_loop_t* loop; 310e66f31c5Sopenharmony_ci uv_buf_t buf = uv_buf_init("PING", 4); 311e66f31c5Sopenharmony_ci int fd; 312e66f31c5Sopenharmony_ci int r; 313e66f31c5Sopenharmony_ci 314e66f31c5Sopenharmony_ci loop = uv_default_loop(); 315e66f31c5Sopenharmony_ci 316e66f31c5Sopenharmony_ci memset(&addr, 0, sizeof addr); 317e66f31c5Sopenharmony_ci addr.sun_family = AF_UNIX; 318e66f31c5Sopenharmony_ci ASSERT_LT(strlen(TEST_PIPENAME), sizeof(addr.sun_path)); 319e66f31c5Sopenharmony_ci memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME)); 320e66f31c5Sopenharmony_ci 321e66f31c5Sopenharmony_ci fd = socket(AF_UNIX, SOCK_STREAM, 0); 322e66f31c5Sopenharmony_ci ASSERT_GE(fd, 0); 323e66f31c5Sopenharmony_ci 324e66f31c5Sopenharmony_ci unlink(TEST_PIPENAME); 325e66f31c5Sopenharmony_ci ASSERT_OK(bind(fd, (const struct sockaddr*)&addr, sizeof addr)); 326e66f31c5Sopenharmony_ci ASSERT_OK(listen(fd, 1)); 327e66f31c5Sopenharmony_ci 328e66f31c5Sopenharmony_ci r = uv_udp_init(loop, &handle); 329e66f31c5Sopenharmony_ci ASSERT_OK(r); 330e66f31c5Sopenharmony_ci r = uv_udp_open(&handle, fd); 331e66f31c5Sopenharmony_ci ASSERT_OK(r); 332e66f31c5Sopenharmony_ci uv_run(loop, UV_RUN_DEFAULT); 333e66f31c5Sopenharmony_ci 334e66f31c5Sopenharmony_ci r = uv_udp_send(&req, 335e66f31c5Sopenharmony_ci &handle, 336e66f31c5Sopenharmony_ci &buf, 337e66f31c5Sopenharmony_ci 1, 338e66f31c5Sopenharmony_ci (const struct sockaddr*) &addr, 339e66f31c5Sopenharmony_ci NULL); 340e66f31c5Sopenharmony_ci ASSERT_OK(r); 341e66f31c5Sopenharmony_ci 342e66f31c5Sopenharmony_ci uv_close((uv_handle_t*)&handle, NULL); 343e66f31c5Sopenharmony_ci uv_run(loop, UV_RUN_DEFAULT); 344e66f31c5Sopenharmony_ci close(fd); 345e66f31c5Sopenharmony_ci unlink(TEST_PIPENAME); 346e66f31c5Sopenharmony_ci 347e66f31c5Sopenharmony_ci MAKE_VALGRIND_HAPPY(loop); 348e66f31c5Sopenharmony_ci return 0; 349e66f31c5Sopenharmony_ci} 350e66f31c5Sopenharmony_ci#endif 351