Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright libuv project 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 
     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 
     35 static int cl_send_cb_called;
     36 static int cl_recv_cb_called;
     37 
     38 static int sv_send_cb_called;
     39 static int sv_recv_cb_called;
     40 
     41 static int close_cb_called;
     42 
     43 
     44 static void sv_alloc_cb(uv_handle_t* handle,
     45                         size_t suggested_size,
     46                         uv_buf_t* buf) {
     47   static char slab[65536];
     48   CHECK_HANDLE(handle);
     49   buf->base = slab;
     50   buf->len = sizeof(slab);
     51 }
     52 
     53 
     54 static void cl_alloc_cb(uv_handle_t* handle,
     55                         size_t suggested_size,
     56                         uv_buf_t* buf) {
     57   /* Do nothing, recv_cb should be called with UV_ENOBUFS. */
     58 }
     59 
     60 
     61 static void close_cb(uv_handle_t* handle) {
     62   CHECK_HANDLE(handle);
     63   ASSERT_EQ(1, uv_is_closing(handle));
     64   close_cb_called++;
     65 }
     66 
     67 
     68 static void cl_recv_cb(uv_udp_t* handle,
     69                        ssize_t nread,
     70                        const uv_buf_t* buf,
     71                        const struct sockaddr* addr,
     72                        unsigned flags) {
     73   CHECK_HANDLE(handle);
     74   ASSERT_OK(flags);
     75   ASSERT_EQ(nread, UV_ENOBUFS);
     76 
     77   cl_recv_cb_called++;
     78 
     79   uv_close((uv_handle_t*) handle, close_cb);
     80 }
     81 
     82 
     83 static void cl_send_cb(uv_udp_send_t* req, int status) {
     84   int r;
     85 
     86   ASSERT_NOT_NULL(req);
     87   ASSERT_OK(status);
     88   CHECK_HANDLE(req->handle);
     89 
     90   r = uv_udp_recv_start(req->handle, cl_alloc_cb, cl_recv_cb);
     91   ASSERT_OK(r);
     92 
     93   cl_send_cb_called++;
     94 }
     95 
     96 
     97 static void sv_send_cb(uv_udp_send_t* req, int status) {
     98   ASSERT_NOT_NULL(req);
     99   ASSERT_OK(status);
    100   CHECK_HANDLE(req->handle);
    101 
    102   uv_close((uv_handle_t*) req->handle, close_cb);
    103   free(req);
    104 
    105   sv_send_cb_called++;
    106 }
    107 
    108 
    109 static void sv_recv_cb(uv_udp_t* handle,
    110                        ssize_t nread,
    111                        const uv_buf_t* rcvbuf,
    112                        const struct sockaddr* addr,
    113                        unsigned flags) {
    114   uv_udp_send_t* req;
    115   uv_buf_t sndbuf;
    116   int r;
    117 
    118   if (nread < 0) {
    119     ASSERT(0 && "unexpected error");
    120   }
    121 
    122   if (nread == 0) {
    123     /* Returning unused buffer. Don't count towards sv_recv_cb_called */
    124     ASSERT_NULL(addr);
    125     return;
    126   }
    127 
    128   CHECK_HANDLE(handle);
    129   ASSERT_OK(flags);
    130 
    131   ASSERT_NOT_NULL(addr);
    132   ASSERT_EQ(4, nread);
    133   ASSERT(!memcmp("PING", rcvbuf->base, nread));
    134 
    135   r = uv_udp_recv_stop(handle);
    136   ASSERT_OK(r);
    137 
    138   req = malloc(sizeof *req);
    139   ASSERT_NOT_NULL(req);
    140 
    141   sndbuf = uv_buf_init("PONG", 4);
    142   r = uv_udp_send(req, handle, &sndbuf, 1, addr, sv_send_cb);
    143   ASSERT_OK(r);
    144 
    145   sv_recv_cb_called++;
    146 }
    147 
    148 
    149 TEST_IMPL(udp_alloc_cb_fail) {
    150   struct sockaddr_in addr;
    151   uv_udp_send_t req;
    152   uv_buf_t buf;
    153   int r;
    154 
    155   ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
    156 
    157   r = uv_udp_init(uv_default_loop(), &server);
    158   ASSERT_OK(r);
    159 
    160   r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
    161   ASSERT_OK(r);
    162 
    163   r = uv_udp_recv_start(&server, sv_alloc_cb, sv_recv_cb);
    164   ASSERT_OK(r);
    165 
    166   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
    167 
    168   r = uv_udp_init(uv_default_loop(), &client);
    169   ASSERT_OK(r);
    170 
    171   buf = uv_buf_init("PING", 4);
    172   r = uv_udp_send(&req,
    173                   &client,
    174                   &buf,
    175                   1,
    176                   (const struct sockaddr*) &addr,
    177                   cl_send_cb);
    178   ASSERT_OK(r);
    179 
    180   ASSERT_OK(close_cb_called);
    181   ASSERT_OK(cl_send_cb_called);
    182   ASSERT_OK(cl_recv_cb_called);
    183   ASSERT_OK(sv_send_cb_called);
    184   ASSERT_OK(sv_recv_cb_called);
    185 
    186   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    187 
    188   ASSERT_EQ(1, cl_send_cb_called);
    189   ASSERT_EQ(1, cl_recv_cb_called);
    190   ASSERT_EQ(1, sv_send_cb_called);
    191   ASSERT_EQ(1, sv_recv_cb_called);
    192   ASSERT_EQ(2, close_cb_called);
    193 
    194   MAKE_VALGRIND_HAPPY(uv_default_loop());
    195   return 0;
    196 }
    197