xref: /netbsd/external/mit/libuv/dist/test/test-ipc.c (revision b29f2fbf)
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