Skip to content

Commit 9e1c70a

Browse files
committed
test-improvements
1 parent 2787ec6 commit 9e1c70a

8 files changed

Lines changed: 145 additions & 42 deletions

File tree

cmake/LwsCheckRequirements.cmake

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,44 @@ function(lws_get_free_port VAR_NAME)
155155

156156
set(${VAR_NAME} ${port} PARENT_SCOPE)
157157
endfunction()
158+
159+
#
160+
# lws_get_free_ports(VAR_NAME COUNT)
161+
#
162+
# Like lws_get_free_port(), but reserves a contiguous block of COUNT adjacent
163+
# ports under the same counter lock, returning the base (lowest) port in
164+
# VAR_NAME. Use this when a single test process listens on several ports at
165+
# once (eg, multi-stage tests that create a fresh vhost per stage), so the
166+
# block cannot be punched full of holes by sibling tests grabbing individual
167+
# ports between separate lws_get_free_port() calls in parallel CI.
168+
#
169+
function(lws_get_free_ports VAR_NAME COUNT)
170+
if (WIN32)
171+
set(COUNTER_FILE "$ENV{TEMP}/lws_port_counter_$ENV{USERNAME}")
172+
else()
173+
set(COUNTER_FILE "/tmp/lws_port_counter_$ENV{USER}")
174+
endif()
175+
176+
file(LOCK "${COUNTER_FILE}.lock" GUARD PROCESS TIMEOUT 10)
177+
178+
if (EXISTS "${COUNTER_FILE}")
179+
file(READ "${COUNTER_FILE}" port)
180+
string(STRIP "${port}" port)
181+
else()
182+
set(port 15000)
183+
endif()
184+
185+
if (port GREATER 30000)
186+
set(port 15000)
187+
endif()
188+
189+
set(${VAR_NAME} ${port} PARENT_SCOPE)
190+
191+
math(EXPR next_port "${port} + ${COUNT}")
192+
if (next_port GREATER 30000)
193+
set(next_port 15000)
194+
endif()
195+
file(WRITE "${COUNTER_FILE}" "${next_port}")
196+
197+
file(LOCK "${COUNTER_FILE}.lock" RELEASE)
198+
endfunction()

lib/tls/openhitls/openhitls-server.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,22 @@ lws_tls_server_abort_connection(struct lws *wsi)
505505
/*
506506
* HITLS_Close() (called from __lws_tls_shutdown) has been observed to
507507
* corrupt heap metadata. Skip it; HITLS_Free() handles full cleanup.
508+
*
509+
* The BSL_UIO was allocated by us in lws_tls_server_new_nonblocking()
510+
* and only associated (refcounted) with the HITLS_Ctx by HITLS_SetUio();
511+
* HITLS_Free() drops that association but does not free the UIO itself,
512+
* so we must BSL_UIO_Free() it. Detach the fd first so neither
513+
* HITLS_Free() nor BSL_UIO_Free() touches the wsi-owned socket.
508514
*/
509515
uio = HITLS_GetUio(wsi->tls.ssl);
510516
if (uio) {
511517
BSL_UIO_SetFD(uio, -1);
512518
}
513519
HITLS_Free(wsi->tls.ssl);
514520
wsi->tls.ssl = NULL;
521+
if (uio) {
522+
BSL_UIO_Free(uio);
523+
}
515524

516525
return LWS_SSL_CAPABLE_DONE;
517526
}
@@ -1043,8 +1052,18 @@ lws_tls_vhost_backend_create_ctx(struct lws_vhost *vhost)
10431052
return 0; /* no action */
10441053
}
10451054

1055+
/*
1056+
* Called by the tls ctx ref system (lws_tls_ctx_ref_destroy_all) when the
1057+
* server config's refcount drops to zero, and also from
1058+
* lws_tls_cert_updated() when retiring an old context after a hot cert
1059+
* update. HITLS_Config is itself refcounted (HITLS_New up-refs it per
1060+
* connection, HITLS_Free down-refs), so this is safe to call from both the
1061+
* ref system and lws_ssl_SSL_CTX_destroy() like the OpenSSL backend does
1062+
* with SSL_CTX_free().
1063+
*/
10461064
void
10471065
lws_tls_vhost_backend_free_ctx(lws_tls_ctx *ctx)
10481066
{
1049-
/* no action */
1067+
if (ctx)
1068+
HITLS_CFG_FreeConfig((HITLS_Config *)ctx);
10501069
}

