1*5f2f4271Schristos /* Copyright libuv project and contributors. All rights reserved.
2*5f2f4271Schristos *
3*5f2f4271Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
4*5f2f4271Schristos * of this software and associated documentation files (the "Software"), to
5*5f2f4271Schristos * deal in the Software without restriction, including without limitation the
6*5f2f4271Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7*5f2f4271Schristos * sell copies of the Software, and to permit persons to whom the Software is
8*5f2f4271Schristos * furnished to do so, subject to the following conditions:
9*5f2f4271Schristos *
10*5f2f4271Schristos * The above copyright notice and this permission notice shall be included in
11*5f2f4271Schristos * all copies or substantial portions of the Software.
12*5f2f4271Schristos *
13*5f2f4271Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14*5f2f4271Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15*5f2f4271Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16*5f2f4271Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17*5f2f4271Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18*5f2f4271Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19*5f2f4271Schristos * IN THE SOFTWARE.
20*5f2f4271Schristos */
21*5f2f4271Schristos
22*5f2f4271Schristos #include "uv.h"
23*5f2f4271Schristos #include "task.h"
24*5f2f4271Schristos
25*5f2f4271Schristos static uv_tcp_t client;
26*5f2f4271Schristos static uv_tcp_t connection;
27*5f2f4271Schristos static uv_connect_t connect_req;
28*5f2f4271Schristos static uv_timer_t timer;
29*5f2f4271Schristos
30*5f2f4271Schristos static int read_cb_called;
31*5f2f4271Schristos static int on_close_called;
32*5f2f4271Schristos
33*5f2f4271Schristos static void on_connection(uv_stream_t* server, int status);
34*5f2f4271Schristos
35*5f2f4271Schristos static void on_client_connect(uv_connect_t* req, int status);
36*5f2f4271Schristos static void on_client_alloc(uv_handle_t* handle,
37*5f2f4271Schristos size_t suggested_size,
38*5f2f4271Schristos uv_buf_t* buf);
39*5f2f4271Schristos static void on_client_read(uv_stream_t* stream,
40*5f2f4271Schristos ssize_t nread,
41*5f2f4271Schristos const uv_buf_t* buf);
42*5f2f4271Schristos static void on_client_timeout(uv_timer_t* handle);
43*5f2f4271Schristos
44*5f2f4271Schristos static void on_close(uv_handle_t* handle);
45*5f2f4271Schristos
46*5f2f4271Schristos
on_client_connect(uv_connect_t * conn_req,int status)47*5f2f4271Schristos static void on_client_connect(uv_connect_t* conn_req, int status) {
48*5f2f4271Schristos int r;
49*5f2f4271Schristos
50*5f2f4271Schristos r = uv_read_start((uv_stream_t*) &client, on_client_alloc, on_client_read);
51*5f2f4271Schristos ASSERT_EQ(r, 0);
52*5f2f4271Schristos
53*5f2f4271Schristos r = uv_timer_start(&timer, on_client_timeout, 1000, 0);
54*5f2f4271Schristos ASSERT_EQ(r, 0);
55*5f2f4271Schristos }
56*5f2f4271Schristos
57*5f2f4271Schristos
on_client_alloc(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)58*5f2f4271Schristos static void on_client_alloc(uv_handle_t* handle,
59*5f2f4271Schristos size_t suggested_size,
60*5f2f4271Schristos uv_buf_t* buf) {
61*5f2f4271Schristos static char slab[8];
62*5f2f4271Schristos buf->base = slab;
63*5f2f4271Schristos buf->len = sizeof(slab);
64*5f2f4271Schristos }
65*5f2f4271Schristos
66*5f2f4271Schristos
on_client_read(uv_stream_t * stream,ssize_t nread,const uv_buf_t * buf)67*5f2f4271Schristos static void on_client_read(uv_stream_t* stream, ssize_t nread,
68*5f2f4271Schristos const uv_buf_t* buf) {
69*5f2f4271Schristos ASSERT_LT(nread, 0);
70*5f2f4271Schristos read_cb_called++;
71*5f2f4271Schristos }
72*5f2f4271Schristos
73*5f2f4271Schristos
on_client_timeout(uv_timer_t * handle)74*5f2f4271Schristos static void on_client_timeout(uv_timer_t* handle) {
75*5f2f4271Schristos ASSERT_EQ(handle, &timer);
76*5f2f4271Schristos ASSERT_EQ(read_cb_called, 0);
77*5f2f4271Schristos uv_read_stop((uv_stream_t*) &client);
78*5f2f4271Schristos uv_close((uv_handle_t*) &client, on_close);
79*5f2f4271Schristos uv_close((uv_handle_t*) &timer, on_close);
80*5f2f4271Schristos }
81*5f2f4271Schristos
82*5f2f4271Schristos
on_connection_alloc(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)83*5f2f4271Schristos static void on_connection_alloc(uv_handle_t* handle,
84*5f2f4271Schristos size_t suggested_size,
85*5f2f4271Schristos uv_buf_t* buf) {
86*5f2f4271Schristos static char slab[8];
87*5f2f4271Schristos buf->base = slab;
88*5f2f4271Schristos buf->len = sizeof(slab);
89*5f2f4271Schristos }
90*5f2f4271Schristos
91*5f2f4271Schristos
on_connection_read(uv_stream_t * stream,ssize_t nread,const uv_buf_t * buf)92*5f2f4271Schristos static void on_connection_read(uv_stream_t* stream,
93*5f2f4271Schristos ssize_t nread,
94*5f2f4271Schristos const uv_buf_t* buf) {
95*5f2f4271Schristos ASSERT_EQ(nread, UV_EOF);
96*5f2f4271Schristos read_cb_called++;
97*5f2f4271Schristos uv_close((uv_handle_t*) stream, on_close);
98*5f2f4271Schristos }
99*5f2f4271Schristos
100*5f2f4271Schristos
on_connection(uv_stream_t * server,int status)101*5f2f4271Schristos static void on_connection(uv_stream_t* server, int status) {
102*5f2f4271Schristos int r;
103*5f2f4271Schristos
104*5f2f4271Schristos ASSERT_EQ(status, 0);
105*5f2f4271Schristos ASSERT_EQ(uv_accept(server, (uv_stream_t*) &connection), 0);
106*5f2f4271Schristos
107*5f2f4271Schristos r = uv_read_start((uv_stream_t*) &connection,
108*5f2f4271Schristos on_connection_alloc,
109*5f2f4271Schristos on_connection_read);
110*5f2f4271Schristos ASSERT_EQ(r, 0);
111*5f2f4271Schristos }
112*5f2f4271Schristos
113*5f2f4271Schristos
on_close(uv_handle_t * handle)114*5f2f4271Schristos static void on_close(uv_handle_t* handle) {
115*5f2f4271Schristos ASSERT(handle == (uv_handle_t*) &client ||
116*5f2f4271Schristos handle == (uv_handle_t*) &connection ||
117*5f2f4271Schristos handle == (uv_handle_t*) &timer);
118*5f2f4271Schristos on_close_called++;
119*5f2f4271Schristos }
120*5f2f4271Schristos
121*5f2f4271Schristos
start_server(uv_loop_t * loop,uv_tcp_t * handle)122*5f2f4271Schristos static void start_server(uv_loop_t* loop, uv_tcp_t* handle) {
123*5f2f4271Schristos struct sockaddr_in addr;
124*5f2f4271Schristos int r;
125*5f2f4271Schristos
126*5f2f4271Schristos ASSERT_EQ(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr), 0);
127*5f2f4271Schristos
128*5f2f4271Schristos r = uv_tcp_init(loop, handle);
129*5f2f4271Schristos ASSERT_EQ(r, 0);
130*5f2f4271Schristos
131*5f2f4271Schristos r = uv_tcp_bind(handle, (const struct sockaddr*) &addr, 0);
132*5f2f4271Schristos ASSERT_EQ(r, 0);
133*5f2f4271Schristos
134*5f2f4271Schristos r = uv_listen((uv_stream_t*) handle, 128, on_connection);
135*5f2f4271Schristos ASSERT_EQ(r, 0);
136*5f2f4271Schristos
137*5f2f4271Schristos uv_unref((uv_handle_t*) handle);
138*5f2f4271Schristos }
139*5f2f4271Schristos
140*5f2f4271Schristos
141*5f2f4271Schristos /* Check that pending write requests have their callbacks
142*5f2f4271Schristos * invoked when the handle is closed.
143*5f2f4271Schristos */
TEST_IMPL(tcp_close_after_read_timeout)144*5f2f4271Schristos TEST_IMPL(tcp_close_after_read_timeout) {
145*5f2f4271Schristos struct sockaddr_in addr;
146*5f2f4271Schristos uv_tcp_t tcp_server;
147*5f2f4271Schristos uv_loop_t* loop;
148*5f2f4271Schristos int r;
149*5f2f4271Schristos
150*5f2f4271Schristos ASSERT_EQ(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr), 0);
151*5f2f4271Schristos
152*5f2f4271Schristos loop = uv_default_loop();
153*5f2f4271Schristos
154*5f2f4271Schristos /* We can't use the echo server, it doesn't handle ECONNRESET. */
155*5f2f4271Schristos start_server(loop, &tcp_server);
156*5f2f4271Schristos
157*5f2f4271Schristos r = uv_tcp_init(loop, &client);
158*5f2f4271Schristos ASSERT_EQ(r, 0);
159*5f2f4271Schristos
160*5f2f4271Schristos r = uv_tcp_connect(&connect_req,
161*5f2f4271Schristos &client,
162*5f2f4271Schristos (const struct sockaddr*) &addr,
163*5f2f4271Schristos on_client_connect);
164*5f2f4271Schristos ASSERT_EQ(r, 0);
165*5f2f4271Schristos
166*5f2f4271Schristos r = uv_tcp_init(loop, &connection);
167*5f2f4271Schristos ASSERT_EQ(r, 0);
168*5f2f4271Schristos
169*5f2f4271Schristos r = uv_timer_init(loop, &timer);
170*5f2f4271Schristos ASSERT_EQ(r, 0);
171*5f2f4271Schristos
172*5f2f4271Schristos ASSERT_EQ(read_cb_called, 0);
173*5f2f4271Schristos ASSERT_EQ(on_close_called, 0);
174*5f2f4271Schristos
175*5f2f4271Schristos r = uv_run(loop, UV_RUN_DEFAULT);
176*5f2f4271Schristos ASSERT_EQ(r, 0);
177*5f2f4271Schristos
178*5f2f4271Schristos ASSERT_EQ(read_cb_called, 1);
179*5f2f4271Schristos ASSERT_EQ(on_close_called, 3);
180*5f2f4271Schristos
181*5f2f4271Schristos MAKE_VALGRIND_HAPPY();
182*5f2f4271Schristos return 0;
183*5f2f4271Schristos }
184