Home | History | Annotate | Line # | Download | only in isc
      1 /*	$NetBSD: stream_shutdown.c,v 1.2 2025/01/26 16:25:50 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <inttypes.h>
     17 #include <sched.h> /* IWYU pragma: keep */
     18 #include <setjmp.h>
     19 #include <signal.h>
     20 #include <stdarg.h>
     21 #include <stdlib.h>
     22 #include <unistd.h>
     23 
     24 /*
     25  * As a workaround, include an OpenSSL header file before including cmocka.h,
     26  * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a
     27  * redefined malloc in cmocka.h.
     28  */
     29 #include <openssl/err.h>
     30 
     31 #define UNIT_TESTING
     32 #include <cmocka.h>
     33 
     34 #include "netmgr_common.h"
     35 
     36 #include <tests/isc.h>
     37 
     38 /*
     39  * FIXME: This really needs two network managers, so there's predictable result
     40  * when shuttingdown the netmgr - right now there's a race whether the listening
     41  * or connecting sockets gets shutdown first
     42  */
     43 
     44 static void
     45 shutdownconnect_connectcb(isc_nmhandle_t *handle, isc_result_t eresult,
     46 			  void *cbarg) {
     47 	F();
     48 
     49 	assert_non_null(handle);
     50 	assert_int_equal(eresult, ISC_R_SHUTTINGDOWN);
     51 	assert_null(cbarg);
     52 
     53 	isc_refcount_decrement(&active_cconnects);
     54 
     55 	atomic_fetch_add(&cconnects, 1);
     56 }
     57 
     58 int
     59 stream_shutdownconnect_setup(void **state ISC_ATTR_UNUSED) {
     60 	int r = setup_netmgr_test(state);
     61 	return r;
     62 }
     63 
     64 int
     65 proxystream_shutdownconnect_setup(void **state) {
     66 	stream_use_PROXY = true;
     67 	return stream_shutdownconnect_setup(state);
     68 }
     69 
     70 int
     71 proxystream_shutdownconnect_teardown(void **state) {
     72 	int r = stream_shutdownconnect_teardown(state);
     73 	stream_use_PROXY = false;
     74 	return r;
     75 }
     76 
     77 int
     78 proxystreamtls_shutdownconnect_setup(void **state) {
     79 	stream_PROXY_over_TLS = true;
     80 	return proxystream_shutdownconnect_setup(state);
     81 }
     82 
     83 int
     84 proxystreamtls_shutdownconnect_teardown(void **state) {
     85 	int r = proxystream_shutdownconnect_teardown(state);
     86 	stream_PROXY_over_TLS = false;
     87 	return r;
     88 }
     89 
     90 void
     91 stream_shutdownconnect(void **state ISC_ATTR_UNUSED) {
     92 	isc_result_t result = stream_listen(stream_accept_cb, NULL, 128, NULL,
     93 					    &listen_sock);
     94 	assert_int_equal(result, ISC_R_SUCCESS);
     95 	isc_loop_teardown(mainloop, stop_listening, listen_sock);
     96 
     97 	/* Schedule the shutdown before the connect */
     98 	isc_loopmgr_shutdown(loopmgr);
     99 
    100 	stream_connect(shutdownconnect_connectcb, NULL, T_CONNECT);
    101 }
    102 
    103 int
    104 stream_shutdownconnect_teardown(void **state ISC_ATTR_UNUSED) {
    105 	X(cconnects);
    106 	X(csends);
    107 	X(creads);
    108 
    109 	atomic_assert_int_eq(cconnects, 1);
    110 	atomic_assert_int_eq(csends, 0);
    111 	atomic_assert_int_eq(creads, 0);
    112 
    113 	return teardown_netmgr_test(state);
    114 }
    115 
    116 /* Issue the shutdown before reading */
    117 
    118 static void
    119 shutdownread_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
    120 		    isc_region_t *region, void *cbarg) {
    121 	F();
    122 	assert_non_null(handle);
    123 	assert_true(eresult == ISC_R_SHUTTINGDOWN ||
    124 		    eresult == ISC_R_CONNECTIONRESET || eresult == ISC_R_EOF);
    125 	assert_non_null(region);
    126 	assert_null(cbarg);
    127 
    128 	atomic_fetch_add(&creads, 1);
    129 	isc_nmhandle_detach(&handle);
    130 	isc_refcount_decrement(&active_creads);
    131 }
    132 
    133 static void
    134 shutdownread_sendcb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
    135 	F();
    136 	assert_non_null(handle);
    137 	assert_true(eresult == ISC_R_SUCCESS || eresult == ISC_R_SHUTTINGDOWN ||
    138 		    eresult == ISC_R_CONNECTIONRESET || eresult == ISC_R_EOF);
    139 	assert_null(cbarg);
    140 
    141 	atomic_fetch_add(&csends, 1);
    142 
    143 	isc_nmhandle_detach(&handle);
    144 	isc_refcount_decrement(&active_csends);
    145 }
    146 
    147 static void
    148 shutdownread_connectcb(isc_nmhandle_t *handle, isc_result_t eresult,
    149 		       void *cbarg) {
    150 	F();
    151 
    152 	assert_non_null(handle);
    153 	assert_int_equal(eresult, ISC_R_SUCCESS);
    154 	assert_null(cbarg);
    155 
    156 	isc_refcount_decrement(&active_cconnects);
    157 
    158 	atomic_fetch_add(&cconnects, 1);
    159 
    160 	/* Schedule the shutdown before read and send */
    161 	isc_loopmgr_shutdown(loopmgr);
    162 
    163 	isc_refcount_increment0(&active_creads);
    164 	isc_nmhandle_ref(handle);
    165 	isc_nm_read(handle, shutdownread_readcb, cbarg);
    166 
    167 	isc_refcount_increment0(&active_csends);
    168 	isc_nmhandle_ref(handle);
    169 	isc_nm_send(handle, (isc_region_t *)&send_msg, shutdownread_sendcb,
    170 		    cbarg);
    171 }
    172 
    173 int
    174 stream_shutdownread_setup(void **state ISC_ATTR_UNUSED) {
    175 	int r = setup_netmgr_test(state);
    176 	return r;
    177 }
    178 
    179 int
    180 proxystream_shutdownread_setup(void **state) {
    181 	stream_use_PROXY = true;
    182 	return stream_shutdownread_setup(state);
    183 }
    184 
    185 int
    186 proxystream_shutdownread_teardown(void **state) {
    187 	int r = stream_shutdownread_teardown(state);
    188 	stream_use_PROXY = false;
    189 	return r;
    190 }
    191 
    192 int
    193 proxystreamtls_shutdownread_setup(void **state) {
    194 	stream_PROXY_over_TLS = true;
    195 	return proxystream_shutdownread_setup(state);
    196 }
    197 
    198 int
    199 proxystreamtls_shutdownread_teardown(void **state) {
    200 	int r = proxystream_shutdownread_teardown(state);
    201 	stream_PROXY_over_TLS = false;
    202 	return r;
    203 }
    204 
    205 void
    206 stream_shutdownread(void **state ISC_ATTR_UNUSED) {
    207 	isc_result_t result = stream_listen(stream_accept_cb, NULL, 128, NULL,
    208 					    &listen_sock);
    209 	assert_int_equal(result, ISC_R_SUCCESS);
    210 	isc_loop_teardown(mainloop, stop_listening, listen_sock);
    211 
    212 	stream_connect(shutdownread_connectcb, NULL, T_CONNECT);
    213 }
    214 
    215 int
    216 stream_shutdownread_teardown(void **state ISC_ATTR_UNUSED) {
    217 	X(cconnects);
    218 	X(csends);
    219 	X(creads);
    220 
    221 	atomic_assert_int_eq(cconnects, 1);
    222 	atomic_assert_int_eq(csends, 1);
    223 	atomic_assert_int_eq(creads, 1);
    224 
    225 	return teardown_netmgr_test(state);
    226 }
    227