xref: /libuv/test/test-udp-open.c (revision 011a1ac1)
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>
30 # include <sys/socket.h>
31 # include <sys/un.h>
32 #endif
33 
34 static int send_cb_called = 0;
35 static int close_cb_called = 0;
36 
37 static uv_udp_send_t send_req;
38 
39 
startup(void)40 static void startup(void) {
41 #ifdef _WIN32
42     struct WSAData wsa_data;
43     int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
44     ASSERT_OK(r);
45 #endif
46 }
47 
48 
create_udp_socket(void)49 static uv_os_sock_t create_udp_socket(void) {
50   uv_os_sock_t sock;
51 
52   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
53 #ifdef _WIN32
54   ASSERT_NE(sock, INVALID_SOCKET);
55 #else
56   ASSERT_GE(sock, 0);
57 #endif
58 
59 #ifndef _WIN32
60   {
61     /* Allow reuse of the port. */
62     int yes = 1;
63     int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
64     ASSERT_OK(r);
65   }
66 #endif
67 
68   return sock;
69 }
70 
71 
close_socket(uv_os_sock_t sock)72 static void close_socket(uv_os_sock_t sock) {
73   int r;
74 #ifdef _WIN32
75   r = closesocket(sock);
76 #else
77   r = close(sock);
78 #endif
79   ASSERT_OK(r);
80 }
81 
82 
alloc_cb(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)83 static void alloc_cb(uv_handle_t* handle,
84                      size_t suggested_size,
85                      uv_buf_t* buf) {
86   static char slab[65536];
87   ASSERT_LE(suggested_size, sizeof(slab));
88   buf->base = slab;
89   buf->len = sizeof(slab);
90 }
91 
92 
close_cb(uv_handle_t * handle)93 static void close_cb(uv_handle_t* handle) {
94   ASSERT_NOT_NULL(handle);
95   close_cb_called++;
96 }
97 
98 
recv_cb(uv_udp_t * handle,ssize_t nread,const uv_buf_t * buf,const struct sockaddr * addr,unsigned flags)99 static void recv_cb(uv_udp_t* handle,
100                        ssize_t nread,
101                        const uv_buf_t* buf,
102                        const struct sockaddr* addr,
103                        unsigned flags) {
104   int r;
105 
106   if (nread < 0) {
107     ASSERT(0 && "unexpected error");
108   }
109 
110   if (nread == 0) {
111     /* Returning unused buffer. Don't count towards sv_recv_cb_called */
112     ASSERT_NULL(addr);
113     return;
114   }
115 
116   ASSERT_OK(flags);
117 
118   ASSERT_NOT_NULL(addr);
119   ASSERT_EQ(4, nread);
120   ASSERT_OK(memcmp("PING", buf->base, nread));
121 
122   r = uv_udp_recv_stop(handle);
123   ASSERT_OK(r);
124 
125   uv_close((uv_handle_t*) handle, close_cb);
126 }
127 
128 
send_cb(uv_udp_send_t * req,int status)129 static void send_cb(uv_udp_send_t* req, int status) {
130   ASSERT_NOT_NULL(req);
131   ASSERT_OK(status);
132 
133   send_cb_called++;
134   uv_close((uv_handle_t*)req->handle, close_cb);
135 }
136 
137 
TEST_IMPL(udp_open)138 TEST_IMPL(udp_open) {
139   struct sockaddr_in addr;
140   uv_buf_t buf = uv_buf_init("PING", 4);
141   uv_udp_t client, client2;
142   uv_os_sock_t sock;
143   int r;
144 
145   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
146 
147   startup();
148   sock = create_udp_socket();
149 
150   r = uv_udp_init(uv_default_loop(), &client);
151   ASSERT_OK(r);
152 
153   r = uv_udp_open(&client, sock);
154   ASSERT_OK(r);
155 
156   r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0);
157   ASSERT_OK(r);
158 
159   r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
160   ASSERT_OK(r);
161 
162   r = uv_udp_send(&send_req,
163                   &client,
164                   &buf,
165                   1,
166                   (const struct sockaddr*) &addr,
167                   send_cb);
168   ASSERT_OK(r);
169 
170 #ifndef _WIN32
171   {
172     r = uv_udp_init(uv_default_loop(), &client2);
173     ASSERT_OK(r);
174 
175     r = uv_udp_open(&client2, sock);
176     ASSERT_EQ(r, UV_EEXIST);
177 
178     uv_close((uv_handle_t*) &client2, NULL);
179   }
180 #else  /* _WIN32 */
181   (void)client2;
182 #endif
183 
184   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
185 
186   ASSERT_EQ(1, send_cb_called);
187   ASSERT_EQ(1, close_cb_called);
188 
189   ASSERT_OK(client.send_queue_size);
190 
191   MAKE_VALGRIND_HAPPY(uv_default_loop());
192   return 0;
193 }
194 
195 
TEST_IMPL(udp_open_twice)196 TEST_IMPL(udp_open_twice) {
197   uv_udp_t client;
198   uv_os_sock_t sock1, sock2;
199   int r;
200 
201   startup();
202   sock1 = create_udp_socket();
203   sock2 = create_udp_socket();
204 
205   r = uv_udp_init(uv_default_loop(), &client);
206   ASSERT_OK(r);
207 
208   r = uv_udp_open(&client, sock1);
209   ASSERT_OK(r);
210 
211   r = uv_udp_open(&client, sock2);
212   ASSERT_EQ(r, UV_EBUSY);
213   close_socket(sock2);
214 
215   uv_close((uv_handle_t*) &client, NULL);
216   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
217 
218   MAKE_VALGRIND_HAPPY(uv_default_loop());
219   return 0;
220 }
221 
TEST_IMPL(udp_open_bound)222 TEST_IMPL(udp_open_bound) {
223   struct sockaddr_in addr;
224   uv_udp_t client;
225   uv_os_sock_t sock;
226   int r;
227 
228   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
229 
230   startup();
231   sock = create_udp_socket();
232 
233   r = bind(sock, (struct sockaddr*) &addr, sizeof(addr));
234   ASSERT_OK(r);
235 
236   r = uv_udp_init(uv_default_loop(), &client);
237   ASSERT_OK(r);
238 
239   r = uv_udp_open(&client, sock);
240   ASSERT_OK(r);
241 
242   r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
243   ASSERT_OK(r);
244 
245   uv_close((uv_handle_t*) &client, NULL);
246   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
247 
248   MAKE_VALGRIND_HAPPY(uv_default_loop());
249   return 0;
250 }
251 
TEST_IMPL(udp_open_connect)252 TEST_IMPL(udp_open_connect) {
253   struct sockaddr_in addr;
254   uv_buf_t buf = uv_buf_init("PING", 4);
255   uv_udp_t client;
256   uv_udp_t server;
257   uv_os_sock_t sock;
258   int r;
259 
260   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
261 
262   startup();
263   sock = create_udp_socket();
264 
265   r = uv_udp_init(uv_default_loop(), &client);
266   ASSERT_OK(r);
267 
268   r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr));
269   ASSERT_OK(r);
270 
271   r = uv_udp_open(&client, sock);
272   ASSERT_OK(r);
273 
274   r = uv_udp_init(uv_default_loop(), &server);
275   ASSERT_OK(r);
276 
277   r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
278   ASSERT_OK(r);
279 
280   r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
281   ASSERT_OK(r);
282 
283   r = uv_udp_send(&send_req,
284                   &client,
285                   &buf,
286                   1,
287                   NULL,
288                   send_cb);
289   ASSERT_OK(r);
290 
291   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
292 
293   ASSERT_EQ(1, send_cb_called);
294   ASSERT_EQ(2, close_cb_called);
295 
296   ASSERT_OK(client.send_queue_size);
297 
298   MAKE_VALGRIND_HAPPY(uv_default_loop());
299   return 0;
300 }
301 
302 #ifndef _WIN32
TEST_IMPL(udp_send_unix)303 TEST_IMPL(udp_send_unix) {
304   /* Test that "uv_udp_send()" supports sending over
305      a "sockaddr_un" address. */
306   struct sockaddr_un addr;
307   uv_udp_t handle;
308   uv_udp_send_t req;
309   uv_loop_t* loop;
310   uv_buf_t buf = uv_buf_init("PING", 4);
311   int fd;
312   int r;
313 
314   loop = uv_default_loop();
315 
316   memset(&addr, 0, sizeof addr);
317   addr.sun_family = AF_UNIX;
318   ASSERT_LT(strlen(TEST_PIPENAME), sizeof(addr.sun_path));
319   memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME));
320 
321   fd = socket(AF_UNIX, SOCK_STREAM, 0);
322   ASSERT_GE(fd, 0);
323 
324   unlink(TEST_PIPENAME);
325   ASSERT_OK(bind(fd, (const struct sockaddr*)&addr, sizeof addr));
326   ASSERT_OK(listen(fd, 1));
327 
328   r = uv_udp_init(loop, &handle);
329   ASSERT_OK(r);
330   r = uv_udp_open(&handle, fd);
331   ASSERT_OK(r);
332   uv_run(loop, UV_RUN_DEFAULT);
333 
334   r = uv_udp_send(&req,
335                   &handle,
336                   &buf,
337                   1,
338                   (const struct sockaddr*) &addr,
339                   NULL);
340   ASSERT_OK(r);
341 
342   uv_close((uv_handle_t*)&handle, NULL);
343   uv_run(loop, UV_RUN_DEFAULT);
344   close(fd);
345   unlink(TEST_PIPENAME);
346 
347   MAKE_VALGRIND_HAPPY(loop);
348   return 0;
349 }
350 #endif
351