uint64_t this_dgram;
BIO_MSG msg;
uint64_t reinject_dgram;
+ int backoff;
};
static long noisy_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
case BIO_CTRL_DUP:
ret = 0L;
break;
+ case BIO_CTRL_NOISE_BACK_OFF: {
+ struct noisy_dgram_st *data;
+
+ data = BIO_get_data(bio);
+ if (!TEST_ptr(data))
+ return 0;
+ data->backoff = 1;
+ ret = 1;
+ break;
+ }
default:
ret = BIO_ctrl(next, cmd, num, ptr);
break;
}
get_noise(&reinject, &should_drop);
+ if (data->backoff) {
+ /*
+ * We might be asked to back off on introducing too much noise if
+ * there is a danger that the connection will fail. In that case
+ * we always ensure that the next datagram does not get dropped so
+ * that the connection always survives. After that we can resume
+ * with normal noise
+ */
+ should_drop = 0;
+ data->backoff = 0;
+ }
/*
* We ignore reinjection if a message is already waiting to be
#define GROWTH_ALLOWANCE 1024
+struct noise_args_data_st {
+ BIO *cbio;
+ BIO *sbio;
+ BIO *tracebio;
+ int flags;
+};
+
struct qtest_fault {
QUIC_TSERVER *qtserv;
BIO_MSG msg;
/* Allocated size of msg data buffer */
size_t msgalloc;
+ struct noise_args_data_st noiseargs;
};
static void packet_plain_finish(void *arg);
return fake_now;
}
+static void noise_msg_callback(int write_p, int version, int content_type,
+ const void *buf, size_t len, SSL *ssl,
+ void *arg)
+{
+ struct noise_args_data_st *noiseargs = (struct noise_args_data_st *)arg;
+
+ if (content_type == SSL3_RT_QUIC_FRAME_FULL) {
+ PACKET pkt;
+ uint64_t frame_type;
+
+ if (!PACKET_buf_init(&pkt, buf, len))
+ return;
+
+ if (!ossl_quic_wire_peek_frame_header(&pkt, &frame_type, NULL))
+ return;
+
+ if (frame_type == OSSL_QUIC_FRAME_TYPE_PING) {
+ /*
+ * If either endpoint issues a ping frame then we are in danger
+ * of our noise being too much such that the connection itself
+ * fails. We back off on the noise for a bit to avoid that.
+ */
+ BIO_ctrl(noiseargs->cbio, BIO_CTRL_NOISE_BACK_OFF, 0, NULL);
+ BIO_ctrl(noiseargs->sbio, BIO_CTRL_NOISE_BACK_OFF, 0, NULL);
+ }
+ }
+
+#ifndef OPENSSL_NO_SSL_TRACE
+ if ((noiseargs->flags & QTEST_FLAG_CLIENT_TRACE) != 0
+ && !SSL_is_server(ssl))
+ SSL_trace(write_p, version, content_type, buf, len, ssl,
+ noiseargs->tracebio);
+#endif
+}
+
int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
SSL_CTX *serverctx, char *certfile, char *keyfile,
int flags, QUIC_TSERVER **qtserv, SSL **cssl,
BIO *tmpbio = NULL;
*qtserv = NULL;
- if (fault != NULL)
- *fault = NULL;
-
if (*cssl == NULL) {
*cssl = SSL_new(clientctx);
if (!TEST_ptr(*cssl))
return 0;
}
+ if (fault != NULL) {
+ *fault = OPENSSL_zalloc(sizeof(**fault));
+ if (*fault == NULL)
+ goto err;
+ }
+
#ifndef OPENSSL_NO_SSL_TRACE
if ((flags & QTEST_FLAG_CLIENT_TRACE) != 0) {
tmpbio = BIO_new_fp(stdout, BIO_NOCLOSE);
}
if ((flags & QTEST_FLAG_NOISE) != 0) {
- BIO *noisebio = BIO_new(bio_f_noisy_dgram_filter());
+ BIO *noisebio;
+
+ /*
+ * It is an error to not have a QTEST_FAULT object when introducing noise
+ */
+ if (!TEST_ptr(fault))
+ goto err;
+
+ noisebio = BIO_new(bio_f_noisy_dgram_filter());
if (!TEST_ptr(noisebio))
goto err;
if (!TEST_ptr(noisebio))
goto err;
sbio = BIO_push(noisebio, sbio);
+
+ (*fault)->noiseargs.cbio = cbio;
+ (*fault)->noiseargs.sbio = sbio;
+ (*fault)->noiseargs.tracebio = tmpbio;
+ (*fault)->noiseargs.flags = flags;
+
+ SSL_set_msg_callback(*cssl, noise_msg_callback);
+ SSL_set_msg_callback_arg(*cssl, &(*fault)->noiseargs);
}
SSL_set_bio(*cssl, cbio, cbio);
if (!TEST_true(SSL_set1_initial_peer_addr(*cssl, peeraddr)))
goto err;
- if (fault != NULL) {
- *fault = OPENSSL_zalloc(sizeof(**fault));
- if (*fault == NULL)
- goto err;
- }
-
fisbio = BIO_new(qtest_get_bio_method());
if (!TEST_ptr(fisbio))
goto err;
sbio = NULL;
fisbio = NULL;
+ if ((flags & QTEST_FLAG_NOISE) != 0)
+ ossl_quic_tserver_set_msg_callback(*qtserv, noise_msg_callback,
+ &(*fault)->noiseargs);
+
if (fault != NULL)
(*fault)->qtserv = *qtserv;
size_t msglen = strlen(msg), written, readbytes, i, j;
unsigned char buf[80];
int flags = QTEST_FLAG_NOISE | QTEST_FLAG_FAKE_TIME;
+ QTEST_FAULT *fault = NULL;
if (idx == 1)
flags |= QTEST_FLAG_PACKET_SPLIT;
|| !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert,
privkey, flags,
&qtserv,
- &clientquic, NULL, NULL)))
+ &clientquic, &fault, NULL)))
goto err;
if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
SSL_free(stream[1]);
SSL_free(clientquic);
SSL_CTX_free(cctx);
+ qtest_fault_free(fault);
return testresult;
}