libuv-svace-build
340 строк · 8.0 Кб
1/* Copyright libuv project 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 <errno.h>26#include <string.h> /* memset */27
28#ifdef _WIN3229# define INVALID_FD (INVALID_HANDLE_VALUE)30#else31# define INVALID_FD (-1)32#endif33
34static uv_loop_t* loop;35static uv_tcp_t tcp_server;36static uv_tcp_t tcp_client;37static uv_tcp_t tcp_accepted;38static uv_connect_t connect_req;39static uv_shutdown_t shutdown_req;40static uv_write_t write_reqs[4];41
42static int client_close;43static int shutdown_before_close;44
45static int write_cb_called;46static int close_cb_called;47static int shutdown_cb_called;48
49static void connect_cb(uv_connect_t* req, int status);50static void write_cb(uv_write_t* req, int status);51static void close_cb(uv_handle_t* handle);52static void shutdown_cb(uv_shutdown_t* req, int status);53
54static int read_size;55
56
57static void do_write(uv_tcp_t* handle) {58uv_buf_t buf;59unsigned i;60int r;61
62buf = uv_buf_init("PING", 4);63for (i = 0; i < ARRAY_SIZE(write_reqs); i++) {64r = uv_write(&write_reqs[i], (uv_stream_t*) handle, &buf, 1, write_cb);65ASSERT_OK(r);66}67}
68
69
70static void do_close(uv_tcp_t* handle) {71uv_os_fd_t fd;72int r;73
74if (shutdown_before_close == 1) {75ASSERT_OK(uv_shutdown(&shutdown_req,76(uv_stream_t*) handle,77shutdown_cb));78ASSERT_EQ(UV_EINVAL, uv_tcp_close_reset(handle, close_cb));79} else if (shutdown_before_close == 2) {80r = uv_fileno((const uv_handle_t*) handle, &fd);81ASSERT_OK(r);82#ifdef _WIN3283ASSERT_PTR_NE(fd, INVALID_FD);84ASSERT_OK(shutdown((SOCKET)fd, SD_BOTH));85#else86ASSERT_NE(fd, INVALID_FD);87ASSERT_OK(shutdown(fd, SHUT_RDWR));88#endif89ASSERT_OK(uv_tcp_close_reset(handle, close_cb));90} else {91ASSERT_OK(uv_tcp_close_reset(handle, close_cb));92ASSERT_EQ(UV_ENOTCONN, uv_shutdown(&shutdown_req, (uv_stream_t*) handle,93shutdown_cb));94}95
96uv_close((uv_handle_t*) &tcp_server, NULL);97}
98
99static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {100static char slab[1024];101buf->base = slab;102buf->len = sizeof(slab);103}
104
105static void read_cb2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {106ASSERT_PTR_EQ((uv_tcp_t*)stream, &tcp_client);107if (nread == UV_EOF)108uv_close((uv_handle_t*) stream, NULL);109}
110
111
112static void connect_cb(uv_connect_t* conn_req, int status) {113ASSERT_PTR_EQ(conn_req, &connect_req);114uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb2);115do_write(&tcp_client);116if (client_close)117do_close(&tcp_client);118}
119
120
121static void write_cb(uv_write_t* req, int status) {122/* write callbacks should run before the close callback */123ASSERT_OK(close_cb_called);124ASSERT_PTR_EQ(req->handle, (uv_stream_t*)&tcp_client);125write_cb_called++;126}
127
128
129static void close_cb(uv_handle_t* handle) {130if (client_close)131ASSERT_PTR_EQ(handle, (uv_handle_t*) &tcp_client);132else133ASSERT_PTR_EQ(handle, (uv_handle_t*) &tcp_accepted);134
135close_cb_called++;136}
137
138static void shutdown_cb(uv_shutdown_t* req, int status) {139if (client_close)140ASSERT_PTR_EQ(req->handle, (uv_stream_t*) &tcp_client);141else142ASSERT_PTR_EQ(req->handle, (uv_stream_t*) &tcp_accepted);143
144shutdown_cb_called++;145}
146
147
148static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {149ASSERT_PTR_EQ((uv_tcp_t*)stream, &tcp_accepted);150if (nread < 0) {151uv_close((uv_handle_t*) stream, NULL);152} else {153read_size += nread;154if (read_size == 16 && client_close == 0)155do_close(&tcp_accepted);156}157}
158
159
160static void connection_cb(uv_stream_t* server, int status) {161ASSERT_OK(status);162
163ASSERT_OK(uv_tcp_init(loop, &tcp_accepted));164ASSERT_OK(uv_accept(server, (uv_stream_t*) &tcp_accepted));165
166uv_read_start((uv_stream_t*) &tcp_accepted, alloc_cb, read_cb);167}
168
169
170static void start_server(uv_loop_t* loop, uv_tcp_t* handle) {171struct sockaddr_in addr;172int r;173
174ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));175
176r = uv_tcp_init(loop, handle);177ASSERT_OK(r);178
179r = uv_tcp_bind(handle, (const struct sockaddr*) &addr, 0);180ASSERT_OK(r);181
182r = uv_listen((uv_stream_t*)handle, 128, connection_cb);183ASSERT_OK(r);184}
185
186
187static void do_connect(uv_loop_t* loop, uv_tcp_t* tcp_client) {188struct sockaddr_in addr;189int r;190
191ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));192
193r = uv_tcp_init(loop, tcp_client);194ASSERT_OK(r);195
196r = uv_tcp_connect(&connect_req,197tcp_client,198(const struct sockaddr*) &addr,199connect_cb);200ASSERT_OK(r);201}
202
203
204/* Check that pending write requests have their callbacks
205* invoked when the handle is closed.
206*/
207TEST_IMPL(tcp_close_reset_client) {208int r;209
210loop = uv_default_loop();211
212start_server(loop, &tcp_server);213
214client_close = 1;215shutdown_before_close = 0;216
217do_connect(loop, &tcp_client);218
219ASSERT_OK(write_cb_called);220ASSERT_OK(close_cb_called);221ASSERT_OK(shutdown_cb_called);222
223r = uv_run(loop, UV_RUN_DEFAULT);224ASSERT_OK(r);225
226ASSERT_EQ(4, write_cb_called);227ASSERT_EQ(1, close_cb_called);228ASSERT_OK(shutdown_cb_called);229
230MAKE_VALGRIND_HAPPY(loop);231return 0;232}
233
234TEST_IMPL(tcp_close_reset_client_after_shutdown) {235int r;236
237loop = uv_default_loop();238
239start_server(loop, &tcp_server);240
241client_close = 1;242shutdown_before_close = 1;243
244do_connect(loop, &tcp_client);245
246ASSERT_OK(write_cb_called);247ASSERT_OK(close_cb_called);248ASSERT_OK(shutdown_cb_called);249
250r = uv_run(loop, UV_RUN_DEFAULT);251ASSERT_OK(r);252
253ASSERT_EQ(4, write_cb_called);254ASSERT_OK(close_cb_called);255ASSERT_EQ(1, shutdown_cb_called);256
257MAKE_VALGRIND_HAPPY(loop);258return 0;259}
260
261TEST_IMPL(tcp_close_reset_accepted) {262int r;263
264loop = uv_default_loop();265
266start_server(loop, &tcp_server);267
268client_close = 0;269shutdown_before_close = 0;270
271do_connect(loop, &tcp_client);272
273ASSERT_OK(write_cb_called);274ASSERT_OK(close_cb_called);275ASSERT_OK(shutdown_cb_called);276
277r = uv_run(loop, UV_RUN_DEFAULT);278ASSERT_OK(r);279
280ASSERT_EQ(4, write_cb_called);281ASSERT_EQ(1, close_cb_called);282ASSERT_OK(shutdown_cb_called);283
284MAKE_VALGRIND_HAPPY(loop);285return 0;286}
287
288TEST_IMPL(tcp_close_reset_accepted_after_shutdown) {289int r;290
291loop = uv_default_loop();292
293start_server(loop, &tcp_server);294
295client_close = 0;296shutdown_before_close = 1;297
298do_connect(loop, &tcp_client);299
300ASSERT_OK(write_cb_called);301ASSERT_OK(close_cb_called);302ASSERT_OK(shutdown_cb_called);303
304r = uv_run(loop, UV_RUN_DEFAULT);305ASSERT_OK(r);306
307ASSERT_EQ(4, write_cb_called);308ASSERT_OK(close_cb_called);309ASSERT_EQ(1, shutdown_cb_called);310
311MAKE_VALGRIND_HAPPY(loop);312return 0;313}
314
315TEST_IMPL(tcp_close_reset_accepted_after_socket_shutdown) {316int r;317
318loop = uv_default_loop();319
320start_server(loop, &tcp_server);321
322client_close = 0;323shutdown_before_close = 2;324
325do_connect(loop, &tcp_client);326
327ASSERT_OK(write_cb_called);328ASSERT_OK(close_cb_called);329ASSERT_OK(shutdown_cb_called);330
331r = uv_run(loop, UV_RUN_DEFAULT);332ASSERT_OK(r);333
334ASSERT_EQ(4, write_cb_called);335ASSERT_EQ(1, close_cb_called);336ASSERT_OK(shutdown_cb_called);337
338MAKE_VALGRIND_HAPPY(loop);339return 0;340}
341