1fbb2e0a3Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2fbb2e0a3Schristos *
3fbb2e0a3Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
4fbb2e0a3Schristos * of this software and associated documentation files (the "Software"), to
5fbb2e0a3Schristos * deal in the Software without restriction, including without limitation the
6fbb2e0a3Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7fbb2e0a3Schristos * sell copies of the Software, and to permit persons to whom the Software is
8fbb2e0a3Schristos * furnished to do so, subject to the following conditions:
9fbb2e0a3Schristos *
10fbb2e0a3Schristos * The above copyright notice and this permission notice shall be included in
11fbb2e0a3Schristos * all copies or substantial portions of the Software.
12fbb2e0a3Schristos *
13fbb2e0a3Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14fbb2e0a3Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15fbb2e0a3Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16fbb2e0a3Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17fbb2e0a3Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18fbb2e0a3Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19fbb2e0a3Schristos * IN THE SOFTWARE.
20fbb2e0a3Schristos */
21fbb2e0a3Schristos
22fbb2e0a3Schristos #include "uv.h"
23fbb2e0a3Schristos #include "task.h"
24fbb2e0a3Schristos
25fbb2e0a3Schristos #include <stdio.h>
26fbb2e0a3Schristos #include <string.h>
27fbb2e0a3Schristos
28fbb2e0a3Schristos static uv_pipe_t channel;
29fbb2e0a3Schristos static uv_tcp_t tcp_server;
30fbb2e0a3Schristos static uv_tcp_t tcp_server2;
31fbb2e0a3Schristos static uv_tcp_t tcp_connection;
32fbb2e0a3Schristos
33fbb2e0a3Schristos static int exit_cb_called;
34fbb2e0a3Schristos static int read_cb_called;
35fbb2e0a3Schristos static int tcp_write_cb_called;
36fbb2e0a3Schristos static int tcp_read_cb_called;
37fbb2e0a3Schristos static int on_pipe_read_called;
38fbb2e0a3Schristos static int local_conn_accepted;
39fbb2e0a3Schristos static int remote_conn_accepted;
40fbb2e0a3Schristos static int tcp_server_listening;
41fbb2e0a3Schristos static uv_write_t write_req;
42fbb2e0a3Schristos static uv_write_t write_req2;
43fbb2e0a3Schristos static uv_write_t conn_notify_req;
44fbb2e0a3Schristos static int close_cb_called;
45fbb2e0a3Schristos static int connection_accepted;
46fbb2e0a3Schristos static int tcp_conn_read_cb_called;
47fbb2e0a3Schristos static int tcp_conn_write_cb_called;
48fbb2e0a3Schristos static int send_zero_write;
49fbb2e0a3Schristos
50fbb2e0a3Schristos typedef struct {
51fbb2e0a3Schristos uv_connect_t conn_req;
52fbb2e0a3Schristos uv_write_t tcp_write_req;
53fbb2e0a3Schristos uv_tcp_t conn;
54fbb2e0a3Schristos } tcp_conn;
55fbb2e0a3Schristos
56fbb2e0a3Schristos #define CONN_COUNT 100
57fbb2e0a3Schristos #define BACKLOG 128
58fbb2e0a3Schristos
59fbb2e0a3Schristos
close_server_conn_cb(uv_handle_t * handle)60fbb2e0a3Schristos static void close_server_conn_cb(uv_handle_t* handle) {
61fbb2e0a3Schristos free(handle);
62fbb2e0a3Schristos }
63fbb2e0a3Schristos
64fbb2e0a3Schristos
on_connection(uv_stream_t * server,int status)65fbb2e0a3Schristos static void on_connection(uv_stream_t* server, int status) {
66fbb2e0a3Schristos uv_tcp_t* conn;
67fbb2e0a3Schristos int r;
68fbb2e0a3Schristos
69fbb2e0a3Schristos if (!local_conn_accepted) {
70fbb2e0a3Schristos /* Accept the connection and close it. Also and close the server. */
71fbb2e0a3Schristos ASSERT_EQ(status, 0);
72fbb2e0a3Schristos ASSERT_PTR_EQ(&tcp_server, server);
73fbb2e0a3Schristos
74fbb2e0a3Schristos conn = malloc(sizeof(*conn));
75fbb2e0a3Schristos ASSERT_NOT_NULL(conn);
76fbb2e0a3Schristos r = uv_tcp_init(server->loop, conn);
77fbb2e0a3Schristos ASSERT_EQ(r, 0);
78fbb2e0a3Schristos
79fbb2e0a3Schristos r = uv_accept(server, (uv_stream_t*)conn);
80fbb2e0a3Schristos ASSERT_EQ(r, 0);
81fbb2e0a3Schristos
82fbb2e0a3Schristos uv_close((uv_handle_t*)conn, close_server_conn_cb);
83fbb2e0a3Schristos uv_close((uv_handle_t*)server, NULL);
84fbb2e0a3Schristos local_conn_accepted = 1;
85fbb2e0a3Schristos }
86fbb2e0a3Schristos }
87fbb2e0a3Schristos
88fbb2e0a3Schristos
exit_cb(uv_process_t * process,int64_t exit_status,int term_signal)89fbb2e0a3Schristos static void exit_cb(uv_process_t* process,
90fbb2e0a3Schristos int64_t exit_status,
91fbb2e0a3Schristos int term_signal) {
92fbb2e0a3Schristos printf("exit_cb\n");
93fbb2e0a3Schristos exit_cb_called++;
94fbb2e0a3Schristos ASSERT_EQ(exit_status, 0);
95fbb2e0a3Schristos ASSERT_EQ(term_signal, 0);
96fbb2e0a3Schristos uv_close((uv_handle_t*)process, NULL);
97fbb2e0a3Schristos }
98fbb2e0a3Schristos
99fbb2e0a3Schristos
on_alloc(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)100fbb2e0a3Schristos static void on_alloc(uv_handle_t* handle,
101fbb2e0a3Schristos size_t suggested_size,
102fbb2e0a3Schristos uv_buf_t* buf) {
103fbb2e0a3Schristos buf->base = malloc(suggested_size);
104fbb2e0a3Schristos buf->len = suggested_size;
105fbb2e0a3Schristos }
106fbb2e0a3Schristos
107fbb2e0a3Schristos
close_client_conn_cb(uv_handle_t * handle)108fbb2e0a3Schristos static void close_client_conn_cb(uv_handle_t* handle) {
109fbb2e0a3Schristos tcp_conn* p = (tcp_conn*)handle->data;
110fbb2e0a3Schristos free(p);
111fbb2e0a3Schristos }
112fbb2e0a3Schristos
113fbb2e0a3Schristos
connect_cb(uv_connect_t * req,int status)114fbb2e0a3Schristos static void connect_cb(uv_connect_t* req, int status) {
115fbb2e0a3Schristos uv_close((uv_handle_t*)req->handle, close_client_conn_cb);
116fbb2e0a3Schristos }
117fbb2e0a3Schristos
118fbb2e0a3Schristos
make_many_connections(void)119fbb2e0a3Schristos static void make_many_connections(void) {
120fbb2e0a3Schristos tcp_conn* conn;
121fbb2e0a3Schristos struct sockaddr_in addr;
122fbb2e0a3Schristos int r, i;
123fbb2e0a3Schristos
124fbb2e0a3Schristos for (i = 0; i < CONN_COUNT; i++) {
125fbb2e0a3Schristos conn = malloc(sizeof(*conn));
126fbb2e0a3Schristos ASSERT_NOT_NULL(conn);
127fbb2e0a3Schristos
128fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &conn->conn);
129fbb2e0a3Schristos ASSERT_EQ(r, 0);
130fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
131fbb2e0a3Schristos
132fbb2e0a3Schristos r = uv_tcp_connect(&conn->conn_req,
133fbb2e0a3Schristos (uv_tcp_t*) &conn->conn,
134fbb2e0a3Schristos (const struct sockaddr*) &addr,
135fbb2e0a3Schristos connect_cb);
136fbb2e0a3Schristos ASSERT_EQ(r, 0);
137fbb2e0a3Schristos
138fbb2e0a3Schristos conn->conn.data = conn;
139fbb2e0a3Schristos }
140fbb2e0a3Schristos }
141fbb2e0a3Schristos
142fbb2e0a3Schristos
on_read(uv_stream_t * handle,ssize_t nread,const uv_buf_t * buf)143fbb2e0a3Schristos static void on_read(uv_stream_t* handle,
144fbb2e0a3Schristos ssize_t nread,
145fbb2e0a3Schristos const uv_buf_t* buf) {
146fbb2e0a3Schristos int r;
147fbb2e0a3Schristos uv_pipe_t* pipe;
148fbb2e0a3Schristos uv_handle_type pending;
149fbb2e0a3Schristos uv_buf_t outbuf;
150fbb2e0a3Schristos
151fbb2e0a3Schristos pipe = (uv_pipe_t*) handle;
152fbb2e0a3Schristos
153fbb2e0a3Schristos if (nread == 0) {
154fbb2e0a3Schristos /* Everything OK, but nothing read. */
155fbb2e0a3Schristos free(buf->base);
156fbb2e0a3Schristos return;
157fbb2e0a3Schristos }
158fbb2e0a3Schristos
159fbb2e0a3Schristos if (nread < 0) {
160fbb2e0a3Schristos if (nread == UV_EOF) {
161fbb2e0a3Schristos free(buf->base);
162fbb2e0a3Schristos return;
163fbb2e0a3Schristos }
164fbb2e0a3Schristos
165fbb2e0a3Schristos printf("error recving on channel: %s\n", uv_strerror(nread));
166fbb2e0a3Schristos abort();
167fbb2e0a3Schristos }
168fbb2e0a3Schristos
169fbb2e0a3Schristos fprintf(stderr, "got %d bytes\n", (int)nread);
170fbb2e0a3Schristos
171fbb2e0a3Schristos pending = uv_pipe_pending_type(pipe);
172fbb2e0a3Schristos if (!tcp_server_listening) {
173fbb2e0a3Schristos ASSERT_EQ(1, uv_pipe_pending_count(pipe));
174fbb2e0a3Schristos ASSERT_GT(nread, 0);
175fbb2e0a3Schristos ASSERT_NOT_NULL(buf->base);
176fbb2e0a3Schristos ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
177fbb2e0a3Schristos read_cb_called++;
178fbb2e0a3Schristos
179fbb2e0a3Schristos /* Accept the pending TCP server, and start listening on it. */
180fbb2e0a3Schristos ASSERT_EQ(pending, UV_TCP);
181fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server);
182fbb2e0a3Schristos ASSERT_EQ(r, 0);
183fbb2e0a3Schristos
184fbb2e0a3Schristos r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);
185fbb2e0a3Schristos ASSERT_EQ(r, 0);
186fbb2e0a3Schristos
187fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);
188fbb2e0a3Schristos ASSERT_EQ(r, 0);
189fbb2e0a3Schristos
190fbb2e0a3Schristos tcp_server_listening = 1;
191fbb2e0a3Schristos
192fbb2e0a3Schristos /* Make sure that the expected data is correctly multiplexed. */
193fbb2e0a3Schristos ASSERT_MEM_EQ("hello\n", buf->base, nread);
194fbb2e0a3Schristos
195*b29f2fbfSchristos outbuf = uv_buf_init("foobar\n", 7);
196fbb2e0a3Schristos r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL);
197fbb2e0a3Schristos ASSERT_EQ(r, 0);
198fbb2e0a3Schristos
199fbb2e0a3Schristos /* Create a bunch of connections to get both servers to accept. */
200fbb2e0a3Schristos make_many_connections();
201fbb2e0a3Schristos } else if (memcmp("accepted_connection\n", buf->base, nread) == 0) {
202fbb2e0a3Schristos /* Remote server has accepted a connection. Close the channel. */
203fbb2e0a3Schristos ASSERT_EQ(0, uv_pipe_pending_count(pipe));
204fbb2e0a3Schristos ASSERT_EQ(pending, UV_UNKNOWN_HANDLE);
205fbb2e0a3Schristos remote_conn_accepted = 1;
206fbb2e0a3Schristos uv_close((uv_handle_t*)&channel, NULL);
207fbb2e0a3Schristos }
208fbb2e0a3Schristos
209fbb2e0a3Schristos free(buf->base);
210fbb2e0a3Schristos }
211fbb2e0a3Schristos
212fbb2e0a3Schristos #ifdef _WIN32
on_read_listen_after_bound_twice(uv_stream_t * handle,ssize_t nread,const uv_buf_t * buf)213fbb2e0a3Schristos static void on_read_listen_after_bound_twice(uv_stream_t* handle,
214fbb2e0a3Schristos ssize_t nread,
215fbb2e0a3Schristos const uv_buf_t* buf) {
216fbb2e0a3Schristos int r;
217fbb2e0a3Schristos uv_pipe_t* pipe;
218fbb2e0a3Schristos uv_handle_type pending;
219fbb2e0a3Schristos
220fbb2e0a3Schristos pipe = (uv_pipe_t*) handle;
221fbb2e0a3Schristos
222fbb2e0a3Schristos if (nread == 0) {
223fbb2e0a3Schristos /* Everything OK, but nothing read. */
224fbb2e0a3Schristos free(buf->base);
225fbb2e0a3Schristos return;
226fbb2e0a3Schristos }
227fbb2e0a3Schristos
228fbb2e0a3Schristos if (nread < 0) {
229fbb2e0a3Schristos if (nread == UV_EOF) {
230fbb2e0a3Schristos free(buf->base);
231fbb2e0a3Schristos return;
232fbb2e0a3Schristos }
233fbb2e0a3Schristos
234fbb2e0a3Schristos printf("error recving on channel: %s\n", uv_strerror(nread));
235fbb2e0a3Schristos abort();
236fbb2e0a3Schristos }
237fbb2e0a3Schristos
238fbb2e0a3Schristos fprintf(stderr, "got %d bytes\n", (int)nread);
239fbb2e0a3Schristos
240fbb2e0a3Schristos ASSERT_GT(uv_pipe_pending_count(pipe), 0);
241fbb2e0a3Schristos pending = uv_pipe_pending_type(pipe);
242fbb2e0a3Schristos ASSERT_GT(nread, 0);
243fbb2e0a3Schristos ASSERT_NOT_NULL(buf->base);
244fbb2e0a3Schristos ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
245fbb2e0a3Schristos read_cb_called++;
246fbb2e0a3Schristos
247fbb2e0a3Schristos if (read_cb_called == 1) {
248fbb2e0a3Schristos /* Accept the first TCP server, and start listening on it. */
249fbb2e0a3Schristos ASSERT_EQ(pending, UV_TCP);
250fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server);
251fbb2e0a3Schristos ASSERT_EQ(r, 0);
252fbb2e0a3Schristos
253fbb2e0a3Schristos r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);
254fbb2e0a3Schristos ASSERT_EQ(r, 0);
255fbb2e0a3Schristos
256fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, on_connection);
257fbb2e0a3Schristos ASSERT_EQ(r, 0);
258fbb2e0a3Schristos } else if (read_cb_called == 2) {
259fbb2e0a3Schristos /* Accept the second TCP server, and start listening on it. */
260fbb2e0a3Schristos ASSERT_EQ(pending, UV_TCP);
261fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server2);
262fbb2e0a3Schristos ASSERT_EQ(r, 0);
263fbb2e0a3Schristos
264fbb2e0a3Schristos r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2);
265fbb2e0a3Schristos ASSERT_EQ(r, 0);
266fbb2e0a3Schristos
267fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server2, BACKLOG, on_connection);
268fbb2e0a3Schristos ASSERT_EQ(r, UV_EADDRINUSE);
269fbb2e0a3Schristos
270fbb2e0a3Schristos uv_close((uv_handle_t*)&tcp_server, NULL);
271fbb2e0a3Schristos uv_close((uv_handle_t*)&tcp_server2, NULL);
272fbb2e0a3Schristos ASSERT_EQ(0, uv_pipe_pending_count(pipe));
273fbb2e0a3Schristos uv_close((uv_handle_t*)&channel, NULL);
274fbb2e0a3Schristos }
275fbb2e0a3Schristos
276fbb2e0a3Schristos free(buf->base);
277fbb2e0a3Schristos }
278fbb2e0a3Schristos #endif
279fbb2e0a3Schristos
spawn_helper(uv_pipe_t * channel,uv_process_t * process,const char * helper)280fbb2e0a3Schristos void spawn_helper(uv_pipe_t* channel,
281fbb2e0a3Schristos uv_process_t* process,
282fbb2e0a3Schristos const char* helper) {
283fbb2e0a3Schristos uv_process_options_t options;
284fbb2e0a3Schristos size_t exepath_size;
285fbb2e0a3Schristos char exepath[1024];
286fbb2e0a3Schristos char* args[3];
287fbb2e0a3Schristos int r;
288fbb2e0a3Schristos uv_stdio_container_t stdio[3];
289fbb2e0a3Schristos
290fbb2e0a3Schristos r = uv_pipe_init(uv_default_loop(), channel, 1);
291fbb2e0a3Schristos ASSERT_EQ(r, 0);
292fbb2e0a3Schristos ASSERT_NE(channel->ipc, 0);
293fbb2e0a3Schristos
294fbb2e0a3Schristos exepath_size = sizeof(exepath);
295fbb2e0a3Schristos r = uv_exepath(exepath, &exepath_size);
296fbb2e0a3Schristos ASSERT_EQ(r, 0);
297fbb2e0a3Schristos
298fbb2e0a3Schristos exepath[exepath_size] = '\0';
299fbb2e0a3Schristos args[0] = exepath;
300fbb2e0a3Schristos args[1] = (char*)helper;
301fbb2e0a3Schristos args[2] = NULL;
302fbb2e0a3Schristos
303fbb2e0a3Schristos memset(&options, 0, sizeof(options));
304fbb2e0a3Schristos options.file = exepath;
305fbb2e0a3Schristos options.args = args;
306fbb2e0a3Schristos options.exit_cb = exit_cb;
307fbb2e0a3Schristos options.stdio = stdio;
308fbb2e0a3Schristos options.stdio_count = ARRAY_SIZE(stdio);
309fbb2e0a3Schristos
310fbb2e0a3Schristos stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE;
311fbb2e0a3Schristos stdio[0].data.stream = (uv_stream_t*) channel;
312fbb2e0a3Schristos stdio[1].flags = UV_INHERIT_FD;
313fbb2e0a3Schristos stdio[1].data.fd = 1;
314fbb2e0a3Schristos stdio[2].flags = UV_INHERIT_FD;
315fbb2e0a3Schristos stdio[2].data.fd = 2;
316fbb2e0a3Schristos
317fbb2e0a3Schristos r = uv_spawn(uv_default_loop(), process, &options);
318fbb2e0a3Schristos ASSERT_EQ(r, 0);
319fbb2e0a3Schristos }
320fbb2e0a3Schristos
321fbb2e0a3Schristos
on_tcp_write(uv_write_t * req,int status)322fbb2e0a3Schristos static void on_tcp_write(uv_write_t* req, int status) {
323fbb2e0a3Schristos ASSERT_EQ(status, 0);
324fbb2e0a3Schristos ASSERT_PTR_EQ(req->handle, &tcp_connection);
325fbb2e0a3Schristos tcp_write_cb_called++;
326fbb2e0a3Schristos }
327fbb2e0a3Schristos
328fbb2e0a3Schristos
on_read_alloc(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)329fbb2e0a3Schristos static void on_read_alloc(uv_handle_t* handle,
330fbb2e0a3Schristos size_t suggested_size,
331fbb2e0a3Schristos uv_buf_t* buf) {
332fbb2e0a3Schristos buf->base = malloc(suggested_size);
333fbb2e0a3Schristos buf->len = suggested_size;
334fbb2e0a3Schristos }
335fbb2e0a3Schristos
336fbb2e0a3Schristos
on_tcp_read(uv_stream_t * tcp,ssize_t nread,const uv_buf_t * buf)337fbb2e0a3Schristos static void on_tcp_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
338fbb2e0a3Schristos ASSERT_GT(nread, 0);
339fbb2e0a3Schristos ASSERT_MEM_EQ("hello again\n", buf->base, nread);
340fbb2e0a3Schristos ASSERT_PTR_EQ(tcp, &tcp_connection);
341fbb2e0a3Schristos free(buf->base);
342fbb2e0a3Schristos
343fbb2e0a3Schristos tcp_read_cb_called++;
344fbb2e0a3Schristos
345fbb2e0a3Schristos uv_close((uv_handle_t*)tcp, NULL);
346fbb2e0a3Schristos uv_close((uv_handle_t*)&channel, NULL);
347fbb2e0a3Schristos }
348fbb2e0a3Schristos
349fbb2e0a3Schristos
on_read_connection(uv_stream_t * handle,ssize_t nread,const uv_buf_t * buf)350fbb2e0a3Schristos static void on_read_connection(uv_stream_t* handle,
351fbb2e0a3Schristos ssize_t nread,
352fbb2e0a3Schristos const uv_buf_t* buf) {
353fbb2e0a3Schristos int r;
354fbb2e0a3Schristos uv_buf_t outbuf;
355fbb2e0a3Schristos uv_pipe_t* pipe;
356fbb2e0a3Schristos uv_handle_type pending;
357fbb2e0a3Schristos
358fbb2e0a3Schristos pipe = (uv_pipe_t*) handle;
359fbb2e0a3Schristos if (nread == 0) {
360fbb2e0a3Schristos /* Everything OK, but nothing read. */
361fbb2e0a3Schristos free(buf->base);
362fbb2e0a3Schristos return;
363fbb2e0a3Schristos }
364fbb2e0a3Schristos
365fbb2e0a3Schristos if (nread < 0) {
366fbb2e0a3Schristos if (nread == UV_EOF) {
367fbb2e0a3Schristos free(buf->base);
368fbb2e0a3Schristos return;
369fbb2e0a3Schristos }
370fbb2e0a3Schristos
371fbb2e0a3Schristos printf("error recving on channel: %s\n", uv_strerror(nread));
372fbb2e0a3Schristos abort();
373fbb2e0a3Schristos }
374fbb2e0a3Schristos
375fbb2e0a3Schristos fprintf(stderr, "got %d bytes\n", (int)nread);
376fbb2e0a3Schristos
377fbb2e0a3Schristos ASSERT_EQ(1, uv_pipe_pending_count(pipe));
378fbb2e0a3Schristos pending = uv_pipe_pending_type(pipe);
379fbb2e0a3Schristos
380fbb2e0a3Schristos ASSERT_GT(nread, 0);
381fbb2e0a3Schristos ASSERT_NOT_NULL(buf->base);
382fbb2e0a3Schristos ASSERT_NE(pending, UV_UNKNOWN_HANDLE);
383fbb2e0a3Schristos read_cb_called++;
384fbb2e0a3Schristos
385fbb2e0a3Schristos /* Accept the pending TCP connection */
386fbb2e0a3Schristos ASSERT_EQ(pending, UV_TCP);
387fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_connection);
388fbb2e0a3Schristos ASSERT_EQ(r, 0);
389fbb2e0a3Schristos
390fbb2e0a3Schristos r = uv_accept(handle, (uv_stream_t*)&tcp_connection);
391fbb2e0a3Schristos ASSERT_EQ(r, 0);
392fbb2e0a3Schristos
393fbb2e0a3Schristos /* Make sure that the expected data is correctly multiplexed. */
394fbb2e0a3Schristos ASSERT_MEM_EQ("hello\n", buf->base, nread);
395fbb2e0a3Schristos
396fbb2e0a3Schristos /* Write/read to/from the connection */
397fbb2e0a3Schristos outbuf = uv_buf_init("world\n", 6);
398fbb2e0a3Schristos r = uv_write(&write_req, (uv_stream_t*)&tcp_connection, &outbuf, 1,
399fbb2e0a3Schristos on_tcp_write);
400fbb2e0a3Schristos ASSERT_EQ(r, 0);
401fbb2e0a3Schristos
402fbb2e0a3Schristos r = uv_read_start((uv_stream_t*)&tcp_connection, on_read_alloc, on_tcp_read);
403fbb2e0a3Schristos ASSERT_EQ(r, 0);
404fbb2e0a3Schristos
405fbb2e0a3Schristos free(buf->base);
406fbb2e0a3Schristos }
407fbb2e0a3Schristos
408fbb2e0a3Schristos
on_read_send_zero(uv_stream_t * handle,ssize_t nread,const uv_buf_t * buf)409fbb2e0a3Schristos static void on_read_send_zero(uv_stream_t* handle,
410fbb2e0a3Schristos ssize_t nread,
411fbb2e0a3Schristos const uv_buf_t* buf) {
412fbb2e0a3Schristos ASSERT(nread == 0 || nread == UV_EOF);
413fbb2e0a3Schristos free(buf->base);
414fbb2e0a3Schristos }
415fbb2e0a3Schristos
416fbb2e0a3Schristos
run_ipc_test(const char * helper,uv_read_cb read_cb)417fbb2e0a3Schristos static int run_ipc_test(const char* helper, uv_read_cb read_cb) {
418fbb2e0a3Schristos uv_process_t process;
419fbb2e0a3Schristos int r;
420fbb2e0a3Schristos
421fbb2e0a3Schristos spawn_helper(&channel, &process, helper);
422fbb2e0a3Schristos uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb);
423fbb2e0a3Schristos
424fbb2e0a3Schristos r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
425fbb2e0a3Schristos ASSERT_EQ(r, 0);
426fbb2e0a3Schristos
427fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
428fbb2e0a3Schristos return 0;
429fbb2e0a3Schristos }
430fbb2e0a3Schristos
431fbb2e0a3Schristos
TEST_IMPL(ipc_listen_before_write)432fbb2e0a3Schristos TEST_IMPL(ipc_listen_before_write) {
433fbb2e0a3Schristos #if defined(NO_SEND_HANDLE_ON_PIPE)
434fbb2e0a3Schristos RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
435fbb2e0a3Schristos #endif
436fbb2e0a3Schristos int r = run_ipc_test("ipc_helper_listen_before_write", on_read);
437fbb2e0a3Schristos ASSERT_EQ(local_conn_accepted, 1);
438fbb2e0a3Schristos ASSERT_EQ(remote_conn_accepted, 1);
439fbb2e0a3Schristos ASSERT_EQ(read_cb_called, 1);
440fbb2e0a3Schristos ASSERT_EQ(exit_cb_called, 1);
441fbb2e0a3Schristos return r;
442fbb2e0a3Schristos }
443fbb2e0a3Schristos
444fbb2e0a3Schristos
TEST_IMPL(ipc_listen_after_write)445fbb2e0a3Schristos TEST_IMPL(ipc_listen_after_write) {
446fbb2e0a3Schristos #if defined(NO_SEND_HANDLE_ON_PIPE)
447fbb2e0a3Schristos RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
448fbb2e0a3Schristos #endif
449fbb2e0a3Schristos int r = run_ipc_test("ipc_helper_listen_after_write", on_read);
450fbb2e0a3Schristos ASSERT_EQ(local_conn_accepted, 1);
451fbb2e0a3Schristos ASSERT_EQ(remote_conn_accepted, 1);
452fbb2e0a3Schristos ASSERT_EQ(read_cb_called, 1);
453fbb2e0a3Schristos ASSERT_EQ(exit_cb_called, 1);
454fbb2e0a3Schristos return r;
455fbb2e0a3Schristos }
456fbb2e0a3Schristos
457fbb2e0a3Schristos
TEST_IMPL(ipc_tcp_connection)458fbb2e0a3Schristos TEST_IMPL(ipc_tcp_connection) {
459fbb2e0a3Schristos #if defined(NO_SEND_HANDLE_ON_PIPE)
460fbb2e0a3Schristos RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
461fbb2e0a3Schristos #endif
462fbb2e0a3Schristos int r = run_ipc_test("ipc_helper_tcp_connection", on_read_connection);
463fbb2e0a3Schristos ASSERT_EQ(read_cb_called, 1);
464fbb2e0a3Schristos ASSERT_EQ(tcp_write_cb_called, 1);
465fbb2e0a3Schristos ASSERT_EQ(tcp_read_cb_called, 1);
466fbb2e0a3Schristos ASSERT_EQ(exit_cb_called, 1);
467fbb2e0a3Schristos return r;
468fbb2e0a3Schristos }
469fbb2e0a3Schristos
470fbb2e0a3Schristos
471fbb2e0a3Schristos #ifdef _WIN32
TEST_IMPL(listen_with_simultaneous_accepts)472fbb2e0a3Schristos TEST_IMPL(listen_with_simultaneous_accepts) {
473fbb2e0a3Schristos uv_tcp_t server;
474fbb2e0a3Schristos int r;
475fbb2e0a3Schristos struct sockaddr_in addr;
476fbb2e0a3Schristos
477fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
478fbb2e0a3Schristos
479fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &server);
480fbb2e0a3Schristos ASSERT_EQ(r, 0);
481fbb2e0a3Schristos
482fbb2e0a3Schristos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
483fbb2e0a3Schristos ASSERT_EQ(r, 0);
484fbb2e0a3Schristos
485fbb2e0a3Schristos r = uv_tcp_simultaneous_accepts(&server, 1);
486fbb2e0a3Schristos ASSERT_EQ(r, 0);
487fbb2e0a3Schristos
488fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
489fbb2e0a3Schristos ASSERT_EQ(r, 0);
490fbb2e0a3Schristos ASSERT_EQ(server.reqs_pending, 32);
491fbb2e0a3Schristos
492fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
493fbb2e0a3Schristos return 0;
494fbb2e0a3Schristos }
495fbb2e0a3Schristos
496fbb2e0a3Schristos
TEST_IMPL(listen_no_simultaneous_accepts)497fbb2e0a3Schristos TEST_IMPL(listen_no_simultaneous_accepts) {
498fbb2e0a3Schristos uv_tcp_t server;
499fbb2e0a3Schristos int r;
500fbb2e0a3Schristos struct sockaddr_in addr;
501fbb2e0a3Schristos
502fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
503fbb2e0a3Schristos
504fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &server);
505fbb2e0a3Schristos ASSERT_EQ(r, 0);
506fbb2e0a3Schristos
507fbb2e0a3Schristos r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
508fbb2e0a3Schristos ASSERT_EQ(r, 0);
509fbb2e0a3Schristos
510fbb2e0a3Schristos r = uv_tcp_simultaneous_accepts(&server, 0);
511fbb2e0a3Schristos ASSERT_EQ(r, 0);
512fbb2e0a3Schristos
513fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
514fbb2e0a3Schristos ASSERT_EQ(r, 0);
515fbb2e0a3Schristos ASSERT_EQ(server.reqs_pending, 1);
516fbb2e0a3Schristos
517fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
518fbb2e0a3Schristos return 0;
519fbb2e0a3Schristos }
520fbb2e0a3Schristos
TEST_IMPL(ipc_listen_after_bind_twice)521fbb2e0a3Schristos TEST_IMPL(ipc_listen_after_bind_twice) {
522fbb2e0a3Schristos #if defined(NO_SEND_HANDLE_ON_PIPE)
523fbb2e0a3Schristos RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
524fbb2e0a3Schristos #endif
525fbb2e0a3Schristos int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice);
526fbb2e0a3Schristos ASSERT_EQ(read_cb_called, 2);
527fbb2e0a3Schristos ASSERT_EQ(exit_cb_called, 1);
528fbb2e0a3Schristos return r;
529fbb2e0a3Schristos }
530fbb2e0a3Schristos #endif
531fbb2e0a3Schristos
TEST_IMPL(ipc_send_zero)532fbb2e0a3Schristos TEST_IMPL(ipc_send_zero) {
533fbb2e0a3Schristos int r;
534fbb2e0a3Schristos r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero);
535fbb2e0a3Schristos ASSERT_EQ(r, 0);
536fbb2e0a3Schristos return 0;
537fbb2e0a3Schristos }
538fbb2e0a3Schristos
539fbb2e0a3Schristos
540fbb2e0a3Schristos /* Everything here runs in a child process. */
541fbb2e0a3Schristos
542fbb2e0a3Schristos static tcp_conn conn;
543fbb2e0a3Schristos
544fbb2e0a3Schristos
close_cb(uv_handle_t * handle)545fbb2e0a3Schristos static void close_cb(uv_handle_t* handle) {
546fbb2e0a3Schristos close_cb_called++;
547fbb2e0a3Schristos }
548fbb2e0a3Schristos
549fbb2e0a3Schristos
conn_notify_write_cb(uv_write_t * req,int status)550fbb2e0a3Schristos static void conn_notify_write_cb(uv_write_t* req, int status) {
551fbb2e0a3Schristos uv_close((uv_handle_t*)&tcp_server, close_cb);
552fbb2e0a3Schristos uv_close((uv_handle_t*)&channel, close_cb);
553fbb2e0a3Schristos }
554fbb2e0a3Schristos
555fbb2e0a3Schristos
tcp_connection_write_cb(uv_write_t * req,int status)556fbb2e0a3Schristos static void tcp_connection_write_cb(uv_write_t* req, int status) {
557fbb2e0a3Schristos ASSERT_PTR_EQ(&conn.conn, req->handle);
558fbb2e0a3Schristos uv_close((uv_handle_t*)req->handle, close_cb);
559fbb2e0a3Schristos uv_close((uv_handle_t*)&channel, close_cb);
560fbb2e0a3Schristos uv_close((uv_handle_t*)&tcp_server, close_cb);
561fbb2e0a3Schristos tcp_conn_write_cb_called++;
562fbb2e0a3Schristos }
563fbb2e0a3Schristos
564fbb2e0a3Schristos
send_zero_write_cb(uv_write_t * req,int status)565fbb2e0a3Schristos static void send_zero_write_cb(uv_write_t* req, int status) {
566fbb2e0a3Schristos ASSERT_EQ(status, 0);
567fbb2e0a3Schristos send_zero_write++;
568fbb2e0a3Schristos }
569fbb2e0a3Schristos
on_tcp_child_process_read(uv_stream_t * tcp,ssize_t nread,const uv_buf_t * buf)570fbb2e0a3Schristos static void on_tcp_child_process_read(uv_stream_t* tcp,
571fbb2e0a3Schristos ssize_t nread,
572fbb2e0a3Schristos const uv_buf_t* buf) {
573fbb2e0a3Schristos uv_buf_t outbuf;
574fbb2e0a3Schristos int r;
575fbb2e0a3Schristos
576fbb2e0a3Schristos if (nread < 0) {
577fbb2e0a3Schristos if (nread == UV_EOF) {
578fbb2e0a3Schristos free(buf->base);
579fbb2e0a3Schristos return;
580fbb2e0a3Schristos }
581fbb2e0a3Schristos
582fbb2e0a3Schristos printf("error recving on tcp connection: %s\n", uv_strerror(nread));
583fbb2e0a3Schristos abort();
584fbb2e0a3Schristos }
585fbb2e0a3Schristos
586fbb2e0a3Schristos ASSERT_GT(nread, 0);
587fbb2e0a3Schristos ASSERT_MEM_EQ("world\n", buf->base, nread);
588fbb2e0a3Schristos on_pipe_read_called++;
589fbb2e0a3Schristos free(buf->base);
590fbb2e0a3Schristos
591fbb2e0a3Schristos /* Write to the socket */
592fbb2e0a3Schristos outbuf = uv_buf_init("hello again\n", 12);
593fbb2e0a3Schristos r = uv_write(&conn.tcp_write_req, tcp, &outbuf, 1, tcp_connection_write_cb);
594fbb2e0a3Schristos ASSERT_EQ(r, 0);
595fbb2e0a3Schristos
596fbb2e0a3Schristos tcp_conn_read_cb_called++;
597fbb2e0a3Schristos }
598fbb2e0a3Schristos
599fbb2e0a3Schristos
connect_child_process_cb(uv_connect_t * req,int status)600fbb2e0a3Schristos static void connect_child_process_cb(uv_connect_t* req, int status) {
601fbb2e0a3Schristos int r;
602fbb2e0a3Schristos
603fbb2e0a3Schristos ASSERT_EQ(status, 0);
604fbb2e0a3Schristos r = uv_read_start(req->handle, on_read_alloc, on_tcp_child_process_read);
605fbb2e0a3Schristos ASSERT_EQ(r, 0);
606fbb2e0a3Schristos }
607fbb2e0a3Schristos
608fbb2e0a3Schristos
ipc_on_connection(uv_stream_t * server,int status)609fbb2e0a3Schristos static void ipc_on_connection(uv_stream_t* server, int status) {
610fbb2e0a3Schristos int r;
611fbb2e0a3Schristos uv_buf_t buf;
612fbb2e0a3Schristos
613fbb2e0a3Schristos if (!connection_accepted) {
614fbb2e0a3Schristos /*
615fbb2e0a3Schristos * Accept the connection and close it. Also let the other
616fbb2e0a3Schristos * side know.
617fbb2e0a3Schristos */
618fbb2e0a3Schristos ASSERT_EQ(status, 0);
619fbb2e0a3Schristos ASSERT_PTR_EQ(&tcp_server, server);
620fbb2e0a3Schristos
621fbb2e0a3Schristos r = uv_tcp_init(server->loop, &conn.conn);
622fbb2e0a3Schristos ASSERT_EQ(r, 0);
623fbb2e0a3Schristos
624fbb2e0a3Schristos r = uv_accept(server, (uv_stream_t*)&conn.conn);
625fbb2e0a3Schristos ASSERT_EQ(r, 0);
626fbb2e0a3Schristos
627fbb2e0a3Schristos uv_close((uv_handle_t*)&conn.conn, close_cb);
628fbb2e0a3Schristos
629fbb2e0a3Schristos buf = uv_buf_init("accepted_connection\n", 20);
630fbb2e0a3Schristos r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,
631fbb2e0a3Schristos NULL, conn_notify_write_cb);
632fbb2e0a3Schristos ASSERT_EQ(r, 0);
633fbb2e0a3Schristos
634fbb2e0a3Schristos connection_accepted = 1;
635fbb2e0a3Schristos }
636fbb2e0a3Schristos }
637fbb2e0a3Schristos
638fbb2e0a3Schristos
close_and_free_cb(uv_handle_t * handle)639*b29f2fbfSchristos static void close_and_free_cb(uv_handle_t* handle) {
640*b29f2fbfSchristos close_cb_called++;
641*b29f2fbfSchristos free(handle);
642*b29f2fbfSchristos }
643*b29f2fbfSchristos
ipc_on_connection_tcp_conn(uv_stream_t * server,int status)644fbb2e0a3Schristos static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) {
645fbb2e0a3Schristos int r;
646fbb2e0a3Schristos uv_buf_t buf;
647fbb2e0a3Schristos uv_tcp_t* conn;
648fbb2e0a3Schristos
649fbb2e0a3Schristos ASSERT_EQ(status, 0);
650fbb2e0a3Schristos ASSERT_PTR_EQ(&tcp_server, server);
651fbb2e0a3Schristos
652fbb2e0a3Schristos conn = malloc(sizeof(*conn));
653fbb2e0a3Schristos ASSERT_NOT_NULL(conn);
654fbb2e0a3Schristos
655fbb2e0a3Schristos r = uv_tcp_init(server->loop, conn);
656fbb2e0a3Schristos ASSERT_EQ(r, 0);
657fbb2e0a3Schristos
658fbb2e0a3Schristos r = uv_accept(server, (uv_stream_t*)conn);
659fbb2e0a3Schristos ASSERT_EQ(r, 0);
660fbb2e0a3Schristos
661fbb2e0a3Schristos /* Send the accepted connection to the other process */
662fbb2e0a3Schristos buf = uv_buf_init("hello\n", 6);
663fbb2e0a3Schristos r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1,
664fbb2e0a3Schristos (uv_stream_t*)conn, NULL);
665fbb2e0a3Schristos ASSERT_EQ(r, 0);
666fbb2e0a3Schristos
667fbb2e0a3Schristos r = uv_read_start((uv_stream_t*) conn,
668fbb2e0a3Schristos on_read_alloc,
669fbb2e0a3Schristos on_tcp_child_process_read);
670fbb2e0a3Schristos ASSERT_EQ(r, 0);
671fbb2e0a3Schristos
672*b29f2fbfSchristos uv_close((uv_handle_t*)conn, close_and_free_cb);
673fbb2e0a3Schristos }
674fbb2e0a3Schristos
675fbb2e0a3Schristos
ipc_helper(int listen_after_write)676fbb2e0a3Schristos int ipc_helper(int listen_after_write) {
677fbb2e0a3Schristos /*
678fbb2e0a3Schristos * This is launched from test-ipc.c. stdin is a duplex channel that we
679fbb2e0a3Schristos * over which a handle will be transmitted.
680fbb2e0a3Schristos */
681fbb2e0a3Schristos struct sockaddr_in addr;
682fbb2e0a3Schristos int r;
683fbb2e0a3Schristos uv_buf_t buf;
684fbb2e0a3Schristos
685fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
686fbb2e0a3Schristos
687fbb2e0a3Schristos r = uv_pipe_init(uv_default_loop(), &channel, 1);
688fbb2e0a3Schristos ASSERT_EQ(r, 0);
689fbb2e0a3Schristos
690fbb2e0a3Schristos uv_pipe_open(&channel, 0);
691fbb2e0a3Schristos
692fbb2e0a3Schristos ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
693fbb2e0a3Schristos ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
694fbb2e0a3Schristos ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
695fbb2e0a3Schristos
696fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server);
697fbb2e0a3Schristos ASSERT_EQ(r, 0);
698fbb2e0a3Schristos
699fbb2e0a3Schristos r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
700fbb2e0a3Schristos ASSERT_EQ(r, 0);
701fbb2e0a3Schristos
702fbb2e0a3Schristos if (!listen_after_write) {
703fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);
704fbb2e0a3Schristos ASSERT_EQ(r, 0);
705fbb2e0a3Schristos }
706fbb2e0a3Schristos
707fbb2e0a3Schristos buf = uv_buf_init("hello\n", 6);
708fbb2e0a3Schristos r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
709fbb2e0a3Schristos (uv_stream_t*)&tcp_server, NULL);
710fbb2e0a3Schristos ASSERT_EQ(r, 0);
711fbb2e0a3Schristos
712fbb2e0a3Schristos if (listen_after_write) {
713fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection);
714fbb2e0a3Schristos ASSERT_EQ(r, 0);
715fbb2e0a3Schristos }
716fbb2e0a3Schristos
717fbb2e0a3Schristos notify_parent_process();
718fbb2e0a3Schristos r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
719fbb2e0a3Schristos ASSERT_EQ(r, 0);
720fbb2e0a3Schristos
721fbb2e0a3Schristos ASSERT_EQ(connection_accepted, 1);
722fbb2e0a3Schristos ASSERT_EQ(close_cb_called, 3);
723fbb2e0a3Schristos
724fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
725fbb2e0a3Schristos return 0;
726fbb2e0a3Schristos }
727fbb2e0a3Schristos
728fbb2e0a3Schristos
ipc_helper_tcp_connection(void)729fbb2e0a3Schristos int ipc_helper_tcp_connection(void) {
730fbb2e0a3Schristos /*
731fbb2e0a3Schristos * This is launched from test-ipc.c. stdin is a duplex channel
732fbb2e0a3Schristos * over which a handle will be transmitted.
733fbb2e0a3Schristos */
734fbb2e0a3Schristos
735fbb2e0a3Schristos int r;
736fbb2e0a3Schristos struct sockaddr_in addr;
737fbb2e0a3Schristos
738fbb2e0a3Schristos r = uv_pipe_init(uv_default_loop(), &channel, 1);
739fbb2e0a3Schristos ASSERT_EQ(r, 0);
740fbb2e0a3Schristos
741fbb2e0a3Schristos uv_pipe_open(&channel, 0);
742fbb2e0a3Schristos
743fbb2e0a3Schristos ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
744fbb2e0a3Schristos ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
745fbb2e0a3Schristos ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
746fbb2e0a3Schristos
747fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server);
748fbb2e0a3Schristos ASSERT_EQ(r, 0);
749fbb2e0a3Schristos
750fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
751fbb2e0a3Schristos
752fbb2e0a3Schristos r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
753fbb2e0a3Schristos ASSERT_EQ(r, 0);
754fbb2e0a3Schristos
755fbb2e0a3Schristos r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection_tcp_conn);
756fbb2e0a3Schristos ASSERT_EQ(r, 0);
757fbb2e0a3Schristos
758fbb2e0a3Schristos /* Make a connection to the server */
759fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &conn.conn);
760fbb2e0a3Schristos ASSERT_EQ(r, 0);
761fbb2e0a3Schristos
762fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
763fbb2e0a3Schristos
764fbb2e0a3Schristos r = uv_tcp_connect(&conn.conn_req,
765fbb2e0a3Schristos (uv_tcp_t*) &conn.conn,
766fbb2e0a3Schristos (const struct sockaddr*) &addr,
767fbb2e0a3Schristos connect_child_process_cb);
768fbb2e0a3Schristos ASSERT_EQ(r, 0);
769fbb2e0a3Schristos
770fbb2e0a3Schristos r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
771fbb2e0a3Schristos ASSERT_EQ(r, 0);
772fbb2e0a3Schristos
773fbb2e0a3Schristos ASSERT_EQ(tcp_conn_read_cb_called, 1);
774fbb2e0a3Schristos ASSERT_EQ(tcp_conn_write_cb_called, 1);
775fbb2e0a3Schristos ASSERT_EQ(close_cb_called, 4);
776fbb2e0a3Schristos
777fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
778fbb2e0a3Schristos return 0;
779fbb2e0a3Schristos }
780fbb2e0a3Schristos
ipc_helper_bind_twice(void)781fbb2e0a3Schristos int ipc_helper_bind_twice(void) {
782fbb2e0a3Schristos /*
783fbb2e0a3Schristos * This is launched from test-ipc.c. stdin is a duplex channel
784fbb2e0a3Schristos * over which two handles will be transmitted.
785fbb2e0a3Schristos */
786fbb2e0a3Schristos struct sockaddr_in addr;
787fbb2e0a3Schristos int r;
788fbb2e0a3Schristos uv_buf_t buf;
789fbb2e0a3Schristos
790fbb2e0a3Schristos ASSERT_EQ(0, uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
791fbb2e0a3Schristos
792fbb2e0a3Schristos r = uv_pipe_init(uv_default_loop(), &channel, 1);
793fbb2e0a3Schristos ASSERT_EQ(r, 0);
794fbb2e0a3Schristos
795fbb2e0a3Schristos uv_pipe_open(&channel, 0);
796fbb2e0a3Schristos
797fbb2e0a3Schristos ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
798fbb2e0a3Schristos ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
799fbb2e0a3Schristos ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
800fbb2e0a3Schristos
801fbb2e0a3Schristos buf = uv_buf_init("hello\n", 6);
802fbb2e0a3Schristos
803fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server);
804fbb2e0a3Schristos ASSERT_EQ(r, 0);
805fbb2e0a3Schristos r = uv_tcp_init(uv_default_loop(), &tcp_server2);
806fbb2e0a3Schristos ASSERT_EQ(r, 0);
807fbb2e0a3Schristos
808fbb2e0a3Schristos r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
809fbb2e0a3Schristos ASSERT_EQ(r, 0);
810fbb2e0a3Schristos r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0);
811fbb2e0a3Schristos ASSERT_EQ(r, 0);
812fbb2e0a3Schristos
813fbb2e0a3Schristos r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
814fbb2e0a3Schristos (uv_stream_t*)&tcp_server, NULL);
815fbb2e0a3Schristos ASSERT_EQ(r, 0);
816fbb2e0a3Schristos r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1,
817fbb2e0a3Schristos (uv_stream_t*)&tcp_server2, NULL);
818fbb2e0a3Schristos ASSERT_EQ(r, 0);
819fbb2e0a3Schristos
820fbb2e0a3Schristos r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
821fbb2e0a3Schristos ASSERT_EQ(r, 0);
822fbb2e0a3Schristos
823fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
824fbb2e0a3Schristos return 0;
825fbb2e0a3Schristos }
826fbb2e0a3Schristos
ipc_helper_send_zero(void)827fbb2e0a3Schristos int ipc_helper_send_zero(void) {
828fbb2e0a3Schristos int r;
829fbb2e0a3Schristos uv_buf_t zero_buf;
830fbb2e0a3Schristos
831fbb2e0a3Schristos zero_buf = uv_buf_init(0, 0);
832fbb2e0a3Schristos
833fbb2e0a3Schristos r = uv_pipe_init(uv_default_loop(), &channel, 0);
834fbb2e0a3Schristos ASSERT_EQ(r, 0);
835fbb2e0a3Schristos
836fbb2e0a3Schristos uv_pipe_open(&channel, 0);
837fbb2e0a3Schristos
838fbb2e0a3Schristos ASSERT_EQ(1, uv_is_readable((uv_stream_t*) &channel));
839fbb2e0a3Schristos ASSERT_EQ(1, uv_is_writable((uv_stream_t*) &channel));
840fbb2e0a3Schristos ASSERT_EQ(0, uv_is_closing((uv_handle_t*) &channel));
841fbb2e0a3Schristos
842fbb2e0a3Schristos r = uv_write(&write_req,
843fbb2e0a3Schristos (uv_stream_t*)&channel,
844fbb2e0a3Schristos &zero_buf,
845fbb2e0a3Schristos 1,
846fbb2e0a3Schristos send_zero_write_cb);
847fbb2e0a3Schristos
848fbb2e0a3Schristos ASSERT_EQ(r, 0);
849fbb2e0a3Schristos
850fbb2e0a3Schristos r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
851fbb2e0a3Schristos ASSERT_EQ(r, 0);
852fbb2e0a3Schristos
853fbb2e0a3Schristos ASSERT_EQ(send_zero_write, 1);
854fbb2e0a3Schristos
855fbb2e0a3Schristos MAKE_VALGRIND_HAPPY();
856fbb2e0a3Schristos return 0;
857fbb2e0a3Schristos }
858