/src/libzmq/tests/testutil.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: MPL-2.0 */ |
2 | | #include "testutil.hpp" |
3 | | #include "testutil_unity.hpp" |
4 | | |
5 | | #include <stdarg.h> |
6 | | #include <string.h> |
7 | | |
8 | | #if defined _WIN32 |
9 | | #include "../src/windows.hpp" |
10 | | #if defined ZMQ_HAVE_WINDOWS |
11 | | #if defined ZMQ_HAVE_IPC |
12 | | #include <direct.h> |
13 | | #include <afunix.h> |
14 | | #endif |
15 | | #include <crtdbg.h> |
16 | | #pragma warning(disable : 4996) |
17 | | // iphlpapi is needed for if_nametoindex (not on Windows XP) |
18 | | #if _WIN32_WINNT > _WIN32_WINNT_WINXP |
19 | | #pragma comment(lib, "iphlpapi") |
20 | | #endif |
21 | | #endif |
22 | | #else |
23 | | #include <pthread.h> |
24 | | #include <unistd.h> |
25 | | #include <signal.h> |
26 | | #include <stdlib.h> |
27 | | #include <grp.h> |
28 | | #include <sys/wait.h> |
29 | | #include <sys/socket.h> |
30 | | #include <sys/types.h> |
31 | | #include <netinet/in.h> |
32 | | #include <arpa/inet.h> |
33 | | #include <net/if.h> |
34 | | #include <netdb.h> |
35 | | #include <sys/un.h> |
36 | | #include <dirent.h> |
37 | | #if defined(ZMQ_HAVE_AIX) |
38 | | #include <sys/types.h> |
39 | | #include <sys/socketvar.h> |
40 | | #endif |
41 | | #endif |
42 | | |
43 | | #ifndef PATH_MAX |
44 | | #define PATH_MAX 1024 |
45 | | #endif |
46 | | |
47 | | const char *SEQ_END = (const char *) 1; |
48 | | |
49 | | const char bounce_content[] = "12345678ABCDEFGH12345678abcdefgh"; |
50 | | |
51 | | static void send_bounce_msg (void *socket_) |
52 | 0 | { |
53 | 0 | send_string_expect_success (socket_, bounce_content, ZMQ_SNDMORE); |
54 | 0 | send_string_expect_success (socket_, bounce_content, 0); |
55 | 0 | } |
56 | | |
57 | | static void recv_bounce_msg (void *socket_) |
58 | 0 | { |
59 | 0 | recv_string_expect_success (socket_, bounce_content, 0); |
60 | 0 | int rcvmore; |
61 | 0 | size_t sz = sizeof (rcvmore); |
62 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
63 | 0 | zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz)); |
64 | 0 | TEST_ASSERT_TRUE (rcvmore); |
65 | 0 | recv_string_expect_success (socket_, bounce_content, 0); |
66 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
67 | 0 | zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz)); |
68 | 0 | TEST_ASSERT_FALSE (rcvmore); |
69 | 0 | } |
70 | | |
71 | | void bounce (void *server_, void *client_) |
72 | 0 | { |
73 | | // Send message from client to server |
74 | 0 | send_bounce_msg (client_); |
75 | | |
76 | | // Receive message at server side and |
77 | | // check that message is still the same |
78 | 0 | recv_bounce_msg (server_); |
79 | | |
80 | | // Send two parts back to client |
81 | 0 | send_bounce_msg (server_); |
82 | | |
83 | | // Receive the two parts at the client side |
84 | 0 | recv_bounce_msg (client_); |
85 | 0 | } |
86 | | |
87 | | static void send_bounce_msg_may_fail (void *socket_) |
88 | 0 | { |
89 | 0 | int timeout = 250; |
90 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
91 | 0 | zmq_setsockopt (socket_, ZMQ_SNDTIMEO, &timeout, sizeof (int))); |
92 | 0 | int rc = zmq_send (socket_, bounce_content, 32, ZMQ_SNDMORE); |
93 | 0 | TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN))); |
94 | 0 | rc = zmq_send (socket_, bounce_content, 32, 0); |
95 | 0 | TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN))); |
96 | 0 | } |
97 | | |
98 | | static void recv_bounce_msg_fail (void *socket_) |
99 | 0 | { |
100 | 0 | int timeout = 250; |
101 | 0 | char buffer[32]; |
102 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
103 | 0 | zmq_setsockopt (socket_, ZMQ_RCVTIMEO, &timeout, sizeof (int))); |
104 | 0 | TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (socket_, buffer, 32, 0)); |
105 | 0 | } |
106 | | |
107 | | void expect_bounce_fail (void *server_, void *client_) |
108 | 0 | { |
109 | | // Send message from client to server |
110 | 0 | send_bounce_msg_may_fail (client_); |
111 | | |
112 | | // Receive message at server side (should not succeed) |
113 | 0 | recv_bounce_msg_fail (server_); |
114 | | |
115 | | // Send message from server to client to test other direction |
116 | | // If connection failed, send may block, without a timeout |
117 | 0 | send_bounce_msg_may_fail (server_); |
118 | | |
119 | | // Receive message at client side (should not succeed) |
120 | 0 | recv_bounce_msg_fail (client_); |
121 | 0 | } |
122 | | |
123 | | char *s_recv (void *socket_) |
124 | 0 | { |
125 | 0 | char buffer[256]; |
126 | 0 | int size = zmq_recv (socket_, buffer, 255, 0); |
127 | 0 | if (size == -1) |
128 | 0 | return NULL; |
129 | 0 | if (size > 255) |
130 | 0 | size = 255; |
131 | 0 | buffer[size] = 0; |
132 | 0 | return strdup (buffer); |
133 | 0 | } |
134 | | |
135 | | void s_send_seq (void *socket_, ...) |
136 | 0 | { |
137 | 0 | va_list ap; |
138 | 0 | va_start (ap, socket_); |
139 | 0 | const char *data = va_arg (ap, const char *); |
140 | 0 | while (true) { |
141 | 0 | const char *prev = data; |
142 | 0 | data = va_arg (ap, const char *); |
143 | 0 | bool end = data == SEQ_END; |
144 | |
|
145 | 0 | if (!prev) { |
146 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
147 | 0 | zmq_send (socket_, 0, 0, end ? 0 : ZMQ_SNDMORE)); |
148 | 0 | } else { |
149 | 0 | TEST_ASSERT_SUCCESS_ERRNO (zmq_send ( |
150 | 0 | socket_, prev, strlen (prev) + 1, end ? 0 : ZMQ_SNDMORE)); |
151 | 0 | } |
152 | 0 | if (end) |
153 | 0 | break; |
154 | 0 | } |
155 | 0 | va_end (ap); |
156 | 0 | } |
157 | | |
158 | | void s_recv_seq (void *socket_, ...) |
159 | 0 | { |
160 | 0 | zmq_msg_t msg; |
161 | 0 | zmq_msg_init (&msg); |
162 | |
|
163 | 0 | int more; |
164 | 0 | size_t more_size = sizeof (more); |
165 | |
|
166 | 0 | va_list ap; |
167 | 0 | va_start (ap, socket_); |
168 | 0 | const char *data = va_arg (ap, const char *); |
169 | |
|
170 | 0 | while (true) { |
171 | 0 | TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, socket_, 0)); |
172 | |
|
173 | 0 | if (!data) |
174 | 0 | TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg)); |
175 | 0 | else |
176 | 0 | TEST_ASSERT_EQUAL_STRING (data, (const char *) zmq_msg_data (&msg)); |
177 | |
|
178 | 0 | data = va_arg (ap, const char *); |
179 | 0 | bool end = data == SEQ_END; |
180 | |
|
181 | 0 | TEST_ASSERT_SUCCESS_ERRNO ( |
182 | 0 | zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size)); |
183 | |
|
184 | 0 | TEST_ASSERT_TRUE (!more == end); |
185 | 0 | if (end) |
186 | 0 | break; |
187 | 0 | } |
188 | 0 | va_end (ap); |
189 | |
|
190 | 0 | zmq_msg_close (&msg); |
191 | 0 | } |
192 | | |
193 | | void close_zero_linger (void *socket_) |
194 | 0 | { |
195 | 0 | int linger = 0; |
196 | 0 | int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger)); |
197 | 0 | TEST_ASSERT_TRUE (rc == 0 || errno == ETERM); |
198 | 0 | TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket_)); |
199 | 0 | } |
200 | | |
201 | | void setup_test_environment (int timeout_seconds_) |
202 | 0 | { |
203 | | #if defined _WIN32 |
204 | | #if defined _MSC_VER |
205 | | _set_abort_behavior (0, _WRITE_ABORT_MSG); |
206 | | _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); |
207 | | _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR); |
208 | | #endif |
209 | | #else |
210 | | #if defined ZMQ_HAVE_CYGWIN |
211 | | // abort test after 121 seconds |
212 | | alarm (121); |
213 | | #else |
214 | 0 | #if !defined ZMQ_DISABLE_TEST_TIMEOUT |
215 | | // abort test after timeout_seconds_ seconds |
216 | 0 | alarm (timeout_seconds_); |
217 | 0 | #endif |
218 | 0 | #endif |
219 | 0 | #endif |
220 | | #if defined __MVS__ |
221 | | // z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a |
222 | | // workaround for no SO_NOGSIGPIPE socket option. |
223 | | signal (SIGPIPE, SIG_IGN); |
224 | | #endif |
225 | 0 | } |
226 | | |
227 | | void msleep (int milliseconds_) |
228 | 0 | { |
229 | | #ifdef ZMQ_HAVE_WINDOWS |
230 | | Sleep (milliseconds_); |
231 | | #else |
232 | 0 | usleep (static_cast<useconds_t> (milliseconds_) * 1000); |
233 | 0 | #endif |
234 | 0 | } |
235 | | |
236 | | int is_ipv6_available () |
237 | 0 | { |
238 | | #if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600) |
239 | | return 0; |
240 | | #else |
241 | 0 | int rc, ipv6 = 1; |
242 | 0 | struct sockaddr_in6 test_addr; |
243 | |
|
244 | 0 | memset (&test_addr, 0, sizeof (test_addr)); |
245 | 0 | test_addr.sin6_family = AF_INET6; |
246 | 0 | inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr)); |
247 | |
|
248 | 0 | fd_t fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP); |
249 | 0 | if (fd == retired_fd) |
250 | 0 | ipv6 = 0; |
251 | 0 | else { |
252 | | #ifdef ZMQ_HAVE_WINDOWS |
253 | | setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &ipv6, |
254 | | sizeof (int)); |
255 | | rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6, |
256 | | sizeof (int)); |
257 | | if (rc == SOCKET_ERROR) |
258 | | ipv6 = 0; |
259 | | else { |
260 | | rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr)); |
261 | | if (rc == SOCKET_ERROR) |
262 | | ipv6 = 0; |
263 | | } |
264 | | #else |
265 | 0 | setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof (int)); |
266 | 0 | rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof (int)); |
267 | 0 | if (rc != 0) |
268 | 0 | ipv6 = 0; |
269 | 0 | else { |
270 | 0 | rc = bind (fd, reinterpret_cast<struct sockaddr *> (&test_addr), |
271 | 0 | sizeof (test_addr)); |
272 | 0 | if (rc != 0) |
273 | 0 | ipv6 = 0; |
274 | 0 | } |
275 | 0 | #endif |
276 | 0 | close (fd); |
277 | 0 | } |
278 | |
|
279 | 0 | return ipv6; |
280 | 0 | #endif // _WIN32_WINNT < 0x0600 |
281 | 0 | } |
282 | | |
283 | | int is_tipc_available () |
284 | 0 | { |
285 | | #ifndef ZMQ_HAVE_TIPC |
286 | | return 0; |
287 | | #else |
288 | 0 | int tipc = 0; |
289 | |
|
290 | 0 | void *ctx = zmq_init (1); |
291 | 0 | TEST_ASSERT_NOT_NULL (ctx); |
292 | 0 | void *rep = zmq_socket (ctx, ZMQ_REP); |
293 | 0 | TEST_ASSERT_NOT_NULL (rep); |
294 | 0 | tipc = zmq_bind (rep, "tipc://{5560,0,0}"); |
295 | |
|
296 | 0 | zmq_close (rep); |
297 | 0 | zmq_ctx_term (ctx); |
298 | |
|
299 | 0 | return tipc == 0; |
300 | 0 | #endif // ZMQ_HAVE_TIPC |
301 | 0 | } |
302 | | |
303 | | int test_inet_pton (int af_, const char *src_, void *dst_) |
304 | 0 | { |
305 | | #if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600) |
306 | | if (af_ == AF_INET) { |
307 | | struct in_addr *ip4addr = (struct in_addr *) dst_; |
308 | | |
309 | | ip4addr->s_addr = inet_addr (src_); |
310 | | |
311 | | // INADDR_NONE is -1 which is also a valid representation for IP |
312 | | // 255.255.255.255 |
313 | | if (ip4addr->s_addr == INADDR_NONE |
314 | | && strcmp (src_, "255.255.255.255") != 0) { |
315 | | return 0; |
316 | | } |
317 | | |
318 | | // Success |
319 | | return 1; |
320 | | } else { |
321 | | // Not supported. |
322 | | return 0; |
323 | | } |
324 | | #else |
325 | 0 | return inet_pton (af_, src_, dst_); |
326 | 0 | #endif |
327 | 0 | } |
328 | | |
329 | | sockaddr_in bind_bsd_socket (int socket_) |
330 | 0 | { |
331 | 0 | struct sockaddr_in saddr; |
332 | 0 | memset (&saddr, 0, sizeof (saddr)); |
333 | 0 | saddr.sin_family = AF_INET; |
334 | 0 | saddr.sin_addr.s_addr = INADDR_ANY; |
335 | 0 | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600) |
336 | 0 | saddr.sin_port = 0; |
337 | | #else |
338 | | saddr.sin_port = htons (PORT_6); |
339 | | #endif |
340 | |
|
341 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
342 | 0 | bind (socket_, (struct sockaddr *) &saddr, sizeof (saddr))); |
343 | |
|
344 | 0 | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600) |
345 | 0 | socklen_t saddr_len = sizeof (saddr); |
346 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
347 | 0 | getsockname (socket_, (struct sockaddr *) &saddr, &saddr_len)); |
348 | 0 | #endif |
349 | |
|
350 | 0 | return saddr; |
351 | 0 | } |
352 | | |
353 | | fd_t connect_socket (const char *endpoint_, const int af_, const int protocol_) |
354 | 0 | { |
355 | 0 | struct sockaddr_storage addr; |
356 | | // OSX is very opinionated and wants the size to match the AF family type |
357 | 0 | socklen_t addr_len; |
358 | 0 | const fd_t s_pre = socket (af_, SOCK_STREAM, |
359 | 0 | protocol_ == IPPROTO_UDP ? IPPROTO_UDP |
360 | 0 | : protocol_ == IPPROTO_TCP ? IPPROTO_TCP |
361 | 0 | : 0); |
362 | | #ifdef ZMQ_HAVE_WINDOWS |
363 | | TEST_ASSERT_NOT_EQUAL (INVALID_SOCKET, s_pre); |
364 | | #else |
365 | 0 | TEST_ASSERT_NOT_EQUAL (-1, s_pre); |
366 | 0 | #endif |
367 | |
|
368 | 0 | if (af_ == AF_INET || af_ == AF_INET6) { |
369 | 0 | const char *port = strrchr (endpoint_, ':') + 1; |
370 | 0 | char address[MAX_SOCKET_STRING]; |
371 | | // getaddrinfo does not like [x:y::z] |
372 | 0 | if (*strchr (endpoint_, '/') + 2 == '[') { |
373 | 0 | strcpy (address, strchr (endpoint_, '[') + 1); |
374 | 0 | address[strlen (address) - strlen (port) - 2] = '\0'; |
375 | 0 | } else { |
376 | 0 | strcpy (address, strchr (endpoint_, '/') + 2); |
377 | 0 | address[strlen (address) - strlen (port) - 1] = '\0'; |
378 | 0 | } |
379 | |
|
380 | 0 | struct addrinfo *in, hint; |
381 | 0 | memset (&hint, 0, sizeof (struct addrinfo)); |
382 | 0 | hint.ai_flags = AI_NUMERICSERV; |
383 | 0 | hint.ai_family = af_; |
384 | 0 | hint.ai_socktype = protocol_ == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; |
385 | 0 | hint.ai_protocol = protocol_ == IPPROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; |
386 | |
|
387 | 0 | TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO ( |
388 | 0 | getaddrinfo (address, port, &hint, &in)); |
389 | 0 | TEST_ASSERT_NOT_NULL (in); |
390 | 0 | memcpy (&addr, in->ai_addr, in->ai_addrlen); |
391 | 0 | addr_len = (socklen_t) in->ai_addrlen; |
392 | 0 | freeaddrinfo (in); |
393 | 0 | } else { |
394 | 0 | #if defined(ZMQ_HAVE_IPC) |
395 | | // Cannot cast addr as gcc 4.4 will fail with strict aliasing errors |
396 | 0 | (*(struct sockaddr_un *) &addr).sun_family = AF_UNIX; |
397 | 0 | strcpy ((*(struct sockaddr_un *) &addr).sun_path, endpoint_); |
398 | 0 | addr_len = sizeof (struct sockaddr_un); |
399 | | #else |
400 | | return retired_fd; |
401 | | #endif |
402 | 0 | } |
403 | |
|
404 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
405 | 0 | connect (s_pre, (struct sockaddr *) &addr, addr_len)); |
406 | |
|
407 | 0 | return s_pre; |
408 | 0 | } |
409 | | |
410 | | fd_t bind_socket_resolve_port (const char *address_, |
411 | | const char *port_, |
412 | | char *my_endpoint_, |
413 | | const int af_, |
414 | | const int protocol_) |
415 | 0 | { |
416 | 0 | struct sockaddr_storage addr; |
417 | | // OSX is very opinionated and wants the size to match the AF family type |
418 | 0 | socklen_t addr_len; |
419 | 0 | const fd_t s_pre = socket (af_, SOCK_STREAM, |
420 | 0 | protocol_ == IPPROTO_UDP ? IPPROTO_UDP |
421 | 0 | : protocol_ == IPPROTO_TCP ? IPPROTO_TCP |
422 | 0 | : 0); |
423 | | #ifdef ZMQ_HAVE_WINDOWS |
424 | | TEST_ASSERT_NOT_EQUAL (INVALID_SOCKET, s_pre); |
425 | | #else |
426 | 0 | TEST_ASSERT_NOT_EQUAL (-1, s_pre); |
427 | 0 | #endif |
428 | |
|
429 | 0 | if (af_ == AF_INET || af_ == AF_INET6) { |
430 | | #ifdef ZMQ_HAVE_WINDOWS |
431 | | const char flag = '\1'; |
432 | | #elif defined ZMQ_HAVE_VXWORKS |
433 | | char flag = '\1'; |
434 | | #else |
435 | 0 | int flag = 1; |
436 | 0 | #endif |
437 | 0 | struct addrinfo *in, hint; |
438 | 0 | memset (&hint, 0, sizeof (struct addrinfo)); |
439 | 0 | hint.ai_flags = AI_NUMERICSERV; |
440 | 0 | hint.ai_family = af_; |
441 | 0 | hint.ai_socktype = protocol_ == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; |
442 | 0 | hint.ai_protocol = protocol_ == IPPROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; |
443 | |
|
444 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
445 | 0 | setsockopt (s_pre, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int))); |
446 | 0 | TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO ( |
447 | 0 | getaddrinfo (address_, port_, &hint, &in)); |
448 | 0 | TEST_ASSERT_NOT_NULL (in); |
449 | 0 | memcpy (&addr, in->ai_addr, in->ai_addrlen); |
450 | 0 | addr_len = (socklen_t) in->ai_addrlen; |
451 | 0 | freeaddrinfo (in); |
452 | 0 | } else { |
453 | 0 | #if defined(ZMQ_HAVE_IPC) |
454 | | // Cannot cast addr as gcc 4.4 will fail with strict aliasing errors |
455 | 0 | (*(struct sockaddr_un *) &addr).sun_family = AF_UNIX; |
456 | 0 | addr_len = sizeof (struct sockaddr_un); |
457 | | #if defined ZMQ_HAVE_WINDOWS |
458 | | char buffer[MAX_PATH] = ""; |
459 | | |
460 | | TEST_ASSERT_SUCCESS_RAW_ERRNO (tmpnam_s (buffer)); |
461 | | TEST_ASSERT_SUCCESS_RAW_ERRNO (_mkdir (buffer)); |
462 | | strcat (buffer, "/ipc"); |
463 | | #else |
464 | 0 | char buffer[PATH_MAX] = ""; |
465 | 0 | strcpy (buffer, "tmpXXXXXX"); |
466 | 0 | #ifdef HAVE_MKDTEMP |
467 | 0 | TEST_ASSERT_TRUE (mkdtemp (buffer)); |
468 | 0 | strcat (buffer, "/socket"); |
469 | | #else |
470 | | int fd = mkstemp (buffer); |
471 | | TEST_ASSERT_TRUE (fd != -1); |
472 | | close (fd); |
473 | | #endif |
474 | 0 | #endif |
475 | 0 | strcpy ((*(struct sockaddr_un *) &addr).sun_path, buffer); |
476 | 0 | memcpy (my_endpoint_, "ipc://", 7); |
477 | 0 | strcat (my_endpoint_, buffer); |
478 | | |
479 | | // TODO check return value of unlink |
480 | 0 | unlink (buffer); |
481 | | #else |
482 | | return retired_fd; |
483 | | #endif |
484 | 0 | } |
485 | |
|
486 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
487 | 0 | bind (s_pre, (struct sockaddr *) &addr, addr_len)); |
488 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO (listen (s_pre, SOMAXCONN)); |
489 | |
|
490 | 0 | if (af_ == AF_INET || af_ == AF_INET6) { |
491 | 0 | addr_len = sizeof (struct sockaddr_storage); |
492 | 0 | TEST_ASSERT_SUCCESS_RAW_ERRNO ( |
493 | 0 | getsockname (s_pre, (struct sockaddr *) &addr, &addr_len)); |
494 | 0 | snprintf ( |
495 | 0 | my_endpoint_, 6 + strlen (address_) + 7 * sizeof (char), "%s://%s:%u", |
496 | 0 | protocol_ == IPPROTO_TCP ? "tcp" |
497 | 0 | : protocol_ == IPPROTO_UDP ? "udp" |
498 | 0 | : protocol_ == IPPROTO_WSS ? "wss" |
499 | 0 | : "ws", |
500 | 0 | address_, |
501 | 0 | af_ == AF_INET ? ntohs ((*(struct sockaddr_in *) &addr).sin_port) |
502 | 0 | : ntohs ((*(struct sockaddr_in6 *) &addr).sin6_port)); |
503 | 0 | } |
504 | |
|
505 | 0 | return s_pre; |
506 | 0 | } |
507 | | |
508 | | bool streq (const char *lhs_, const char *rhs_) |
509 | 0 | { |
510 | 0 | return strcmp (lhs_, rhs_) == 0; |
511 | 0 | } |
512 | | |
513 | | bool strneq (const char *lhs_, const char *rhs_) |
514 | 0 | { |
515 | 0 | return strcmp (lhs_, rhs_) != 0; |
516 | 0 | } |
517 | | |
518 | | #if defined _WIN32 |
519 | | int fuzzer_corpus_encode (const char *dirname, |
520 | | uint8_t ***data, |
521 | | size_t **len, |
522 | | size_t *num_cases) |
523 | | { |
524 | | (void) dirname; |
525 | | (void) data; |
526 | | (void) len; |
527 | | (void) num_cases; |
528 | | |
529 | | return -1; |
530 | | } |
531 | | |
532 | | #else |
533 | | |
534 | | int fuzzer_corpus_encode (const char *dirname, |
535 | | uint8_t ***data, |
536 | | size_t **len, |
537 | | size_t *num_cases) |
538 | 0 | { |
539 | 0 | TEST_ASSERT_NOT_NULL (dirname); |
540 | 0 | TEST_ASSERT_NOT_NULL (data); |
541 | 0 | TEST_ASSERT_NOT_NULL (len); |
542 | |
|
543 | 0 | struct dirent *ent; |
544 | 0 | DIR *dir = opendir (dirname); |
545 | 0 | if (!dir) |
546 | 0 | return -1; |
547 | | |
548 | 0 | *len = NULL; |
549 | 0 | *data = NULL; |
550 | 0 | *num_cases = 0; |
551 | |
|
552 | 0 | while ((ent = readdir (dir)) != NULL) { |
553 | 0 | if (!strcmp (ent->d_name, ".") || !strcmp (ent->d_name, "..")) |
554 | 0 | continue; |
555 | | |
556 | 0 | char *filename = |
557 | 0 | (char *) malloc (strlen (dirname) + strlen (ent->d_name) + 2); |
558 | 0 | TEST_ASSERT_NOT_NULL (filename); |
559 | 0 | strcpy (filename, dirname); |
560 | 0 | strcat (filename, "/"); |
561 | 0 | strcat (filename, ent->d_name); |
562 | 0 | FILE *f = fopen (filename, "r"); |
563 | 0 | free (filename); |
564 | 0 | if (!f) |
565 | 0 | continue; |
566 | | |
567 | 0 | fseek (f, 0, SEEK_END); |
568 | 0 | size_t file_len = ftell (f); |
569 | 0 | fseek (f, 0, SEEK_SET); |
570 | 0 | if (file_len == 0) { |
571 | 0 | fclose (f); |
572 | 0 | continue; |
573 | 0 | } |
574 | | |
575 | 0 | *len = (size_t *) realloc (*len, (*num_cases + 1) * sizeof (size_t)); |
576 | 0 | TEST_ASSERT_NOT_NULL (*len); |
577 | 0 | *(*len + *num_cases) = file_len; |
578 | 0 | *data = |
579 | 0 | (uint8_t **) realloc (*data, (*num_cases + 1) * sizeof (uint8_t *)); |
580 | 0 | TEST_ASSERT_NOT_NULL (*data); |
581 | 0 | *(*data + *num_cases) = |
582 | 0 | (uint8_t *) malloc (file_len * sizeof (uint8_t)); |
583 | 0 | TEST_ASSERT_NOT_NULL (*(*data + *num_cases)); |
584 | 0 | size_t read_bytes = 0; |
585 | 0 | read_bytes = fread (*(*data + *num_cases), 1, file_len, f); |
586 | 0 | TEST_ASSERT_EQUAL (file_len, read_bytes); |
587 | 0 | (*num_cases)++; |
588 | |
|
589 | 0 | fclose (f); |
590 | 0 | } |
591 | |
|
592 | 0 | closedir (dir); |
593 | |
|
594 | 0 | return 0; |
595 | 0 | } |
596 | | #endif |