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