xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/test/testsock.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "testutil.h"
18 #include "testsock.h"
19 #include "apr_thread_proc.h"
20 #include "apr_network_io.h"
21 #include "apr_errno.h"
22 #include "apr_general.h"
23 #include "apr_lib.h"
24 #include "apr_strings.h"
25 #include "apr_poll.h"
26 #define APR_WANT_BYTEFUNC
27 #include "apr_want.h"
28 
launch_child(abts_case * tc,apr_proc_t * proc,const char * arg1,apr_pool_t * p)29 static void launch_child(abts_case *tc, apr_proc_t *proc, const char *arg1, apr_pool_t *p)
30 {
31     apr_procattr_t *procattr;
32     const char *args[3];
33     apr_status_t rv;
34 
35     rv = apr_procattr_create(&procattr, p);
36     APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv);
37 
38     rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE,
39             APR_NO_PIPE);
40     APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv);
41 
42     rv = apr_procattr_error_check_set(procattr, 1);
43     APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv);
44 
45     rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
46     APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);
47 
48     args[0] = "sockchild" EXTENSION;
49     args[1] = arg1;
50     args[2] = NULL;
51     rv = apr_proc_create(proc, TESTBINPATH "sockchild" EXTENSION, args, NULL,
52                          procattr, p);
53     APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv);
54 }
55 
wait_child(abts_case * tc,apr_proc_t * proc)56 static int wait_child(abts_case *tc, apr_proc_t *proc)
57 {
58     int exitcode;
59     apr_exit_why_e why;
60 
61     ABTS_ASSERT(tc, "Error waiting for child process",
62             apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE);
63 
64     ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT);
65     return exitcode;
66 }
67 
test_addr_info(abts_case * tc,void * data)68 static void test_addr_info(abts_case *tc, void *data)
69 {
70     apr_status_t rv;
71     apr_sockaddr_t *sa;
72     int rc;
73 
74     rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 80, 0, p);
75     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
76 
77     rc = apr_sockaddr_is_wildcard(sa);
78     ABTS_INT_NEQUAL(tc, 0, rc);
79 
80     rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 80, 0, p);
81     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
82     ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
83 
84     rc = apr_sockaddr_is_wildcard(sa);
85     ABTS_INT_EQUAL(tc, 0, rc);
86 
87     rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 0, 0, p);
88     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
89     ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
90     ABTS_INT_EQUAL(tc, 0, sa->port);
91     ABTS_INT_EQUAL(tc, 0, ntohs(sa->sa.sin.sin_port));
92 }
93 
test_serv_by_name(abts_case * tc,void * data)94 static void test_serv_by_name(abts_case *tc, void *data)
95 {
96     apr_status_t rv;
97     apr_sockaddr_t *sa;
98 
99     rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 0, 0, p);
100     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
101 
102     rv = apr_getservbyname(sa, "ftp");
103     APR_ASSERT_SUCCESS(tc, "Problem getting ftp service", rv);
104     ABTS_INT_EQUAL(tc, 21, sa->port);
105 
106     rv = apr_getservbyname(sa, "complete_and_utter_rubbish");
107     APR_ASSERT_SUCCESS(tc, "Problem getting non-existent service", !rv);
108 
109     rv = apr_getservbyname(sa, "telnet");
110     APR_ASSERT_SUCCESS(tc, "Problem getting telnet service", rv);
111     ABTS_INT_EQUAL(tc, 23, sa->port);
112 }
113 
setup_socket(abts_case * tc)114 static apr_socket_t *setup_socket(abts_case *tc)
115 {
116     apr_status_t rv;
117     apr_sockaddr_t *sa;
118     apr_socket_t *sock;
119 
120     rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8021, 0, p);
121     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
122 
123     rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
124     APR_ASSERT_SUCCESS(tc, "Problem creating socket", rv);
125 
126     rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
127     APR_ASSERT_SUCCESS(tc, "Could not set REUSEADDR on socket", rv);
128 
129     rv = apr_socket_bind(sock, sa);
130     APR_ASSERT_SUCCESS(tc, "Problem binding to port", rv);
131     if (rv) return NULL;
132 
133     rv = apr_socket_listen(sock, 5);
134     APR_ASSERT_SUCCESS(tc, "Problem listening on socket", rv);
135 
136     return sock;
137 }
138 
test_create_bind_listen(abts_case * tc,void * data)139 static void test_create_bind_listen(abts_case *tc, void *data)
140 {
141     apr_status_t rv;
142     apr_socket_t *sock = setup_socket(tc);
143 
144     if (!sock) return;
145 
146     rv = apr_socket_close(sock);
147     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
148 }
149 
test_send(abts_case * tc,void * data)150 static void test_send(abts_case *tc, void *data)
151 {
152     apr_status_t rv;
153     apr_socket_t *sock;
154     apr_socket_t *sock2;
155     apr_proc_t proc;
156     int protocol;
157     apr_size_t length;
158 
159     sock = setup_socket(tc);
160     if (!sock) return;
161 
162     launch_child(tc, &proc, "read", p);
163 
164     rv = apr_socket_accept(&sock2, sock, p);
165     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
166 
167     apr_socket_protocol_get(sock2, &protocol);
168     ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
169 
170     length = strlen(DATASTR);
171     apr_socket_send(sock2, DATASTR, &length);
172 
173     /* Make sure that the client received the data we sent */
174     ABTS_SIZE_EQUAL(tc, strlen(DATASTR), wait_child(tc, &proc));
175 
176     rv = apr_socket_close(sock2);
177     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
178     rv = apr_socket_close(sock);
179     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
180 }
181 
test_recv(abts_case * tc,void * data)182 static void test_recv(abts_case *tc, void *data)
183 {
184     apr_status_t rv;
185     apr_socket_t *sock;
186     apr_socket_t *sock2;
187     apr_proc_t proc;
188     int protocol;
189     apr_size_t length = STRLEN;
190     char datastr[STRLEN];
191 
192     sock = setup_socket(tc);
193     if (!sock) return;
194 
195     launch_child(tc, &proc, "write", p);
196 
197     rv = apr_socket_accept(&sock2, sock, p);
198     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
199 
200     apr_socket_protocol_get(sock2, &protocol);
201     ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
202 
203     memset(datastr, 0, STRLEN);
204     apr_socket_recv(sock2, datastr, &length);
205 
206     /* Make sure that the server received the data we sent */
207     ABTS_STR_EQUAL(tc, DATASTR, datastr);
208     ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
209 
210     rv = apr_socket_close(sock2);
211     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
212     rv = apr_socket_close(sock);
213     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
214 }
215 
test_atreadeof(abts_case * tc,void * data)216 static void test_atreadeof(abts_case *tc, void *data)
217 {
218     apr_status_t rv;
219     apr_socket_t *sock;
220     apr_socket_t *sock2;
221     apr_proc_t proc;
222     apr_size_t length = STRLEN;
223     char datastr[STRLEN];
224     int atreadeof = -1;
225 
226     sock = setup_socket(tc);
227     if (!sock) return;
228 
229     launch_child(tc, &proc, "write", p);
230 
231     rv = apr_socket_accept(&sock2, sock, p);
232     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
233 
234     /* Check that the remote socket is still open */
235     rv = apr_socket_atreadeof(sock2, &atreadeof);
236     APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #1", rv);
237     ABTS_INT_EQUAL(tc, 0, atreadeof);
238 
239     memset(datastr, 0, STRLEN);
240     apr_socket_recv(sock2, datastr, &length);
241 
242     /* Make sure that the server received the data we sent */
243     ABTS_STR_EQUAL(tc, DATASTR, datastr);
244     ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
245 
246     /* The child is dead, so should be the remote socket */
247     rv = apr_socket_atreadeof(sock2, &atreadeof);
248     APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #2", rv);
249     ABTS_INT_EQUAL(tc, 1, atreadeof);
250 
251     rv = apr_socket_close(sock2);
252     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
253 
254     launch_child(tc, &proc, "close", p);
255 
256     rv = apr_socket_accept(&sock2, sock, p);
257     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
258 
259     /* The child closed the socket as soon as it could... */
260     rv = apr_socket_atreadeof(sock2, &atreadeof);
261     APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #3", rv);
262     if (!atreadeof) { /* ... but perhaps not yet; wait a moment */
263         apr_sleep(apr_time_from_msec(5));
264         rv = apr_socket_atreadeof(sock2, &atreadeof);
265         APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #4", rv);
266     }
267     ABTS_INT_EQUAL(tc, 1, atreadeof);
268     wait_child(tc, &proc);
269 
270     rv = apr_socket_close(sock2);
271     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
272 
273     rv = apr_socket_close(sock);
274     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
275 }
276 
test_timeout(abts_case * tc,void * data)277 static void test_timeout(abts_case *tc, void *data)
278 {
279     apr_status_t rv;
280     apr_socket_t *sock;
281     apr_socket_t *sock2;
282     apr_proc_t proc;
283     int protocol;
284     int exit;
285 
286     sock = setup_socket(tc);
287     if (!sock) return;
288 
289     launch_child(tc, &proc, "read", p);
290 
291     rv = apr_socket_accept(&sock2, sock, p);
292     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
293 
294     apr_socket_protocol_get(sock2, &protocol);
295     ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
296 
297     exit = wait_child(tc, &proc);
298     ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit);
299 
300     /* We didn't write any data, so make sure the child program returns
301      * an error.
302      */
303     rv = apr_socket_close(sock2);
304     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
305     rv = apr_socket_close(sock);
306     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
307 }
308 
test_print_addr(abts_case * tc,void * data)309 static void test_print_addr(abts_case *tc, void *data)
310 {
311     apr_sockaddr_t *sa;
312     apr_status_t rv;
313     char *s;
314 
315     rv = apr_sockaddr_info_get(&sa, "0.0.0.0", APR_INET, 80, 0, p);
316     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
317 
318     s = apr_psprintf(p, "foo %pI bar", sa);
319 
320     ABTS_STR_EQUAL(tc, "foo 0.0.0.0:80 bar", s);
321 
322 #if APR_HAVE_IPV6
323     rv = apr_sockaddr_info_get(&sa, "::ffff:0.0.0.0", APR_INET6, 80, 0, p);
324     APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
325     if (rv == APR_SUCCESS)
326         ABTS_TRUE(tc, sa != NULL);
327     if (rv == APR_SUCCESS && sa) {
328         /* sa should now be a v4-mapped IPv6 address. */
329         char buf[128];
330         int rc;
331 
332         rc = apr_sockaddr_is_wildcard(sa);
333         ABTS_INT_NEQUAL(tc, 0, rc);
334 
335         memset(buf, 'z', sizeof buf);
336 
337         APR_ASSERT_SUCCESS(tc, "could not get IP address",
338                            apr_sockaddr_ip_getbuf(buf, 22, sa));
339 
340         ABTS_STR_EQUAL(tc, "0.0.0.0", buf);
341     }
342 #endif
343 }
344 
test_get_addr(abts_case * tc,void * data)345 static void test_get_addr(abts_case *tc, void *data)
346 {
347     apr_status_t rv;
348     apr_socket_t *ld, *sd, *cd;
349     apr_sockaddr_t *sa, *ca;
350     apr_pool_t *subp;
351     char *a, *b;
352 
353     APR_ASSERT_SUCCESS(tc, "create subpool", apr_pool_create(&subp, p));
354 
355     ld = setup_socket(tc);
356     if (!ld) return;
357 
358     APR_ASSERT_SUCCESS(tc,
359                        "get local address of bound socket",
360                        apr_socket_addr_get(&sa, APR_LOCAL, ld));
361 
362     rv = apr_socket_create(&cd, sa->family, SOCK_STREAM,
363                            APR_PROTO_TCP, subp);
364     APR_ASSERT_SUCCESS(tc, "create client socket", rv);
365 
366     APR_ASSERT_SUCCESS(tc, "enable non-block mode",
367                        apr_socket_opt_set(cd, APR_SO_NONBLOCK, 1));
368 
369     /* It is valid for a connect() on a socket with NONBLOCK set to
370      * succeed (if the connection can be established synchronously),
371      * but if it does, this test cannot proceed.  */
372     rv = apr_socket_connect(cd, sa);
373     if (rv == APR_SUCCESS) {
374         apr_socket_close(ld);
375         apr_socket_close(cd);
376         ABTS_NOT_IMPL(tc, "Cannot test if connect completes "
377                       "synchronously");
378         return;
379     }
380 
381     if (!APR_STATUS_IS_EINPROGRESS(rv)) {
382         apr_socket_close(ld);
383         apr_socket_close(cd);
384         APR_ASSERT_SUCCESS(tc, "connect to listener", rv);
385         return;
386     }
387 
388     APR_ASSERT_SUCCESS(tc, "accept connection",
389                        apr_socket_accept(&sd, ld, subp));
390 
391     {
392         /* wait for writability */
393         apr_pollfd_t pfd;
394         int n;
395 
396         pfd.p = p;
397         pfd.desc_type = APR_POLL_SOCKET;
398         pfd.reqevents = APR_POLLOUT|APR_POLLHUP;
399         pfd.desc.s = cd;
400         pfd.client_data = NULL;
401 
402         APR_ASSERT_SUCCESS(tc, "poll for connect completion",
403                            apr_poll(&pfd, 1, &n, 5 * APR_USEC_PER_SEC));
404 
405     }
406 
407     APR_ASSERT_SUCCESS(tc, "get local address of server socket",
408                        apr_socket_addr_get(&sa, APR_LOCAL, sd));
409     APR_ASSERT_SUCCESS(tc, "get remote address of client socket",
410                        apr_socket_addr_get(&ca, APR_REMOTE, cd));
411 
412     /* Test that the pool of the returned sockaddr objects exactly
413      * match the socket. */
414     ABTS_PTR_EQUAL(tc, subp, sa->pool);
415     ABTS_PTR_EQUAL(tc, subp, ca->pool);
416 
417     /* Check equivalence. */
418     a = apr_psprintf(p, "%pI fam=%d", sa, sa->family);
419     b = apr_psprintf(p, "%pI fam=%d", ca, ca->family);
420     ABTS_STR_EQUAL(tc, a, b);
421 
422     /* Check pool of returned sockaddr, as above. */
423     APR_ASSERT_SUCCESS(tc, "get local address of client socket",
424                        apr_socket_addr_get(&sa, APR_LOCAL, cd));
425     APR_ASSERT_SUCCESS(tc, "get remote address of server socket",
426                        apr_socket_addr_get(&ca, APR_REMOTE, sd));
427 
428     /* Check equivalence. */
429     a = apr_psprintf(p, "%pI fam=%d", sa, sa->family);
430     b = apr_psprintf(p, "%pI fam=%d", ca, ca->family);
431     ABTS_STR_EQUAL(tc, a, b);
432 
433     ABTS_PTR_EQUAL(tc, subp, sa->pool);
434     ABTS_PTR_EQUAL(tc, subp, ca->pool);
435 
436     apr_socket_close(cd);
437     apr_socket_close(sd);
438     apr_socket_close(ld);
439 
440     apr_pool_destroy(subp);
441 }
442 
443 /* Make sure that setting a connected socket non-blocking works
444  * when the listening socket was non-blocking.
445  * If APR thinks that non-blocking is inherited but it really
446  * isn't, this testcase will fail.
447  */
test_nonblock_inheritance(abts_case * tc,void * data)448 static void test_nonblock_inheritance(abts_case *tc, void *data)
449 {
450     apr_status_t rv;
451     apr_socket_t *sock;
452     apr_socket_t *sock2;
453     apr_proc_t proc;
454     char buffer[10];
455     apr_size_t length;
456     int tries;
457 
458     sock = setup_socket(tc);
459     if (!sock) return;
460 
461     rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1);
462     APR_ASSERT_SUCCESS(tc, "Could not make listening socket nonblocking", rv);
463 
464     launch_child(tc, &proc, "write_after_delay", p);
465 
466     tries = 10;
467     while (tries--) {
468         rv = apr_socket_accept(&sock2, sock, p);
469         if (!APR_STATUS_IS_EAGAIN(rv)) {
470             break;
471         }
472         apr_sleep(apr_time_from_msec(50));
473     }
474     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
475 
476     rv = apr_socket_opt_set(sock2, APR_SO_NONBLOCK, 1);
477     APR_ASSERT_SUCCESS(tc, "Could not make connected socket nonblocking", rv);
478 
479     length = sizeof buffer;
480     rv = apr_socket_recv(sock2, buffer, &length);
481     ABTS_ASSERT(tc, "should have gotten EAGAIN", APR_STATUS_IS_EAGAIN(rv));
482 
483     wait_child(tc, &proc);
484 
485     rv = apr_socket_close(sock2);
486     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
487     rv = apr_socket_close(sock);
488     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
489 }
490 
testsock(abts_suite * suite)491 abts_suite *testsock(abts_suite *suite)
492 {
493     suite = ADD_SUITE(suite)
494 
495     abts_run_test(suite, test_addr_info, NULL);
496     abts_run_test(suite, test_serv_by_name, NULL);
497     abts_run_test(suite, test_create_bind_listen, NULL);
498     abts_run_test(suite, test_send, NULL);
499     abts_run_test(suite, test_recv, NULL);
500     abts_run_test(suite, test_atreadeof, NULL);
501     abts_run_test(suite, test_timeout, NULL);
502     abts_run_test(suite, test_print_addr, NULL);
503     abts_run_test(suite, test_get_addr, NULL);
504     abts_run_test(suite, test_nonblock_inheritance, NULL);
505 
506     return suite;
507 }
508 
509