lib/tls/openhitls/openhitls-ssl.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ lws_ssl_info_callback(const lws_tls_conn *ssl, int where, int ret)
476476
int
477477
lws_ssl_close(struct lws *wsi)
478478
{
479-
lws_sockfd_type n;
479+
lws_sockfd_type n = LWS_SOCK_INVALID;
480480
BSL_UIO *uio;
481481

482482
if (!wsi->tls.ssl) {
@@ -496,14 +496,24 @@ lws_ssl_close(struct lws *wsi)
496496
* Get the fd before any cleanup that may invalidate it.
497497
*/
498498
uio = HITLS_GetUio(wsi->tls.ssl);
499-
BSL_UIO_Ctrl(uio, BSL_UIO_GET_FD, sizeof(lws_sockfd_type), &n);
500-
501-
499+
if (uio)
500+
BSL_UIO_Ctrl(uio, BSL_UIO_GET_FD, sizeof(lws_sockfd_type), &n);
502501

503502
if (lws_socket_is_valid(n))
504503
compatible_close(n);
504+
/*
505+
* Detach the fd from the UIO so neither HITLS_Free() nor BSL_UIO_Free()
506+
* can touch the (already closed) wsi-owned socket, then drop the TLS
507+
* context. The UIO was allocated by us (in client bio create / server
508+
* new_nonblocking) and only associated with the HITLS_Ctx; HITLS_Free()
509+
* does not free it, so we must BSL_UIO_Free() it ourselves.
510+
*/
511+
if (uio)
512+
BSL_UIO_SetFD(uio, -1);
505513
HITLS_Free(wsi->tls.ssl);
506514
wsi->tls.ssl = NULL;
515+
if (uio)
516+
BSL_UIO_Free(uio);
507517
lws_tls_restrict_return(wsi);
508518

509519
return 1; /* handled */

minimal-examples-lowlevel/http-server/minimal-http-server-openhitls-mtls-crl/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ if (requirements)
2828
#
2929
# CTest configuration
3030
#
31+
# This test opens three server sockets (one per stage, base_port + 0..2) in
32+
# a single process, so reserve a contiguous block of three rather than a
33+
# single port: otherwise a sibling test can grab an individual port from
34+
# inside our block in parallel CI.
35+
#
3136
if (NOT WIN32)
32-
lws_get_free_port(PORT_OH_MTLS_CRL)
37+
lws_get_free_ports(PORT_OH_MTLS_CRL 3)
3338

3439
add_test(NAME http-server-mtls-crl COMMAND
3540
${SAMP} --port ${PORT_OH_MTLS_CRL})

minimal-examples-lowlevel/http-server/minimal-http-server-openhitls-mtls-crl/minimal-http-server-openhitls-mtls-crl.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ static struct lws_context *context;
1818
static struct lws *client_wsi;
1919

2020
static int test_stage;
21-
static int test_port = 7780;
21+
/*
22+
* Base listen port; each stage uses base_port + stage (stages 0..2, so a
23+
* contiguous block of three). Default preserves standalone behaviour; ctest
24+
* overrides it with a CI-allocated free port via --port so parallel runs (and
25+
* sibling openHiTLS server tests) can't collide.
26+
*/
27+
static int base_port = 7780;
2228
static int app_data_sent;
2329
static int app_data_received;
2430
static int wsi_closed;
@@ -105,7 +111,7 @@ static struct lws_context* create_context_for_stage(int stage)
105111

106112
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
107113
info.protocols = protocols;
108-
info.port = test_port + stage;
114+
info.port = base_port + stage;
109115

110116
switch (stage) {
111117
case 0:
@@ -153,13 +159,24 @@ static void sigint_handler(int sig)
153159

154160
int main(int argc, const char **argv)
155161
{
162+
const char *p;
156163
int n = 0;
157164
int idx;
158165

159166
signal(SIGINT, sigint_handler);
160167

161168
lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN, NULL);
162-
lwsl_user("LWS TLS12 mTLS with CRL test\n");
169+
170+
/*
171+
* ctest passes --port allocated by lws_get_free_ports(3) so the whole
172+
* base_port + 0..2 block is reserved and parallel runs can't tread on each
173+
* other or sibling tests. Default keeps the original standalone range.
174+
*/
175+
p = lws_cmdline_option(argc, argv, "--port");
176+
if (p)
177+
base_port = atoi(p);
178+
179+
lwsl_user("LWS TLS12 mTLS with CRL test (base port %d)\n", base_port);
163180
lwsl_user("Stage 0: Using NORMAL server cert + client cert required\n");
164181

165182
context = create_context_for_stage(test_stage);
@@ -172,7 +189,7 @@ int main(int argc, const char **argv)
172189
struct lws_client_connect_info i;
173190
memset(&i, 0, sizeof(i));
174191
i.context = context;
175-
i.port = test_port;
192+
i.port = base_port;
176193
i.address = "localhost";
177194
i.ssl_connection = LCCSCF_USE_SSL |
178195
LCCSCF_ALLOW_SELFSIGNED |
@@ -225,7 +242,7 @@ int main(int argc, const char **argv)
225242

226243
memset(&i, 0, sizeof(i));
227244
i.context = context;
228-
i.port = test_port + test_stage;
245+
i.port = base_port + test_stage;
229246
i.address = "localhost";
230247
i.ssl_connection = LCCSCF_USE_SSL |
231248
LCCSCF_ALLOW_SELFSIGNED |
@@ -260,13 +277,12 @@ int main(int argc, const char **argv)
260277
lwsl_user("========================================\n");
261278

262279
cleanup:
263-
/*
264-
* openHiTLS currently traps in context teardown when a client and
265-
* embedded TLS server share the same context. The test verdict is
266-
* known when the loop exits, so allow process exit to reclaim it.
267-
*/
268-
(void)all_contexts;
269-
(void)idx;
280+
for (idx = 0; idx < num_contexts; idx++) {
281+
if (all_contexts[idx]) {
282+
lws_context_destroy(all_contexts[idx]);
283+
all_contexts[idx] = NULL;
284+
}
285+
}
270286

271287
return bad;
272288
}

minimal-examples-lowlevel/http-server/minimal-http-server-openhitls-sni-mismatch/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ if (requirements)
2828
#
2929
# CTest configuration
3030
#
31+
# This test opens four server sockets (one per stage, base_port + 0..3) in a
32+
# single process, so reserve a contiguous block of four rather than a single
33+
# port: otherwise a sibling test can grab an individual port from inside our
34+
# block in parallel CI.
35+
#
3136
if (NOT WIN32)
32-
lws_get_free_port(PORT_OH_SNI_MISMATCH)
37+
lws_get_free_ports(PORT_OH_SNI_MISMATCH 4)
3338

3439
add_test(NAME http-server-sni-mismatch COMMAND
3540
${SAMP} --port ${PORT_OH_SNI_MISMATCH})

minimal-examples-lowlevel/http-server/minimal-http-server-openhitls-sni-mismatch/minimal-http-server-openhitls-sni-mismatch.c

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ static const char *expected_cert_cn[] = {
3131
"localhost" /* Stage 3: no sni vhost, default cert */
3232
};
3333

34-
static int test_ports[] = {
35-
7781, /* Stage 0 */
36-
7782, /* Stage 1 */
37-
7783, /* Stage 2 */
38-
7784 /* Stage 3 */
39-
};
34+
/*
35+
* Base listen port; each stage uses base_port + stage. Default preserves
36+
* standalone behaviour; ctest overrides it with a CI-allocated free port via
37+
* --port so parallel runs (and sibling openHiTLS server tests) can't collide.
38+
*/
39+
static int base_port = 7781;
4040
static const struct lws_protocols protocols[];
4141

4242
struct pss_sni_server {
@@ -189,27 +189,32 @@ create_context_for_stage(int stage)
189189
case 0:
190190
/* Stage 0: vhost="nosni.com" with default cert */
191191
lwsl_user("Stage 0: Creating vhost 'nosni.com' with default cert\n");
192-
vh = create_vhost_with_sni(context, test_ports[0], "nosni.com",
192+
vh = create_vhost_with_sni(context, base_port + 0, "nosni.com",
193193
"certs/default.pem", "certs/default.key");
194194
break;
195195
case 1:
196196
/* Stage 1: vhost="sni.com" with sni.com cert */
197197
lwsl_user("Stage 1: Creating vhost 'sni.com' with sni.com cert\n");
198-
vh = create_vhost_with_sni(context, test_ports[1], "sni.com",
198+
vh = create_vhost_with_sni(context, base_port + 1, "sni.com",
199199
"certs/sni.pem", "certs/sni.key");
200200
break;
201201
case 2:
202202
/* Stage 2: vhost="sni.com" with default cert */
203203
lwsl_user("Stage 2: Creating vhost 'sni.com' with default cert\n");
204-
vh = create_vhost_with_sni(context, test_ports[2], "sni.com",
204+
vh = create_vhost_with_sni(context, base_port + 2, "sni.com",
205205
"certs/default.pem", "certs/default.key");
206206
break;
207207
case 3:
208208
/* Stage 3: no SNI vhost at all, only default vhost */
209209
lwsl_user("Stage 3: Creating default vhost 'localhost' (no SNI vhost)\n");
210-
vh = create_vhost_with_sni(context, test_ports[3], "localhost",
210+
vh = create_vhost_with_sni(context, base_port + 3, "localhost",
211211
"certs/default.pem", "certs/default.key");
212212
break;
213+
default:
214+
/* stage is bounded to 0..3 by the caller; reject anything else */
215+
lwsl_err("Stage %d: invalid stage\n", stage);
216+
lws_context_destroy(context);
217+
return NULL;
213218
}
214219

215220
if (!vh) {
@@ -228,7 +233,7 @@ connect_to_stage(int stage)
228233

229234
memset(&i, 0, sizeof(i));
230235
i.context = context;
231-
i.port = test_ports[stage];
236+
i.port = base_port + stage;
232237
i.address = "localhost";
233238
i.ssl_connection = LCCSCF_USE_SSL |
234239
LCCSCF_ALLOW_SELFSIGNED |
@@ -254,13 +259,24 @@ connect_to_stage(int stage)
254259

255260
int main(int argc, const char **argv)
256261
{
262+
const char *p;
257263
int n = 0;
258264
int stage;
259265

260266
signal(SIGINT, sigint_handler);
261267

262268
lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN, NULL);
263-
lwsl_user("LWS SNI Test - 4 Scenarios\n\n");
269+
270+
/*
271+
* ctest passes --port allocated by lws_get_free_ports(4) so the whole
272+
* base_port + 0..3 block is reserved and parallel runs can't tread on each
273+
* other or sibling tests. Default keeps the original standalone range.
274+
*/
275+
p = lws_cmdline_option(argc, argv, "--port");
276+
if (p)
277+
base_port = atoi(p);
278+
279+
lwsl_user("LWS SNI Test - 4 Scenarios (base port %d)\n\n", base_port);
264280

265281
/* Test all 4 stages */
266282
for (stage = 0; stage < 4 && !bad && !interrupted; stage++) {
@@ -295,12 +311,7 @@ int main(int argc, const char **argv)
295311

296312
lwsl_user("Stage %d: Completed\n\n", stage);
297313

298-
/*
299-
* openHiTLS currently traps in context teardown when a client
300-
* and embedded TLS server share the same context. The test
301-
* verdict is known when the loop exits, so allow process exit
302-
* to reclaim it.
303-
*/
314+
lws_context_destroy(context);
304315
}
305316

306317
lwsl_user("========================================\n");

minimal-examples-lowlevel/http-server/minimal-http-server-openhitls-tls13/minimal-http-server-openhitls-tls13.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,7 @@ int main(int argc, const char **argv)
280280
lwsl_user("Bytes received: %zu\n", received_len);
281281
lwsl_user("========================================\n");
282282

283-
/*
284-
* openHiTLS currently traps in context teardown when a client and
285-
* embedded TLS server share the same context. The test verdict is
286-
* known when the loop exits, so allow process exit to reclaim it.
287-
*/
283+
lws_context_destroy(context);
288284

289285
return bad;
290286
}

0 commit comments

Comments
 (0)