mirror of
https://github.com/openssl/openssl.git
synced 2025-02-17 14:32:04 +08:00
QUIC Test Server Implementation
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19734)
This commit is contained in:
parent
b1b06da2a3
commit
51a168b804
79
include/internal/quic_tserver.h
Normal file
79
include/internal/quic_tserver.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef OSSL_QUIC_TSERVER_H
|
||||
# define OSSL_QUIC_TSERVER_H
|
||||
|
||||
# include <openssl/ssl.h>
|
||||
# include "internal/quic_stream.h"
|
||||
|
||||
# ifndef OPENSSL_NO_QUIC
|
||||
|
||||
/*
|
||||
* QUIC Test Server Module
|
||||
* =======================
|
||||
*
|
||||
* This implements a QUIC test server. Since full QUIC server support is not yet
|
||||
* implemented this server is limited in features and scope. It exists to
|
||||
* provide a target for our QUIC client to talk to for testing purposes.
|
||||
*
|
||||
* A given QUIC test server instance supports only one client at a time.
|
||||
*
|
||||
* Note that this test server is not suitable for production use because it does
|
||||
* not implement address verification, anti-amplification or retry logic.
|
||||
*/
|
||||
typedef struct quic_tserver_st QUIC_TSERVER;
|
||||
|
||||
typedef struct quic_tserver_args_st {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
const char *propq;
|
||||
BIO *net_rbio, *net_wbio;
|
||||
} QUIC_TSERVER_ARGS;
|
||||
|
||||
QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args);
|
||||
|
||||
void ossl_quic_tserver_free(QUIC_TSERVER *srv);
|
||||
|
||||
/* Advances the state machine. */
|
||||
int ossl_quic_tserver_tick(QUIC_TSERVER *srv);
|
||||
|
||||
/* Returns 1 if we have a (non-terminated) client. */
|
||||
int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv);
|
||||
|
||||
/*
|
||||
* Attempts to read from stream 0. Writes the number of bytes read to
|
||||
* *bytes_read and returns 1 on success. If no bytes are available, 0 is written
|
||||
* to *bytes_read and 1 is returned (this is considered a success case).
|
||||
*
|
||||
* Returns 0 if connection is not currently active.
|
||||
*/
|
||||
int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
unsigned char *buf,
|
||||
size_t buf_len,
|
||||
size_t *bytes_read);
|
||||
|
||||
/*
|
||||
* Attempts to write to stream 0. Writes the number of bytes consumed to
|
||||
* *consumed and returns 1 on success. If there is no space currently available
|
||||
* to write any bytes, 0 is written to *consumed and 1 is returned (this is
|
||||
* considered a success case).
|
||||
*
|
||||
* Note that unlike libssl public APIs, this API always works in a 'partial
|
||||
* write' mode.
|
||||
*
|
||||
* Returns 0 if connection is not currently active.
|
||||
*/
|
||||
int ossl_quic_tserver_write(QUIC_TSERVER *srv,
|
||||
const unsigned char *buf,
|
||||
size_t buf_len,
|
||||
size_t *bytes_written);
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
@ -11,3 +11,4 @@ SOURCE[$LIBSSL]=quic_sf_list.c quic_rstream.c quic_sstream.c
|
||||
SOURCE[$LIBSSL]=quic_dummy_handshake.c
|
||||
SOURCE[$LIBSSL]=quic_reactor.c
|
||||
SOURCE[$LIBSSL]=quic_channel.c
|
||||
SOURCE[$LIBSSL]=quic_tserver.c
|
||||
|
163
ssl/quic/quic_tserver.c
Normal file
163
ssl/quic/quic_tserver.c
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 "internal/quic_tserver.h"
|
||||
#include "internal/quic_channel.h"
|
||||
#include "internal/quic_statm.h"
|
||||
#include "internal/common.h"
|
||||
|
||||
/*
|
||||
* QUIC Test Server Module
|
||||
* =======================
|
||||
*/
|
||||
struct quic_tserver_st {
|
||||
QUIC_TSERVER_ARGS args;
|
||||
|
||||
/*
|
||||
* The QUIC channel providing the core QUIC connection implementation.
|
||||
*/
|
||||
QUIC_CHANNEL *ch;
|
||||
|
||||
/* Our single bidirectional application data stream. */
|
||||
QUIC_STREAM *stream0;
|
||||
|
||||
/* The current peer L4 address. AF_UNSPEC if we do not have a peer yet. */
|
||||
BIO_ADDR cur_peer_addr;
|
||||
|
||||
/* Are we connected to a peer? */
|
||||
unsigned int connected : 1;
|
||||
};
|
||||
|
||||
QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args)
|
||||
{
|
||||
QUIC_TSERVER *srv = NULL;
|
||||
QUIC_CHANNEL_ARGS ch_args = {0};
|
||||
|
||||
if (args->net_rbio == NULL || args->net_wbio == NULL)
|
||||
goto err;
|
||||
|
||||
if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)
|
||||
goto err;
|
||||
|
||||
srv->args = *args;
|
||||
|
||||
ch_args.libctx = srv->args.libctx;
|
||||
ch_args.propq = srv->args.propq;
|
||||
ch_args.is_server = 1;
|
||||
|
||||
if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!ossl_quic_channel_set_net_rbio(srv->ch, srv->args.net_rbio)
|
||||
|| !ossl_quic_channel_set_net_wbio(srv->ch, srv->args.net_wbio))
|
||||
goto err;
|
||||
|
||||
srv->stream0 = ossl_quic_channel_get_stream_by_id(srv->ch, 0);
|
||||
if (srv->stream0 == NULL)
|
||||
goto err;
|
||||
|
||||
return srv;
|
||||
|
||||
err:
|
||||
if (srv != NULL)
|
||||
ossl_quic_channel_free(srv->ch);
|
||||
|
||||
OPENSSL_free(srv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ossl_quic_tserver_free(QUIC_TSERVER *srv)
|
||||
{
|
||||
if (srv == NULL)
|
||||
return;
|
||||
|
||||
ossl_quic_channel_free(srv->ch);
|
||||
BIO_free(srv->args.net_rbio);
|
||||
BIO_free(srv->args.net_wbio);
|
||||
OPENSSL_free(srv);
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
|
||||
{
|
||||
ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));
|
||||
|
||||
if (ossl_quic_channel_is_active(srv->ch))
|
||||
srv->connected = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
|
||||
{
|
||||
return ossl_quic_channel_is_active(srv->ch);
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
unsigned char *buf,
|
||||
size_t buf_len,
|
||||
size_t *bytes_read)
|
||||
{
|
||||
int is_fin = 0; /* TODO(QUIC): Handle FIN in API */
|
||||
|
||||
if (!ossl_quic_channel_is_active(srv->ch))
|
||||
return 0;
|
||||
|
||||
if (!ossl_quic_rstream_read(srv->stream0->rstream, buf, buf_len,
|
||||
bytes_read, &is_fin))
|
||||
return 0;
|
||||
|
||||
if (*bytes_read > 0) {
|
||||
/*
|
||||
* We have read at least one byte from the stream. Inform stream-level
|
||||
* RXFC of the retirement of controlled bytes. Update the active stream
|
||||
* status (the RXFC may now want to emit a frame granting more credit to
|
||||
* the peer).
|
||||
*/
|
||||
OSSL_RTT_INFO rtt_info;
|
||||
ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);
|
||||
|
||||
if (!ossl_quic_rxfc_on_retire(&srv->stream0->rxfc, *bytes_read,
|
||||
rtt_info.smoothed_rtt))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_fin)
|
||||
srv->stream0->recv_fin_retired = 1;
|
||||
|
||||
if (*bytes_read > 0)
|
||||
ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
|
||||
srv->stream0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_write(QUIC_TSERVER *srv,
|
||||
const unsigned char *buf,
|
||||
size_t buf_len,
|
||||
size_t *bytes_written)
|
||||
{
|
||||
if (!ossl_quic_channel_is_active(srv->ch))
|
||||
return 0;
|
||||
|
||||
if (!ossl_quic_sstream_append(srv->stream0->sstream,
|
||||
buf, buf_len, bytes_written))
|
||||
return 0;
|
||||
|
||||
if (*bytes_written > 0)
|
||||
/*
|
||||
* We have appended at least one byte to the stream. Potentially mark
|
||||
* the stream as active, depending on FC.
|
||||
*/
|
||||
ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
|
||||
srv->stream0);
|
||||
|
||||
/* Try and send. */
|
||||
ossl_quic_tserver_tick(srv);
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user