libuv-svace-build
201 строка · 5.3 Кб
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
25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28
29#define CHECK_HANDLE(handle) \30ASSERT_NE((uv_udp_t*)(handle) == &client || (uv_udp_t*)(handle) == &client2, 0)31
32static uv_udp_t client;33static uv_udp_t client2;34static uv_timer_t timer;35
36static int send_cb_called;37static int recv_cb_called;38static int close_cb_called;39static int alloc_cb_called;40static int timer_cb_called;41static int can_recverr;42
43
44static void alloc_cb(uv_handle_t* handle,45size_t suggested_size,46uv_buf_t* buf) {47static char slab[65536];48CHECK_HANDLE(handle);49ASSERT_LE(suggested_size, sizeof(slab));50buf->base = slab;51buf->len = sizeof(slab);52alloc_cb_called++;53}
54
55
56static void close_cb(uv_handle_t* handle) {57ASSERT_EQ(1, uv_is_closing(handle));58close_cb_called++;59}
60
61
62static void send_cb(uv_udp_send_t* req, int status) {63ASSERT_NOT_NULL(req);64ASSERT_OK(status);65ASSERT_OK(status);66CHECK_HANDLE(req->handle);67send_cb_called++;68}
69
70static void send_cb_recverr(uv_udp_send_t* req, int status) {71ASSERT_PTR_NE(req, NULL);72ASSERT(status == 0 || status == UV_ECONNREFUSED);73CHECK_HANDLE(req->handle);74send_cb_called++;75}
76
77static void recv_cb(uv_udp_t* handle,78ssize_t nread,79const uv_buf_t* rcvbuf,80const struct sockaddr* addr,81unsigned flags) {82CHECK_HANDLE(handle);83recv_cb_called++;84
85if (nread < 0) {86ASSERT(0 && "unexpected error");87} else if (nread == 0) {88/* Returning unused buffer */89ASSERT_NULL(addr);90} else {91ASSERT_NOT_NULL(addr);92}93}
94
95
96static void timer_cb(uv_timer_t* h) {97ASSERT_PTR_EQ(h, &timer);98timer_cb_called++;99uv_close((uv_handle_t*) &client, close_cb);100if (can_recverr)101uv_close((uv_handle_t*) &client2, close_cb);102uv_close((uv_handle_t*) h, close_cb);103}
104
105
106TEST_IMPL(udp_send_unreachable) {107struct sockaddr_in addr;108struct sockaddr_in addr2;109struct sockaddr_in addr3;110uv_udp_send_t req1, req2, req3, req4;111uv_buf_t buf;112int r;113
114#ifdef __linux__115can_recverr = 1;116#endif117
118ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));119ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT_2, &addr2));120ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT_3, &addr3));121
122r = uv_timer_init( uv_default_loop(), &timer );123ASSERT_OK(r);124
125r = uv_timer_start( &timer, timer_cb, 1000, 0 );126ASSERT_OK(r);127
128r = uv_udp_init(uv_default_loop(), &client);129ASSERT_OK(r);130
131r = uv_udp_bind(&client, (const struct sockaddr*) &addr2, 0);132ASSERT_OK(r);133
134r = uv_udp_recv_start(&client, alloc_cb, recv_cb);135ASSERT_OK(r);136
137/* client sends "PING", then "PANG" */138buf = uv_buf_init("PING", 4);139
140r = uv_udp_send(&req1,141&client,142&buf,1431,144(const struct sockaddr*) &addr,145send_cb);146ASSERT_OK(r);147
148buf = uv_buf_init("PANG", 4);149
150r = uv_udp_send(&req2,151&client,152&buf,1531,154(const struct sockaddr*) &addr,155send_cb);156ASSERT_OK(r);157
158if (can_recverr) {159r = uv_udp_init(uv_default_loop(), &client2);160ASSERT_OK(r);161
162r = uv_udp_bind(&client2,163(const struct sockaddr*) &addr3,164UV_UDP_LINUX_RECVERR);165ASSERT_OK(r);166
167r = uv_udp_recv_start(&client2, alloc_cb, recv_cb);168ASSERT_OK(r);169
170/* client sends "PING", then "PANG" */171buf = uv_buf_init("PING", 4);172
173r = uv_udp_send(&req3,174&client2,175&buf,1761,177(const struct sockaddr*) &addr,178send_cb_recverr);179ASSERT_OK(r);180
181buf = uv_buf_init("PANG", 4);182
183r = uv_udp_send(&req4,184&client2,185&buf,1861,187(const struct sockaddr*) &addr,188send_cb_recverr);189ASSERT_OK(r);190}191
192uv_run(uv_default_loop(), UV_RUN_DEFAULT);193
194ASSERT_EQ(send_cb_called, (long)(can_recverr ? 4 : 2));195ASSERT_EQ(recv_cb_called, alloc_cb_called);196ASSERT_EQ(1, timer_cb_called);197ASSERT_EQ(close_cb_called, (long)(can_recverr ? 3 : 2));198
199MAKE_VALGRIND_HAPPY(uv_default_loop());200return 0;201}
202