mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
QUIC Front End I/O API: Add support for signalling and detecting end-of-stream
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19897)
This commit is contained in:
parent
cf06f34727
commit
a9979965bf
@ -247,6 +247,12 @@ int ossl_quic_sstream_append(QUIC_SSTREAM *qss,
|
||||
*/
|
||||
void ossl_quic_sstream_fin(QUIC_SSTREAM *qss);
|
||||
|
||||
/*
|
||||
* If the stream has had ossl_quic_sstream_fin() called, returns 1 and writes
|
||||
* the final size to *final_size. Otherwise, returns 0.
|
||||
*/
|
||||
int ossl_quic_sstream_get_final_size(QUIC_SSTREAM *qss, uint64_t *final_size);
|
||||
|
||||
/*
|
||||
* Resizes the internal ring buffer. All stream data is preserved safely.
|
||||
*
|
||||
|
@ -52,13 +52,20 @@ int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv);
|
||||
* *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.
|
||||
* Returns 0 if connection is not currently active. If the receive part of
|
||||
* the stream has reached the end of stream condition, returns 0; call
|
||||
* ossl_quic_tserver_has_read_ended() to identify this condition.
|
||||
*/
|
||||
int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
unsigned char *buf,
|
||||
size_t buf_len,
|
||||
size_t *bytes_read);
|
||||
|
||||
/*
|
||||
* Returns 1 if the read part of the stream has ended normally.
|
||||
*/
|
||||
int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv);
|
||||
|
||||
/*
|
||||
* Attempts to write to stream 0. Writes the number of bytes consumed to
|
||||
* *bytes_written and returns 1 on success. If there is no space currently
|
||||
@ -75,6 +82,11 @@ int ossl_quic_tserver_write(QUIC_TSERVER *srv,
|
||||
size_t buf_len,
|
||||
size_t *bytes_written);
|
||||
|
||||
/*
|
||||
* Signals normal end of the stream.
|
||||
*/
|
||||
int ossl_quic_tserver_conclude(QUIC_TSERVER *srv);
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
@ -2270,6 +2270,8 @@ __owur int SSL_shutdown_ex(SSL *ssl, uint64_t flags,
|
||||
const SSL_SHUTDOWN_EX_ARGS *args,
|
||||
size_t args_len);
|
||||
|
||||
__owur int SSL_stream_conclude(SSL *ssl, uint64_t flags);
|
||||
|
||||
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
||||
# define SSL_cache_hit(s) SSL_session_reused(s)
|
||||
# endif
|
||||
|
@ -756,6 +756,8 @@ int ossl_quic_accept(SSL *s)
|
||||
* (BIO/)SSL_read => ossl_quic_read
|
||||
* (BIO/)SSL_write => ossl_quic_write
|
||||
* SSL_pending => ossl_quic_pending
|
||||
* SSL_stream_conclude => ossl_quic_conn_stream_conclude
|
||||
*
|
||||
*/
|
||||
|
||||
/* SSL_get_error */
|
||||
@ -1053,6 +1055,10 @@ static int quic_read_actual(QUIC_CONNECTION *qc,
|
||||
{
|
||||
int is_fin = 0;
|
||||
|
||||
/* If the receive part of the stream is over, issue EOF. */
|
||||
if (stream->recv_fin_retired)
|
||||
return QUIC_RAISE_NORMAL_ERROR(qc, SSL_ERROR_ZERO_RETURN);
|
||||
|
||||
if (stream->rstream == NULL)
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||
|
||||
@ -1099,9 +1105,11 @@ static int quic_read_again(void *arg)
|
||||
{
|
||||
struct quic_read_again_args *args = arg;
|
||||
|
||||
if (!ossl_quic_channel_is_active(args->qc->ch))
|
||||
if (!ossl_quic_channel_is_active(args->qc->ch)) {
|
||||
/* If connection is torn down due to an error while blocking, stop. */
|
||||
QUIC_RAISE_NON_NORMAL_ERROR(args->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!quic_read_actual(args->qc, args->stream,
|
||||
args->buf, args->len, args->bytes_read,
|
||||
@ -1129,15 +1137,15 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch))
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
|
||||
/* If we haven't finished the handshake, try to advance it.*/
|
||||
/* If we haven't finished the handshake, try to advance it. */
|
||||
if (ossl_quic_do_handshake(qc) < 1)
|
||||
return 0;
|
||||
return 0; /* ossl_quic_do_handshake raised error here */
|
||||
|
||||
if (qc->stream0 == NULL)
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||
|
||||
if (!quic_read_actual(qc, qc->stream0, buf, len, bytes_read, peek))
|
||||
return 0;
|
||||
return 0; /* quic_read_actual raised error here */
|
||||
|
||||
if (*bytes_read > 0) {
|
||||
/*
|
||||
@ -1160,12 +1168,10 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
|
||||
args.peek = peek;
|
||||
|
||||
res = block_until_pred(qc, quic_read_again, &args, 0);
|
||||
if (res <= 0) {
|
||||
if (!ossl_quic_channel_is_active(qc->ch))
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
else
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||
}
|
||||
if (res == 0)
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||
else if (res < 0)
|
||||
return 0; /* quic_read_again raised error here */
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
@ -1207,6 +1213,26 @@ size_t ossl_quic_pending(const SSL *s)
|
||||
return avail;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSL_stream_conclude
|
||||
* -------------------
|
||||
*/
|
||||
int ossl_quic_conn_stream_conclude(QUIC_CONNECTION *qc)
|
||||
{
|
||||
QUIC_STREAM *qs = qc->stream0;
|
||||
|
||||
if (qs == NULL || qs->sstream == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ossl_quic_channel_is_active(qc->ch)
|
||||
|| ossl_quic_sstream_get_final_size(qs->sstream, NULL))
|
||||
return 1;
|
||||
|
||||
ossl_quic_sstream_fin(qs->sstream);
|
||||
quic_post_write(qc, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUIC Front-End I/O API: SSL_CTX Management
|
||||
* ==========================================
|
||||
|
@ -442,6 +442,17 @@ void ossl_quic_sstream_fin(QUIC_SSTREAM *qss)
|
||||
qss->have_final_size = 1;
|
||||
}
|
||||
|
||||
int ossl_quic_sstream_get_final_size(QUIC_SSTREAM *qss, uint64_t *final_size)
|
||||
{
|
||||
if (!qss->have_final_size)
|
||||
return 0;
|
||||
|
||||
if (final_size != NULL)
|
||||
*final_size = qss->ring_buf.head_offset;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_quic_sstream_append(QUIC_SSTREAM *qss,
|
||||
const unsigned char *buf,
|
||||
size_t buf_len,
|
||||
|
@ -142,11 +142,14 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
size_t buf_len,
|
||||
size_t *bytes_read)
|
||||
{
|
||||
int is_fin = 0; /* TODO(QUIC): Handle FIN in API */
|
||||
int is_fin = 0;
|
||||
|
||||
if (!ossl_quic_channel_is_active(srv->ch))
|
||||
return 0;
|
||||
|
||||
if (srv->stream0->recv_fin_retired)
|
||||
return 0;
|
||||
|
||||
if (!ossl_quic_rstream_read(srv->stream0->rstream, buf, buf_len,
|
||||
bytes_read, &is_fin))
|
||||
return 0;
|
||||
@ -177,6 +180,11 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv)
|
||||
{
|
||||
return srv->stream0->recv_fin_retired;
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_write(QUIC_TSERVER *srv,
|
||||
const unsigned char *buf,
|
||||
size_t buf_len,
|
||||
@ -201,3 +209,18 @@ int ossl_quic_tserver_write(QUIC_TSERVER *srv,
|
||||
ossl_quic_tserver_tick(srv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_conclude(QUIC_TSERVER *srv)
|
||||
{
|
||||
if (!ossl_quic_channel_is_active(srv->ch))
|
||||
return 0;
|
||||
|
||||
if (!ossl_quic_sstream_get_final_size(srv->stream0->sstream, NULL)) {
|
||||
ossl_quic_sstream_fin(srv->stream0->sstream);
|
||||
ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
|
||||
srv->stream0);
|
||||
}
|
||||
|
||||
ossl_quic_tserver_tick(srv);
|
||||
return 1;
|
||||
}
|
||||
|
@ -7197,3 +7197,17 @@ int SSL_shutdown_ex(SSL *ssl, uint64_t flags,
|
||||
return SSL_shutdown(ssl);
|
||||
#endif
|
||||
}
|
||||
|
||||
int SSL_stream_conclude(SSL *ssl, uint64_t flags)
|
||||
{
|
||||
#ifndef OPENSSL_NO_QUIC
|
||||
QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(ssl);
|
||||
|
||||
if (qc == NULL)
|
||||
return 0;
|
||||
|
||||
return ossl_quic_conn_stream_conclude(qc);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -542,3 +542,4 @@ SSL_set_initial_peer_addr ? 3_2_0 EXIST::FUNCTION:
|
||||
SSL_net_read_desired ? 3_2_0 EXIST::FUNCTION:
|
||||
SSL_net_write_desired ? 3_2_0 EXIST::FUNCTION:
|
||||
SSL_shutdown_ex ? 3_2_0 EXIST::FUNCTION:
|
||||
SSL_stream_conclude ? 3_2_0 EXIST::FUNCTION:
|
||||
|
Loading…
Reference in New Issue
Block a user