1 /* Copyright Joyent, Inc. and other Node 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 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #ifndef _WIN32
29 # include <unistd.h> /* close */
30 #else
31 # include <fcntl.h>
32 #endif
33
34 static uv_pipe_t pipe_client;
35 static uv_pipe_t pipe_server;
36 static uv_connect_t connect_req;
37
38 static int pipe_close_cb_called = 0;
39 static int pipe_client_connect_cb_called = 0;
40
41
pipe_close_cb(uv_handle_t * handle)42 static void pipe_close_cb(uv_handle_t* handle) {
43 ASSERT_NE(handle == (uv_handle_t*) &pipe_client ||
44 handle == (uv_handle_t*) &pipe_server, 0);
45 pipe_close_cb_called++;
46 }
47
48
pipe_client_connect_cb(uv_connect_t * req,int status)49 static void pipe_client_connect_cb(uv_connect_t* req, int status) {
50 char buf[1024];
51 size_t len;
52 int r;
53
54 ASSERT_PTR_EQ(req, &connect_req);
55 ASSERT_OK(status);
56
57 len = sizeof buf;
58 r = uv_pipe_getpeername(&pipe_client, buf, &len);
59 ASSERT_OK(r);
60
61 if (*buf == '\0') { /* Linux abstract socket. */
62 const char expected[] = "\0" TEST_PIPENAME;
63 ASSERT_EQ(len, sizeof(expected) - 1);
64 ASSERT_MEM_EQ(buf, expected, len);
65 } else {
66 ASSERT_NE(0, buf[len - 1]);
67 ASSERT_MEM_EQ(buf, TEST_PIPENAME, len);
68 }
69
70 len = sizeof buf;
71 r = uv_pipe_getsockname(&pipe_client, buf, &len);
72 ASSERT(r == 0 && len == 0);
73
74 pipe_client_connect_cb_called++;
75
76 uv_close((uv_handle_t*) &pipe_client, pipe_close_cb);
77 uv_close((uv_handle_t*) &pipe_server, pipe_close_cb);
78 }
79
80
pipe_server_connection_cb(uv_stream_t * handle,int status)81 static void pipe_server_connection_cb(uv_stream_t* handle, int status) {
82 /* This function *may* be called, depending on whether accept or the
83 * connection callback is called first.
84 */
85 ASSERT_OK(status);
86 }
87
88
TEST_IMPL(pipe_getsockname)89 TEST_IMPL(pipe_getsockname) {
90 #if defined(NO_SELF_CONNECT)
91 RETURN_SKIP(NO_SELF_CONNECT);
92 #endif
93 uv_loop_t* loop;
94 char namebuf[256];
95 char buf[1024];
96 size_t namelen;
97 size_t len;
98 int r;
99
100 snprintf(namebuf, sizeof(namebuf), "%s-oob", TEST_PIPENAME);
101 namelen = sizeof(TEST_PIPENAME) - 1;
102
103 loop = uv_default_loop();
104 ASSERT_NOT_NULL(loop);
105
106 r = uv_pipe_init(loop, &pipe_server, 0);
107 ASSERT_OK(r);
108
109 r = uv_pipe_bind2(&pipe_server, "bad\0path", 8, 0);
110 ASSERT_EQ(r, UV_EINVAL);
111
112 len = sizeof buf;
113 r = uv_pipe_getsockname(&pipe_server, buf, &len);
114 ASSERT_EQ(r, UV_EBADF);
115
116 len = sizeof buf;
117 r = uv_pipe_getpeername(&pipe_server, buf, &len);
118 ASSERT_EQ(r, UV_EBADF);
119
120 r = uv_pipe_bind2(&pipe_server, namebuf, namelen, 0);
121 ASSERT_OK(r);
122
123 #ifndef _WIN32
124 ASSERT_STR_EQ(pipe_server.pipe_fname, TEST_PIPENAME);
125 #endif
126
127 len = sizeof buf;
128 r = uv_pipe_getsockname(&pipe_server, buf, &len);
129 ASSERT_OK(r);
130
131 ASSERT_NE(0, buf[len - 1]);
132 ASSERT_EQ(buf[len], '\0');
133 ASSERT_OK(memcmp(buf, TEST_PIPENAME, len));
134
135 len = sizeof buf;
136 r = uv_pipe_getpeername(&pipe_server, buf, &len);
137 ASSERT_EQ(r, UV_ENOTCONN);
138
139 r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb);
140 ASSERT_OK(r);
141
142 r = uv_pipe_init(loop, &pipe_client, 0);
143 ASSERT_OK(r);
144
145 len = sizeof buf;
146 r = uv_pipe_getsockname(&pipe_client, buf, &len);
147 ASSERT_EQ(r, UV_EBADF);
148
149 len = sizeof buf;
150 r = uv_pipe_getpeername(&pipe_client, buf, &len);
151 ASSERT_EQ(r, UV_EBADF);
152
153 r = uv_pipe_connect2(&connect_req,
154 &pipe_client,
155 namebuf,
156 namelen,
157 0,
158 pipe_client_connect_cb);
159 ASSERT_OK(r);
160
161 len = sizeof buf;
162 r = uv_pipe_getsockname(&pipe_client, buf, &len);
163 ASSERT(r == 0 && len == 0);
164
165 len = sizeof buf;
166 r = uv_pipe_getpeername(&pipe_client, buf, &len);
167 ASSERT_OK(r);
168
169 ASSERT_NE(0, buf[len - 1]);
170 ASSERT_OK(memcmp(buf, TEST_PIPENAME, len));
171
172 r = uv_run(loop, UV_RUN_DEFAULT);
173 ASSERT_OK(r);
174 ASSERT_EQ(1, pipe_client_connect_cb_called);
175 ASSERT_EQ(2, pipe_close_cb_called);
176
177 MAKE_VALGRIND_HAPPY(loop);
178 return 0;
179 }
180
181
TEST_IMPL(pipe_getsockname_abstract)182 TEST_IMPL(pipe_getsockname_abstract) {
183 /* TODO(bnoordhuis) Use unique name, susceptible to concurrent test runs. */
184 static const char name[] = "\0" TEST_PIPENAME;
185 #if defined(__linux__)
186 char buf[256];
187 size_t buflen;
188
189 buflen = sizeof(buf);
190 memset(buf, 0, sizeof(buf));
191 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_server, 0));
192 ASSERT_OK(uv_pipe_bind2(&pipe_server, name, sizeof(name) - 1, 0));
193 ASSERT_OK(uv_pipe_getsockname(&pipe_server, buf, &buflen));
194 ASSERT_UINT64_EQ(sizeof(name) - 1, buflen);
195 ASSERT_MEM_EQ(name, buf, buflen);
196 ASSERT_OK(uv_listen((uv_stream_t*) &pipe_server,
197 0,
198 pipe_server_connection_cb));
199 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_client, 0));
200 ASSERT_OK(uv_pipe_connect2(&connect_req,
201 &pipe_client,
202 name,
203 sizeof(name) - 1,
204 0,
205 pipe_client_connect_cb));
206 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
207 ASSERT_EQ(1, pipe_client_connect_cb_called);
208 ASSERT_EQ(2, pipe_close_cb_called);
209 MAKE_VALGRIND_HAPPY(uv_default_loop());
210 return 0;
211 #else
212 /* On other platforms it should simply fail with UV_EINVAL. */
213 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_server, 0));
214 ASSERT_EQ(UV_EINVAL, uv_pipe_bind2(&pipe_server, name, sizeof(name), 0));
215 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_client, 0));
216 uv_close((uv_handle_t*) &pipe_server, pipe_close_cb);
217 ASSERT_EQ(UV_EINVAL, uv_pipe_connect2(&connect_req,
218 &pipe_client,
219 name,
220 sizeof(name),
221 0,
222 (uv_connect_cb) abort));
223 uv_close((uv_handle_t*) &pipe_client, pipe_close_cb);
224 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
225 ASSERT_EQ(2, pipe_close_cb_called);
226 MAKE_VALGRIND_HAPPY(uv_default_loop());
227 return 0;
228 #endif
229 }
230
TEST_IMPL(pipe_getsockname_blocking)231 TEST_IMPL(pipe_getsockname_blocking) {
232 #ifdef _WIN32
233 HANDLE readh, writeh;
234 int readfd;
235 char buf1[1024], buf2[1024];
236 size_t len1, len2;
237 int r;
238
239 r = CreatePipe(&readh, &writeh, NULL, 65536);
240 ASSERT(r);
241
242 r = uv_pipe_init(uv_default_loop(), &pipe_client, 0);
243 ASSERT_OK(r);
244 readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY);
245 ASSERT_NE(r, -1);
246 r = uv_pipe_open(&pipe_client, readfd);
247 ASSERT_OK(r);
248 r = uv_read_start((uv_stream_t*) &pipe_client,
249 (uv_alloc_cb) abort,
250 (uv_read_cb) abort);
251 ASSERT_OK(r);
252 Sleep(100);
253 r = uv_read_stop((uv_stream_t*)&pipe_client);
254 ASSERT_OK(r);
255
256 len1 = sizeof buf1;
257 r = uv_pipe_getsockname(&pipe_client, buf1, &len1);
258 ASSERT_OK(r);
259 ASSERT_OK(len1); /* It's an annonymous pipe. */
260
261 r = uv_read_start((uv_stream_t*)&pipe_client,
262 (uv_alloc_cb) abort,
263 (uv_read_cb) abort);
264 ASSERT_OK(r);
265 Sleep(100);
266
267 len2 = sizeof buf2;
268 r = uv_pipe_getsockname(&pipe_client, buf2, &len2);
269 ASSERT_OK(r);
270 ASSERT_OK(len2); /* It's an annonymous pipe. */
271
272 r = uv_read_stop((uv_stream_t*)&pipe_client);
273 ASSERT_OK(r);
274
275 ASSERT_EQ(len1, len2);
276 ASSERT_OK(memcmp(buf1, buf2, len1));
277
278 pipe_close_cb_called = 0;
279 uv_close((uv_handle_t*)&pipe_client, pipe_close_cb);
280
281 uv_run(uv_default_loop(), UV_RUN_DEFAULT);
282
283 ASSERT_EQ(1, pipe_close_cb_called);
284
285 CloseHandle(writeh);
286 #endif
287
288 MAKE_VALGRIND_HAPPY(uv_default_loop());
289 return 0;
290 }
291