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 | |
27 | |
28 | static int close_cb_called = 0; |
29 | |
30 | |
31 | static void close_cb(uv_handle_t* handle) { |
32 | ASSERT(handle != NULL); |
33 | close_cb_called++; |
34 | } |
35 | |
36 | |
37 | TEST_IMPL(tcp_bind_error_addrinuse) { |
38 | struct sockaddr_in addr; |
39 | uv_tcp_t server1, server2; |
40 | int r; |
41 | |
42 | ASSERT(0 == uv_ip4_addr("0.0.0.0" , TEST_PORT, &addr)); |
43 | r = uv_tcp_init(uv_default_loop(), &server1); |
44 | ASSERT(r == 0); |
45 | r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); |
46 | ASSERT(r == 0); |
47 | |
48 | r = uv_tcp_init(uv_default_loop(), &server2); |
49 | ASSERT(r == 0); |
50 | r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); |
51 | ASSERT(r == 0); |
52 | |
53 | r = uv_listen((uv_stream_t*)&server1, 128, NULL); |
54 | ASSERT(r == 0); |
55 | r = uv_listen((uv_stream_t*)&server2, 128, NULL); |
56 | ASSERT(r == UV_EADDRINUSE); |
57 | |
58 | uv_close((uv_handle_t*)&server1, close_cb); |
59 | uv_close((uv_handle_t*)&server2, close_cb); |
60 | |
61 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
62 | |
63 | ASSERT(close_cb_called == 2); |
64 | |
65 | MAKE_VALGRIND_HAPPY(); |
66 | return 0; |
67 | } |
68 | |
69 | |
70 | TEST_IMPL(tcp_bind_error_addrnotavail_1) { |
71 | struct sockaddr_in addr; |
72 | uv_tcp_t server; |
73 | int r; |
74 | |
75 | ASSERT(0 == uv_ip4_addr("127.255.255.255" , TEST_PORT, &addr)); |
76 | |
77 | r = uv_tcp_init(uv_default_loop(), &server); |
78 | ASSERT(r == 0); |
79 | |
80 | /* It seems that Linux is broken here - bind succeeds. */ |
81 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); |
82 | ASSERT(r == 0 || r == UV_EADDRNOTAVAIL); |
83 | |
84 | uv_close((uv_handle_t*)&server, close_cb); |
85 | |
86 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
87 | |
88 | ASSERT(close_cb_called == 1); |
89 | |
90 | MAKE_VALGRIND_HAPPY(); |
91 | return 0; |
92 | } |
93 | |
94 | |
95 | TEST_IMPL(tcp_bind_error_addrnotavail_2) { |
96 | struct sockaddr_in addr; |
97 | uv_tcp_t server; |
98 | int r; |
99 | |
100 | ASSERT(0 == uv_ip4_addr("4.4.4.4" , TEST_PORT, &addr)); |
101 | |
102 | r = uv_tcp_init(uv_default_loop(), &server); |
103 | ASSERT(r == 0); |
104 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); |
105 | ASSERT(r == UV_EADDRNOTAVAIL); |
106 | |
107 | uv_close((uv_handle_t*)&server, close_cb); |
108 | |
109 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
110 | |
111 | ASSERT(close_cb_called == 1); |
112 | |
113 | MAKE_VALGRIND_HAPPY(); |
114 | return 0; |
115 | } |
116 | |
117 | |
118 | TEST_IMPL(tcp_bind_error_fault) { |
119 | char garbage[] = |
120 | "blah blah blah blah blah blah blah blah blah blah blah blah" ; |
121 | struct sockaddr_in* garbage_addr; |
122 | uv_tcp_t server; |
123 | int r; |
124 | |
125 | garbage_addr = (struct sockaddr_in*) &garbage; |
126 | |
127 | r = uv_tcp_init(uv_default_loop(), &server); |
128 | ASSERT(r == 0); |
129 | r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); |
130 | ASSERT(r == UV_EINVAL); |
131 | |
132 | uv_close((uv_handle_t*)&server, close_cb); |
133 | |
134 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
135 | |
136 | ASSERT(close_cb_called == 1); |
137 | |
138 | MAKE_VALGRIND_HAPPY(); |
139 | return 0; |
140 | } |
141 | |
142 | /* Notes: On Linux uv_bind(server, NULL) will segfault the program. */ |
143 | |
144 | TEST_IMPL(tcp_bind_error_inval) { |
145 | struct sockaddr_in addr1; |
146 | struct sockaddr_in addr2; |
147 | uv_tcp_t server; |
148 | int r; |
149 | |
150 | ASSERT(0 == uv_ip4_addr("0.0.0.0" , TEST_PORT, &addr1)); |
151 | ASSERT(0 == uv_ip4_addr("0.0.0.0" , TEST_PORT_2, &addr2)); |
152 | |
153 | r = uv_tcp_init(uv_default_loop(), &server); |
154 | ASSERT(r == 0); |
155 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); |
156 | ASSERT(r == 0); |
157 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); |
158 | ASSERT(r == UV_EINVAL); |
159 | |
160 | uv_close((uv_handle_t*)&server, close_cb); |
161 | |
162 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
163 | |
164 | ASSERT(close_cb_called == 1); |
165 | |
166 | MAKE_VALGRIND_HAPPY(); |
167 | return 0; |
168 | } |
169 | |
170 | |
171 | TEST_IMPL(tcp_bind_localhost_ok) { |
172 | struct sockaddr_in addr; |
173 | uv_tcp_t server; |
174 | int r; |
175 | |
176 | ASSERT(0 == uv_ip4_addr("127.0.0.1" , TEST_PORT, &addr)); |
177 | |
178 | r = uv_tcp_init(uv_default_loop(), &server); |
179 | ASSERT(r == 0); |
180 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); |
181 | ASSERT(r == 0); |
182 | |
183 | MAKE_VALGRIND_HAPPY(); |
184 | return 0; |
185 | } |
186 | |
187 | |
188 | TEST_IMPL(tcp_bind_invalid_flags) { |
189 | struct sockaddr_in addr; |
190 | uv_tcp_t server; |
191 | int r; |
192 | |
193 | ASSERT(0 == uv_ip4_addr("127.0.0.1" , TEST_PORT, &addr)); |
194 | |
195 | r = uv_tcp_init(uv_default_loop(), &server); |
196 | ASSERT(r == 0); |
197 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); |
198 | ASSERT(r == UV_EINVAL); |
199 | |
200 | MAKE_VALGRIND_HAPPY(); |
201 | return 0; |
202 | } |
203 | |
204 | |
205 | TEST_IMPL(tcp_listen_without_bind) { |
206 | int r; |
207 | uv_tcp_t server; |
208 | |
209 | r = uv_tcp_init(uv_default_loop(), &server); |
210 | ASSERT(r == 0); |
211 | r = uv_listen((uv_stream_t*)&server, 128, NULL); |
212 | ASSERT(r == 0); |
213 | |
214 | MAKE_VALGRIND_HAPPY(); |
215 | return 0; |
216 | } |
217 | |
218 | |
219 | TEST_IMPL(tcp_bind_writable_flags) { |
220 | struct sockaddr_in addr; |
221 | uv_tcp_t server; |
222 | uv_buf_t buf; |
223 | uv_write_t write_req; |
224 | uv_shutdown_t shutdown_req; |
225 | int r; |
226 | |
227 | ASSERT(0 == uv_ip4_addr("0.0.0.0" , TEST_PORT, &addr)); |
228 | r = uv_tcp_init(uv_default_loop(), &server); |
229 | ASSERT(r == 0); |
230 | r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); |
231 | ASSERT(r == 0); |
232 | r = uv_listen((uv_stream_t*)&server, 128, NULL); |
233 | ASSERT(r == 0); |
234 | |
235 | ASSERT(0 == uv_is_writable((uv_stream_t*) &server)); |
236 | ASSERT(0 == uv_is_readable((uv_stream_t*) &server)); |
237 | |
238 | buf = uv_buf_init("PING" , 4); |
239 | r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); |
240 | ASSERT(r == UV_EPIPE); |
241 | r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); |
242 | #ifdef _WIN32 |
243 | ASSERT(r == UV_EPIPE); |
244 | #else |
245 | ASSERT(r == UV_ENOTCONN); |
246 | #endif |
247 | r = uv_read_start((uv_stream_t*) &server, NULL, NULL); |
248 | ASSERT(r == UV_ENOTCONN); |
249 | |
250 | uv_close((uv_handle_t*)&server, close_cb); |
251 | |
252 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
253 | |
254 | ASSERT(close_cb_called == 1); |
255 | |
256 | MAKE_VALGRIND_HAPPY(); |
257 | return 0; |
258 | } |
259 | |