Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright libuv project and 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 
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 
     29 #define CHECK_HANDLE(handle) \
     30   ASSERT_NE((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client, 0)
     31 
     32 static uv_udp_t server;
     33 static uv_udp_t client;
     34 static uv_buf_t buf;
     35 static struct sockaddr_in6 lo_addr;
     36 
     37 static int cl_send_cb_called;
     38 static int sv_recv_cb_called;
     39 
     40 static int close_cb_called;
     41 
     42 
     43 static void alloc_cb(uv_handle_t* handle,
     44                      size_t suggested_size,
     45                      uv_buf_t* buf) {
     46   static char slab[65536];
     47   CHECK_HANDLE(handle);
     48   ASSERT_LE(suggested_size, sizeof(slab));
     49   buf->base = slab;
     50   buf->len = sizeof(slab);
     51 }
     52 
     53 
     54 static void close_cb(uv_handle_t* handle) {
     55   CHECK_HANDLE(handle);
     56   ASSERT(uv_is_closing(handle));
     57   close_cb_called++;
     58 }
     59 
     60 
     61 static void cl_send_cb(uv_udp_send_t* req, int status) {
     62   int r;
     63 
     64   ASSERT_NOT_NULL(req);
     65   ASSERT_OK(status);
     66   CHECK_HANDLE(req->handle);
     67   if (++cl_send_cb_called == 1) {
     68     uv_udp_connect(&client, NULL);
     69     r = uv_udp_send(req, &client, &buf, 1, NULL, cl_send_cb);
     70     ASSERT_EQ(r, UV_EDESTADDRREQ);
     71     r = uv_udp_send(req,
     72                     &client,
     73                     &buf,
     74                     1,
     75                     (const struct sockaddr*) &lo_addr,
     76                     cl_send_cb);
     77     ASSERT_OK(r);
     78   }
     79 
     80 }
     81 
     82 
     83 static void sv_recv_cb(uv_udp_t* handle,
     84                        ssize_t nread,
     85                        const uv_buf_t* rcvbuf,
     86                        const struct sockaddr* addr,
     87                        unsigned flags) {
     88   if (nread > 0) {
     89     ASSERT_EQ(4, nread);
     90     ASSERT_NOT_NULL(addr);
     91     ASSERT_OK(memcmp("EXIT", rcvbuf->base, nread));
     92     if (++sv_recv_cb_called == 4) {
     93       uv_close((uv_handle_t*) &server, close_cb);
     94       uv_close((uv_handle_t*) &client, close_cb);
     95     }
     96   }
     97 }
     98 
     99 
    100 TEST_IMPL(udp_connect6) {
    101 #if defined(__OpenBSD__)
    102   RETURN_SKIP("Test does not currently work in OpenBSD");
    103 #endif
    104   uv_udp_send_t req;
    105   struct sockaddr_in6 ext_addr;
    106   struct sockaddr_in6 tmp_addr;
    107   int r;
    108   int addrlen;
    109 
    110   if (!can_ipv6())
    111     RETURN_SKIP("IPv6 not supported");
    112 
    113   ASSERT_OK(uv_ip6_addr("::", TEST_PORT, &lo_addr));
    114 
    115   r = uv_udp_init(uv_default_loop(), &server);
    116   ASSERT_OK(r);
    117 
    118   r = uv_udp_bind(&server, (const struct sockaddr*) &lo_addr, 0);
    119   ASSERT_OK(r);
    120 
    121   r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
    122   ASSERT_OK(r);
    123 
    124   r = uv_udp_init(uv_default_loop(), &client);
    125   ASSERT_OK(r);
    126 
    127   buf = uv_buf_init("EXIT", 4);
    128 
    129   /* connect() to INADDR_ANY fails on Windows wih WSAEADDRNOTAVAIL */
    130   ASSERT_OK(uv_ip6_addr("::", TEST_PORT, &tmp_addr));
    131   r = uv_udp_connect(&client, (const struct sockaddr*) &tmp_addr);
    132 #ifdef _WIN32
    133   ASSERT_EQ(r, UV_EADDRNOTAVAIL);
    134 #else
    135   ASSERT_OK(r);
    136   r = uv_udp_connect(&client, NULL);
    137   ASSERT_OK(r);
    138 #endif
    139 
    140   ASSERT_OK(uv_ip6_addr("2001:4860:4860::8888", TEST_PORT, &ext_addr));
    141   ASSERT_OK(uv_ip6_addr("::1", TEST_PORT, &lo_addr));
    142 
    143   r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
    144   ASSERT_OK(r);
    145   r = uv_udp_connect(&client, (const struct sockaddr*) &ext_addr);
    146   ASSERT_EQ(r, UV_EISCONN);
    147 
    148   addrlen = sizeof(tmp_addr);
    149   r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
    150   ASSERT_OK(r);
    151 
    152   /* To send messages in connected UDP sockets addr must be NULL */
    153   r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
    154   ASSERT_EQ(r, UV_EISCONN);
    155   r = uv_udp_try_send(&client, &buf, 1, NULL);
    156   ASSERT_EQ(4, r);
    157   r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &ext_addr);
    158   ASSERT_EQ(r, UV_EISCONN);
    159 
    160   r = uv_udp_connect(&client, NULL);
    161   ASSERT_OK(r);
    162   r = uv_udp_connect(&client, NULL);
    163   ASSERT_EQ(r, UV_ENOTCONN);
    164 
    165   addrlen = sizeof(tmp_addr);
    166   r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
    167   ASSERT_EQ(r, UV_ENOTCONN);
    168 
    169   /* To send messages in disconnected UDP sockets addr must be set */
    170   r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
    171   ASSERT_EQ(4, r);
    172   r = uv_udp_try_send(&client, &buf, 1, NULL);
    173   ASSERT_EQ(r, UV_EDESTADDRREQ);
    174 
    175 
    176   r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
    177   ASSERT_OK(r);
    178   r = uv_udp_send(&req,
    179                   &client,
    180                   &buf,
    181                   1,
    182                   (const struct sockaddr*) &lo_addr,
    183                   cl_send_cb);
    184   ASSERT_EQ(r, UV_EISCONN);
    185   r = uv_udp_send(&req, &client, &buf, 1, NULL, cl_send_cb);
    186   ASSERT_OK(r);
    187 
    188   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    189 
    190   ASSERT_EQ(2, close_cb_called);
    191   ASSERT_EQ(4, sv_recv_cb_called);
    192   ASSERT_EQ(2, cl_send_cb_called);
    193 
    194   ASSERT_OK(client.send_queue_size);
    195   ASSERT_OK(server.send_queue_size);
    196 
    197   MAKE_VALGRIND_HAPPY(uv_default_loop());
    198   return 0;
    199 }
    200