/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/quic.h>
#include <openssl/rand.h>
#include "helpers/ssltestlib.h"
#include "helpers/quictestlib.h"
#include "testutil.h"
#include "testutil/output.h"
#include "../ssl/ssl_local.h"
static OSSL_LIB_CTX *libctx = NULL;
static OSSL_PROVIDER *defctxnull = NULL;
static char *certsdir = NULL;
static char *cert = NULL;
static char *privkey = NULL;
static char *datadir = NULL;
static int is_fips = 0;
/* The ssltrace test assumes some options are switched on/off */
#if !defined(OPENSSL_NO_SSL_TRACE) && !defined(OPENSSL_NO_EC) \
&& defined(OPENSSL_NO_ZLIB) && defined(OPENSSL_NO_BROTLI) \
&& defined(OPENSSL_NO_ZSTD) && !defined(OPENSSL_NO_ECX) \
&& !defined(OPENSSL_NO_DH)
# define DO_SSL_TRACE_TEST
#endif
/*
* Test that we read what we've written.
* Test 0: Non-blocking
* Test 1: Blocking
* Test 2: Blocking, introduce socket error, test error handling.
*/
static int test_quic_write_read(int idx)
{
SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method());
SSL_CTX *sctx = NULL;
SSL *clientquic = NULL;
QUIC_TSERVER *qtserv = NULL;
int j, k, ret = 0;
unsigned char buf[20];
static char *msg = "A test message";
size_t msglen = strlen(msg);
size_t numbytes = 0;
int ssock = 0, csock = 0;
uint64_t sid = UINT64_MAX;
SSL_SESSION *sess = NULL;
if (idx >= 1 && !qtest_supports_blocking())
return TEST_skip("Blocking tests not supported in this build");
for (k = 0; k < 2; k++) {
if (!TEST_ptr(cctx)
|| !TEST_true(qtest_create_quic_objects(libctx, cctx, sctx,
cert, privkey,
idx >= 1
? QTEST_FLAG_BLOCK
: 0,
&qtserv, &clientquic,
NULL))
|| !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost")))
goto end;
if (sess != NULL && !TEST_true(SSL_set_session(clientquic, sess)))
goto end;
if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
goto end;
if (idx >= 1) {
if (!TEST_true(BIO_get_fd(ossl_quic_tserver_get0_rbio(qtserv),
&ssock)))
goto end;
if (!TEST_int_gt(csock = SSL_get_rfd(clientquic), 0))
goto end;
}
sid = 0; /* client-initiated bidirectional stream */
for (j = 0; j < 2; j++) {
/* Check that sending and receiving app data is ok */
if (!TEST_true(SSL_write_ex(clientquic, msg, msglen, &numbytes))
|| !TEST_size_t_eq(numbytes, msglen))
goto end;
if (idx >= 1) {
do {
if (!TEST_true(wait_until_sock_readable(ssock)))
goto end;
ossl_quic_tserver_tick(qtserv);
if (!TEST_true(ossl_quic_tserver_read(qtserv, sid, buf,
sizeof(buf),
&numbytes)))
goto end;
} while (numbytes == 0);
if (!TEST_mem_eq(buf, numbytes, msg, msglen))
goto end;
}
if (idx >= 2 && j > 0)
/* Introduce permanent socket error */
BIO_closesocket(csock);
ossl_quic_tserver_tick(qtserv);
if (!TEST_true(ossl_quic_tserver_write(qtserv, sid,
(unsigned char *)msg,
msglen, &numbytes)))
goto end;
ossl_quic_tserver_tick(qtserv);
SSL_handle_events(clientquic);
if (idx >= 2 && j > 0) {
if (!TEST_false(SSL_read_ex(clientquic, buf, 1, &numbytes))
|| !