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 | #if defined(__linux__) |
29 | #include <sys/socket.h> |
30 | #include <sys/un.h> |
31 | #endif |
32 | |
33 | #ifndef _WIN32 |
34 | # include <unistd.h> /* close */ |
35 | #else |
36 | # include <fcntl.h> |
37 | #endif |
38 | |
39 | static uv_pipe_t pipe_client; |
40 | static uv_pipe_t pipe_server; |
41 | static uv_connect_t connect_req; |
42 | |
43 | static int pipe_close_cb_called = 0; |
44 | static int pipe_client_connect_cb_called = 0; |
45 | |
46 | |
47 | static void pipe_close_cb(uv_handle_t* handle) { |
48 | ASSERT(handle == (uv_handle_t*) &pipe_client || |
49 | handle == (uv_handle_t*) &pipe_server); |
50 | pipe_close_cb_called++; |
51 | } |
52 | |
53 | |
54 | static void pipe_client_connect_cb(uv_connect_t* req, int status) { |
55 | char buf[1024]; |
56 | size_t len; |
57 | int r; |
58 | |
59 | ASSERT(req == &connect_req); |
60 | ASSERT(status == 0); |
61 | |
62 | len = sizeof buf; |
63 | r = uv_pipe_getpeername(&pipe_client, buf, &len); |
64 | ASSERT(r == 0); |
65 | |
66 | ASSERT(buf[len - 1] != 0); |
67 | ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); |
68 | |
69 | len = sizeof buf; |
70 | r = uv_pipe_getsockname(&pipe_client, buf, &len); |
71 | ASSERT(r == 0 && len == 0); |
72 | |
73 | pipe_client_connect_cb_called++; |
74 | |
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 | |
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(status == 0); |
86 | } |
87 | |
88 | |
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 buf[1024]; |
95 | size_t len; |
96 | int r; |
97 | |
98 | loop = uv_default_loop(); |
99 | ASSERT(loop != NULL); |
100 | |
101 | r = uv_pipe_init(loop, &pipe_server, 0); |
102 | ASSERT(r == 0); |
103 | |
104 | len = sizeof buf; |
105 | r = uv_pipe_getsockname(&pipe_server, buf, &len); |
106 | ASSERT(r == UV_EBADF); |
107 | |
108 | len = sizeof buf; |
109 | r = uv_pipe_getpeername(&pipe_server, buf, &len); |
110 | ASSERT(r == UV_EBADF); |
111 | |
112 | r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); |
113 | ASSERT(r == 0); |
114 | |
115 | len = sizeof buf; |
116 | r = uv_pipe_getsockname(&pipe_server, buf, &len); |
117 | ASSERT(r == 0); |
118 | |
119 | ASSERT(buf[len - 1] != 0); |
120 | ASSERT(buf[len] == '\0'); |
121 | ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); |
122 | |
123 | len = sizeof buf; |
124 | r = uv_pipe_getpeername(&pipe_server, buf, &len); |
125 | ASSERT(r == UV_ENOTCONN); |
126 | |
127 | r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); |
128 | ASSERT(r == 0); |
129 | |
130 | r = uv_pipe_init(loop, &pipe_client, 0); |
131 | ASSERT(r == 0); |
132 | |
133 | len = sizeof buf; |
134 | r = uv_pipe_getsockname(&pipe_client, buf, &len); |
135 | ASSERT(r == UV_EBADF); |
136 | |
137 | len = sizeof buf; |
138 | r = uv_pipe_getpeername(&pipe_client, buf, &len); |
139 | ASSERT(r == UV_EBADF); |
140 | |
141 | uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); |
142 | |
143 | len = sizeof buf; |
144 | r = uv_pipe_getsockname(&pipe_client, buf, &len); |
145 | ASSERT(r == 0 && len == 0); |
146 | |
147 | len = sizeof buf; |
148 | r = uv_pipe_getpeername(&pipe_client, buf, &len); |
149 | ASSERT(r == 0); |
150 | |
151 | ASSERT(buf[len - 1] != 0); |
152 | ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); |
153 | |
154 | r = uv_run(loop, UV_RUN_DEFAULT); |
155 | ASSERT(r == 0); |
156 | ASSERT(pipe_client_connect_cb_called == 1); |
157 | ASSERT(pipe_close_cb_called == 2); |
158 | |
159 | MAKE_VALGRIND_HAPPY(); |
160 | return 0; |
161 | } |
162 | |
163 | |
164 | TEST_IMPL(pipe_getsockname_abstract) { |
165 | #if defined(__linux__) |
166 | char buf[1024]; |
167 | size_t len; |
168 | int r; |
169 | int sock; |
170 | struct sockaddr_un sun; |
171 | socklen_t sun_len; |
172 | char abstract_pipe[] = "\0test-pipe" ; |
173 | |
174 | sock = socket(AF_UNIX, SOCK_STREAM, 0); |
175 | ASSERT(sock != -1); |
176 | |
177 | sun_len = sizeof sun; |
178 | memset(&sun, 0, sun_len); |
179 | sun.sun_family = AF_UNIX; |
180 | memcpy(sun.sun_path, abstract_pipe, sizeof abstract_pipe); |
181 | |
182 | r = bind(sock, (struct sockaddr*)&sun, sun_len); |
183 | ASSERT(r == 0); |
184 | |
185 | r = uv_pipe_init(uv_default_loop(), &pipe_server, 0); |
186 | ASSERT(r == 0); |
187 | r = uv_pipe_open(&pipe_server, sock); |
188 | ASSERT(r == 0); |
189 | |
190 | len = sizeof buf; |
191 | r = uv_pipe_getsockname(&pipe_server, buf, &len); |
192 | ASSERT(r == 0); |
193 | |
194 | ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0); |
195 | |
196 | uv_close((uv_handle_t*)&pipe_server, pipe_close_cb); |
197 | |
198 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
199 | |
200 | close(sock); |
201 | |
202 | ASSERT(pipe_close_cb_called == 1); |
203 | MAKE_VALGRIND_HAPPY(); |
204 | return 0; |
205 | #else |
206 | MAKE_VALGRIND_HAPPY(); |
207 | return 0; |
208 | #endif |
209 | } |
210 | |
211 | TEST_IMPL(pipe_getsockname_blocking) { |
212 | #ifdef _WIN32 |
213 | HANDLE readh, writeh; |
214 | int readfd; |
215 | char buf1[1024], buf2[1024]; |
216 | size_t len1, len2; |
217 | int r; |
218 | |
219 | r = CreatePipe(&readh, &writeh, NULL, 65536); |
220 | ASSERT(r != 0); |
221 | |
222 | r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); |
223 | ASSERT(r == 0); |
224 | readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); |
225 | ASSERT(r != -1); |
226 | r = uv_pipe_open(&pipe_client, readfd); |
227 | ASSERT(r == 0); |
228 | r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); |
229 | ASSERT(r == 0); |
230 | Sleep(100); |
231 | r = uv_read_stop((uv_stream_t*)&pipe_client); |
232 | ASSERT(r == 0); |
233 | |
234 | len1 = sizeof buf1; |
235 | r = uv_pipe_getsockname(&pipe_client, buf1, &len1); |
236 | ASSERT(r == 0); |
237 | ASSERT(len1 == 0); /* It's an annonymous pipe. */ |
238 | |
239 | r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); |
240 | ASSERT(r == 0); |
241 | Sleep(100); |
242 | |
243 | len2 = sizeof buf2; |
244 | r = uv_pipe_getsockname(&pipe_client, buf2, &len2); |
245 | ASSERT(r == 0); |
246 | ASSERT(len2 == 0); /* It's an annonymous pipe. */ |
247 | |
248 | r = uv_read_stop((uv_stream_t*)&pipe_client); |
249 | ASSERT(r == 0); |
250 | |
251 | ASSERT(len1 == len2); |
252 | ASSERT(memcmp(buf1, buf2, len1) == 0); |
253 | |
254 | pipe_close_cb_called = 0; |
255 | uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); |
256 | |
257 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
258 | |
259 | ASSERT(pipe_close_cb_called == 1); |
260 | |
261 | CloseHandle(writeh); |
262 | #endif |
263 | |
264 | MAKE_VALGRIND_HAPPY(); |
265 | return 0; |
266 | } |
267 | |