|
160
|
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 static uv_tcp_t server;
|
|
|
26 static uv_tcp_t connection;
|
|
|
27 static int read_cb_called = 0;
|
|
|
28
|
|
|
29 static uv_tcp_t client;
|
|
|
30 static uv_connect_t connect_req;
|
|
|
31
|
|
|
32
|
|
|
33 static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
|
|
34
|
|
|
35 static void on_write_close_immediately(uv_write_t* req, int status) {
|
|
|
36 ASSERT_OK(status);
|
|
|
37
|
|
|
38 uv_close((uv_handle_t*)req->handle, NULL); /* Close immediately */
|
|
|
39 free(req);
|
|
|
40 }
|
|
|
41
|
|
|
42 static void on_write(uv_write_t* req, int status) {
|
|
|
43 ASSERT_OK(status);
|
|
|
44
|
|
|
45 free(req);
|
|
|
46 }
|
|
|
47
|
|
|
48 static void do_write(uv_stream_t* stream, uv_write_cb cb) {
|
|
|
49 uv_write_t* req = malloc(sizeof(*req));
|
|
|
50 uv_buf_t buf;
|
|
|
51 buf.base = "1234578";
|
|
|
52 buf.len = 8;
|
|
|
53 ASSERT_OK(uv_write(req, stream, &buf, 1, cb));
|
|
|
54 }
|
|
|
55
|
|
|
56 static void on_alloc(uv_handle_t* handle,
|
|
|
57 size_t suggested_size,
|
|
|
58 uv_buf_t* buf) {
|
|
|
59 static char slab[65536];
|
|
|
60 buf->base = slab;
|
|
|
61 buf->len = sizeof(slab);
|
|
|
62 }
|
|
|
63
|
|
|
64 static void on_read1(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
|
|
65 ASSERT_GE(nread, 0);
|
|
|
66
|
|
|
67 /* Do write on a half open connection to force WSAECONNABORTED (on Windows)
|
|
|
68 * in the subsequent uv_read_start()
|
|
|
69 */
|
|
|
70 do_write(stream, on_write);
|
|
|
71
|
|
|
72 ASSERT_OK(uv_read_stop(stream));
|
|
|
73
|
|
|
74 ASSERT_OK(uv_read_start(stream, on_alloc, on_read2));
|
|
|
75
|
|
|
76 read_cb_called++;
|
|
|
77 }
|
|
|
78
|
|
|
79 static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
|
|
80 ASSERT_LT(nread, 0);
|
|
|
81
|
|
|
82 uv_close((uv_handle_t*)stream, NULL);
|
|
|
83 uv_close((uv_handle_t*)&server, NULL);
|
|
|
84
|
|
|
85 read_cb_called++;
|
|
|
86 }
|
|
|
87
|
|
|
88 static void on_connection(uv_stream_t* server, int status) {
|
|
|
89 ASSERT_OK(status);
|
|
|
90
|
|
|
91 ASSERT_OK(uv_tcp_init(server->loop, &connection));
|
|
|
92
|
|
|
93 ASSERT_OK(uv_accept(server, (uv_stream_t* )&connection));
|
|
|
94
|
|
|
95 ASSERT_OK(uv_read_start((uv_stream_t*)&connection, on_alloc, on_read1));
|
|
|
96 }
|
|
|
97
|
|
|
98 static void on_connect(uv_connect_t* req, int status) {
|
|
|
99 ASSERT_OK(status);
|
|
|
100
|
|
|
101 do_write((uv_stream_t*)&client, on_write_close_immediately);
|
|
|
102 }
|
|
|
103
|
|
|
104 TEST_IMPL(tcp_read_stop_start) {
|
|
|
105 uv_loop_t* loop = uv_default_loop();
|
|
|
106
|
|
|
107 { /* Server */
|
|
|
108 struct sockaddr_in addr;
|
|
|
109
|
|
|
110 ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
|
|
|
111
|
|
|
112 ASSERT_OK(uv_tcp_init(loop, &server));
|
|
|
113
|
|
|
114 ASSERT_OK(uv_tcp_bind(&server, (struct sockaddr*) & addr, 0));
|
|
|
115
|
|
|
116 ASSERT_OK(uv_listen((uv_stream_t*)&server, 10, on_connection));
|
|
|
117 }
|
|
|
118
|
|
|
119 { /* Client */
|
|
|
120 struct sockaddr_in addr;
|
|
|
121
|
|
|
122 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
|
|
|
123
|
|
|
124 ASSERT_OK(uv_tcp_init(loop, &client));
|
|
|
125
|
|
|
126 ASSERT_OK(uv_tcp_connect(&connect_req, &client,
|
|
|
127 (const struct sockaddr*) & addr, on_connect));
|
|
|
128 }
|
|
|
129
|
|
|
130 ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
|
|
|
131
|
|
|
132 ASSERT_GE(read_cb_called, 2);
|
|
|
133
|
|
|
134 MAKE_VALGRIND_HAPPY(loop);
|
|
|
135 return 0;
|
|
|
136 }
|