mirror of
https://github.com/openssl/openssl.git
synced 2025-04-24 20:51:14 +08:00
QUIC DISPATCH/APL: Implement SSL_set_default_stream_mode, default XSO refactor
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20765)
This commit is contained in:
parent
19cb088772
commit
8b7be3aa7e
@ -1465,6 +1465,7 @@ SSL_R_NO_SHARED_CIPHER:193:no shared cipher
|
|||||||
SSL_R_NO_SHARED_GROUPS:410:no shared groups
|
SSL_R_NO_SHARED_GROUPS:410:no shared groups
|
||||||
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms
|
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms
|
||||||
SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
|
SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
|
||||||
|
SSL_R_NO_STREAM:355:no stream
|
||||||
SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm
|
SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm
|
||||||
SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
|
SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
|
||||||
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share
|
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share
|
||||||
|
@ -84,6 +84,19 @@
|
|||||||
*/
|
*/
|
||||||
# define QUIC_TAKES_LOCK
|
# define QUIC_TAKES_LOCK
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function acquires the channel mutex and leaves it acquired
|
||||||
|
* when returning success.
|
||||||
|
*
|
||||||
|
* Any function tagged with this has the following precondition and
|
||||||
|
* postcondition:
|
||||||
|
*
|
||||||
|
* Precondition: must not hold channel mutex (unchecked)
|
||||||
|
* Postcondition: channel mutex is held by calling thread
|
||||||
|
* or function returned failure
|
||||||
|
*/
|
||||||
|
# define QUIC_ACQUIRES_LOCK
|
||||||
|
|
||||||
# define QUIC_TODO_LOCK
|
# define QUIC_TODO_LOCK
|
||||||
|
|
||||||
# define QUIC_CHANNEL_STATE_IDLE 0
|
# define QUIC_CHANNEL_STATE_IDLE 0
|
||||||
|
@ -69,6 +69,9 @@ __owur SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags);
|
|||||||
__owur SSL *ossl_quic_get0_connection(SSL *s);
|
__owur SSL *ossl_quic_get0_connection(SSL *s);
|
||||||
__owur int ossl_quic_get_stream_type(SSL *s);
|
__owur int ossl_quic_get_stream_type(SSL *s);
|
||||||
__owur uint64_t ossl_quic_get_stream_id(SSL *s);
|
__owur uint64_t ossl_quic_get_stream_id(SSL *s);
|
||||||
|
__owur int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode);
|
||||||
|
__owur SSL *ossl_quic_detach_stream(SSL *s);
|
||||||
|
__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to override ossl_time_now() for debug purposes. Must be called before
|
* Used to override ossl_time_now() for debug purposes. Must be called before
|
||||||
|
@ -2277,6 +2277,14 @@ __owur int SSL_get_stream_type(SSL *s);
|
|||||||
|
|
||||||
__owur uint64_t SSL_get_stream_id(SSL *s);
|
__owur uint64_t SSL_get_stream_id(SSL *s);
|
||||||
|
|
||||||
|
#define SSL_DEFAULT_STREAM_MODE_NONE 0
|
||||||
|
#define SSL_DEFAULT_STREAM_MODE_AUTO_BIDI 1
|
||||||
|
#define SSL_DEFAULT_STREAM_MODE_AUTO_UNI 2
|
||||||
|
__owur int SSL_set_default_stream_mode(SSL *s, uint32_t mode);
|
||||||
|
|
||||||
|
__owur SSL *SSL_detach_stream(SSL *s);
|
||||||
|
__owur int SSL_attach_stream(SSL *conn, SSL *stream);
|
||||||
|
|
||||||
#define SSL_STREAM_FLAG_UNI (1U << 0)
|
#define SSL_STREAM_FLAG_UNI (1U << 0)
|
||||||
__owur SSL *SSL_new_stream(SSL *s, uint64_t flags);
|
__owur SSL *SSL_new_stream(SSL *s, uint64_t flags);
|
||||||
|
|
||||||
|
@ -202,6 +202,7 @@
|
|||||||
# define SSL_R_NO_SHARED_GROUPS 410
|
# define SSL_R_NO_SHARED_GROUPS 410
|
||||||
# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376
|
# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376
|
||||||
# define SSL_R_NO_SRTP_PROFILES 359
|
# define SSL_R_NO_SRTP_PROFILES 359
|
||||||
|
# define SSL_R_NO_STREAM 355
|
||||||
# define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297
|
# define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297
|
||||||
# define SSL_R_NO_SUITABLE_GROUPS 295
|
# define SSL_R_NO_SUITABLE_GROUPS 295
|
||||||
# define SSL_R_NO_SUITABLE_KEY_SHARE 101
|
# define SSL_R_NO_SUITABLE_KEY_SHARE 101
|
||||||
@ -353,5 +354,6 @@
|
|||||||
# define SSL_R_WRONG_VERSION_NUMBER 267
|
# define SSL_R_WRONG_VERSION_NUMBER 267
|
||||||
# define SSL_R_X509_LIB 268
|
# define SSL_R_X509_LIB 268
|
||||||
# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
|
# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
|
||||||
|
# define SSL_R_CONN_USE_ONLY 411
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,7 +20,11 @@
|
|||||||
static void aon_write_finish(QUIC_XSO *xso);
|
static void aon_write_finish(QUIC_XSO *xso);
|
||||||
static int create_channel(QUIC_CONNECTION *qc);
|
static int create_channel(QUIC_CONNECTION *qc);
|
||||||
static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs);
|
static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs);
|
||||||
static int qc_try_create_default_xso(QUIC_CONNECTION *qc, int remote_init);
|
static int qc_try_create_default_xso_for_write(QUIC_CONNECTION *qc);
|
||||||
|
static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc);
|
||||||
|
static void quic_lock(QUIC_CONNECTION *qc);
|
||||||
|
static void quic_unlock(QUIC_CONNECTION *qc);
|
||||||
|
static int quic_do_handshake(QUIC_CONNECTION *qc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* QUIC Front-End I/O API: Common Utilities
|
* QUIC Front-End I/O API: Common Utilities
|
||||||
@ -136,7 +140,7 @@ static int expect_quic(const SSL *s, QCTX *ctx)
|
|||||||
ctx->is_stream = 0;
|
ctx->is_stream = 0;
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL);
|
return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL);
|
||||||
|
|
||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
case SSL_TYPE_QUIC_CONNECTION:
|
case SSL_TYPE_QUIC_CONNECTION:
|
||||||
@ -165,22 +169,50 @@ static int expect_quic(const SSL *s, QCTX *ctx)
|
|||||||
*
|
*
|
||||||
* remote_init determines if we expect the default XSO to be remotely created or
|
* remote_init determines if we expect the default XSO to be remotely created or
|
||||||
* not. If it is -1, do not instantiate a default XSO if one does not yet exist.
|
* not. If it is -1, do not instantiate a default XSO if one does not yet exist.
|
||||||
|
*
|
||||||
|
* Channel mutex is acquired and retained on success.
|
||||||
*/
|
*/
|
||||||
static int ossl_unused expect_quic_with_stream(const SSL *s, int remote_init,
|
QUIC_ACQUIRES_LOCK
|
||||||
QCTX *ctx)
|
static int ossl_unused expect_quic_with_stream_lock(const SSL *s, int remote_init,
|
||||||
|
QCTX *ctx)
|
||||||
{
|
{
|
||||||
if (!expect_quic(s, ctx))
|
if (!expect_quic(s, ctx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
quic_lock(ctx->qc);
|
||||||
|
|
||||||
if (ctx->xso == NULL && remote_init >= 0) {
|
if (ctx->xso == NULL && remote_init >= 0) {
|
||||||
qc_try_create_default_xso(ctx->qc, remote_init);
|
if (ossl_quic_channel_is_term_any(ctx->qc->ch)) {
|
||||||
|
QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we haven't finished the handshake, try to advance it. */
|
||||||
|
if (quic_do_handshake(ctx->qc) < 1)
|
||||||
|
/* ossl_quic_do_handshake raised error here */
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (remote_init == 0) {
|
||||||
|
if (!qc_try_create_default_xso_for_write(ctx->qc))
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
if (!qc_wait_for_default_xso_for_read(ctx->qc))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->xso = ctx->qc->default_xso;
|
ctx->xso = ctx->qc->default_xso;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->xso == NULL)
|
if (ctx->xso == NULL) {
|
||||||
return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, ERR_R_INTERNAL_ERROR, NULL);
|
QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_NO_STREAM, NULL);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1; /* lock held */
|
||||||
|
|
||||||
|
err:
|
||||||
|
quic_unlock(ctx->qc);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -193,7 +225,7 @@ static int ossl_unused expect_quic_conn_only(const SSL *s, QCTX *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ctx->is_stream)
|
if (ctx->is_stream)
|
||||||
return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, ERR_R_INTERNAL_ERROR, NULL);
|
return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_CONN_USE_ONLY, NULL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -261,6 +293,7 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
|
|||||||
qc->as_server = 0; /* TODO(QUIC): server support */
|
qc->as_server = 0; /* TODO(QUIC): server support */
|
||||||
qc->as_server_state = qc->as_server;
|
qc->as_server_state = qc->as_server;
|
||||||
|
|
||||||
|
qc->default_stream_mode = SSL_DEFAULT_STREAM_MODE_AUTO_BIDI;
|
||||||
qc->default_ssl_mode = qc->ssl.ctx->mode;
|
qc->default_ssl_mode = qc->ssl.ctx->mode;
|
||||||
qc->default_blocking = 1;
|
qc->default_blocking = 1;
|
||||||
qc->last_error = SSL_ERROR_NONE;
|
qc->last_error = SSL_ERROR_NONE;
|
||||||
@ -1119,50 +1152,123 @@ int ossl_quic_accept(SSL *s)
|
|||||||
* exists). Note that this is NOT an error condition.
|
* exists). Note that this is NOT an error condition.
|
||||||
*/
|
*/
|
||||||
QUIC_NEEDS_LOCK
|
QUIC_NEEDS_LOCK
|
||||||
static int qc_try_create_default_xso(QUIC_CONNECTION *qc, int remote_init)
|
static int qc_try_create_default_xso_for_write(QUIC_CONNECTION *qc)
|
||||||
{
|
{
|
||||||
QUIC_STREAM *qs;
|
uint64_t flags = 0;
|
||||||
|
|
||||||
if (qc->default_xso != NULL)
|
if (qc->default_xso_created
|
||||||
qc->default_xso_created = 1;
|
|| qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
|
||||||
|
|
||||||
if (qc->default_xso_created)
|
|
||||||
/*
|
/*
|
||||||
* We only do this once. If the user detaches a previously created
|
* We only do this once. If the user detaches a previously created
|
||||||
* default XSO we don't auto-create another one.
|
* default XSO we don't auto-create another one.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_NO_STREAM, NULL);
|
||||||
|
|
||||||
if (!remote_init) {
|
/* Create a locally-initiated stream. */
|
||||||
/*
|
if (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
|
||||||
* We are writing to the stream first, so this is a locally-initiated
|
flags |= SSL_STREAM_FLAG_UNI;
|
||||||
* stream.
|
|
||||||
*/
|
|
||||||
qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, 0);
|
|
||||||
if (qc->default_xso == NULL)
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Client is reading first. This means it is expecting to get data on a
|
|
||||||
* stream the peer writes to first, meaning this is a remotely-initiated
|
|
||||||
* stream. Ordinarily, we wait for the RXDP to handle a STREAM frame to
|
|
||||||
* create such a stream. But in this case, special case it and create
|
|
||||||
* the bookkeeping structures for the first peer-initiated bidirectional
|
|
||||||
* stream so the client can start to wait on it.
|
|
||||||
*/
|
|
||||||
qs = ossl_quic_channel_new_stream_remote(qc->ch,
|
|
||||||
QUIC_STREAM_INITIATOR_SERVER
|
|
||||||
| QUIC_STREAM_DIR_BIDI);
|
|
||||||
if (qs == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
qc->default_xso = create_xso_from_stream(qc, qs);
|
qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, flags);
|
||||||
if (qc->default_xso == NULL) {
|
if (qc->default_xso == NULL)
|
||||||
ossl_quic_stream_map_release(ossl_quic_channel_get_qsm(qc->ch), qs);
|
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||||
return 0;
|
|
||||||
}
|
qc->default_xso_created = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct quic_wait_for_stream_args {
|
||||||
|
QUIC_CONNECTION *qc;
|
||||||
|
QUIC_STREAM *qs;
|
||||||
|
uint64_t expect_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
QUIC_NEEDS_LOCK
|
||||||
|
static int quic_wait_for_stream(void *arg)
|
||||||
|
{
|
||||||
|
struct quic_wait_for_stream_args *args = arg;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args->qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(args->qc->ch),
|
||||||
|
args->expect_id);
|
||||||
|
if (args->qs != NULL)
|
||||||
|
return 1; /* stream now exists */
|
||||||
|
|
||||||
|
return 0; /* did not get a stream, keep trying */
|
||||||
|
}
|
||||||
|
|
||||||
|
QUIC_NEEDS_LOCK
|
||||||
|
static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc)
|
||||||
|
{
|
||||||
|
/* Called on a QCSO and we don't currently have a default stream. */
|
||||||
|
uint64_t expect_id;
|
||||||
|
QUIC_STREAM *qs;
|
||||||
|
int res;
|
||||||
|
struct quic_wait_for_stream_args wargs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If default stream functionality is disabled or we already detached
|
||||||
|
* one, don't make another default stream and just fail.
|
||||||
|
*/
|
||||||
|
if (qc->default_xso_created
|
||||||
|
|| qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_NO_STREAM, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The peer may have opened a stream since we last ticked. So tick and
|
||||||
|
* see if the stream with ordinal 0 (remote, bidi/uni based on stream
|
||||||
|
* mode) exists yet. QUIC stream IDs must be allocated in order, so the
|
||||||
|
* first stream created by a peer must have an ordinal of 0.
|
||||||
|
*/
|
||||||
|
expect_id = qc->as_server
|
||||||
|
? QUIC_STREAM_INITIATOR_CLIENT
|
||||||
|
: QUIC_STREAM_INITIATOR_SERVER;
|
||||||
|
|
||||||
|
expect_id |= (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
|
||||||
|
? QUIC_STREAM_DIR_UNI
|
||||||
|
: QUIC_STREAM_DIR_BIDI;
|
||||||
|
|
||||||
|
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(qc->ch),
|
||||||
|
expect_id);
|
||||||
|
if (qs == NULL) {
|
||||||
|
ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
|
||||||
|
|
||||||
|
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(qc->ch),
|
||||||
|
expect_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qs == NULL) {
|
||||||
|
if (!qc_blocking_mode(qc))
|
||||||
|
/* Non-blocking mode, so just bail immediately. */
|
||||||
|
return QUIC_RAISE_NORMAL_ERROR(qc, SSL_ERROR_WANT_READ);
|
||||||
|
|
||||||
|
/* Block until we have a stream. */
|
||||||
|
wargs.qc = qc;
|
||||||
|
wargs.qs = NULL;
|
||||||
|
wargs.expect_id = expect_id;
|
||||||
|
|
||||||
|
res = block_until_pred(qc, quic_wait_for_stream, &wargs, 0);
|
||||||
|
if (res == 0)
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||||
|
else if (res < 0 || wargs.qs == NULL)
|
||||||
|
/* quic_wait_for_stream raised error here */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qs = wargs.qs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now have qs != NULL. Make it the default stream, creating the
|
||||||
|
* necessary XSO.
|
||||||
|
*/
|
||||||
|
qc->default_xso = create_xso_from_stream(qc, qs);
|
||||||
|
if (qc->default_xso == NULL)
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||||
|
|
||||||
qc->default_xso_created = 1;
|
qc->default_xso_created = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1218,6 +1324,7 @@ SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags)
|
|||||||
if (xso == NULL)
|
if (xso == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
ctx.qc->default_xso_created = 1; /* inhibits default XSO */
|
||||||
quic_unlock(ctx.qc);
|
quic_unlock(ctx.qc);
|
||||||
return &xso->ssl;
|
return &xso->ssl;
|
||||||
|
|
||||||
@ -1508,11 +1615,11 @@ int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
|
|||||||
|
|
||||||
*written = 0;
|
*written = 0;
|
||||||
|
|
||||||
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx)) {
|
if (len == 0)
|
||||||
return 0;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
quic_lock(ctx.qc);
|
if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
|
||||||
|
return 0;
|
||||||
|
|
||||||
partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0);
|
partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0);
|
||||||
|
|
||||||
@ -1647,7 +1754,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
|
|||||||
|
|
||||||
*bytes_read = 0;
|
*bytes_read = 0;
|
||||||
|
|
||||||
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx))
|
if (!expect_quic(s, &ctx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
quic_lock(ctx.qc);
|
quic_lock(ctx.qc);
|
||||||
@ -1663,6 +1770,21 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx.xso == NULL) {
|
||||||
|
/*
|
||||||
|
* Called on a QCSO and we don't currently have a default stream.
|
||||||
|
*
|
||||||
|
* Wait until we get a stream initiated by the peer (blocking mode) or
|
||||||
|
* fail if we don't have one yet (non-blocking mode).
|
||||||
|
*/
|
||||||
|
if (!qc_wait_for_default_xso_for_read(ctx.qc)) {
|
||||||
|
ret = 0; /* error already raised here */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.xso = ctx.qc->default_xso;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx.xso->stream == NULL) {
|
if (ctx.xso->stream == NULL) {
|
||||||
ret = QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL);
|
ret = QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1734,11 +1856,9 @@ static size_t ossl_quic_pending_int(const SSL *s)
|
|||||||
size_t avail = 0;
|
size_t avail = 0;
|
||||||
int fin = 0;
|
int fin = 0;
|
||||||
|
|
||||||
if (!expect_quic_with_stream(s, /*remote_init=*/-1, &ctx))
|
if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, &ctx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
quic_lock(ctx.qc);
|
|
||||||
|
|
||||||
if (ctx.xso->stream == NULL || ctx.xso->stream->rstream == NULL)
|
if (ctx.xso->stream == NULL || ctx.xso->stream->rstream == NULL)
|
||||||
/* Cannot raise errors here because we are const, just fail. */
|
/* Cannot raise errors here because we are const, just fail. */
|
||||||
goto out;
|
goto out;
|
||||||
@ -1771,11 +1891,9 @@ int ossl_quic_conn_stream_conclude(SSL *s)
|
|||||||
QCTX ctx;
|
QCTX ctx;
|
||||||
QUIC_STREAM *qs;
|
QUIC_STREAM *qs;
|
||||||
|
|
||||||
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx))
|
if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
quic_lock(ctx.qc);
|
|
||||||
|
|
||||||
qs = ctx.xso->stream;
|
qs = ctx.xso->stream;
|
||||||
|
|
||||||
if (qs == NULL || qs->sstream == NULL) {
|
if (qs == NULL || qs->sstream == NULL) {
|
||||||
@ -1874,11 +1992,105 @@ int ossl_quic_get_stream_type(SSL *s)
|
|||||||
uint64_t ossl_quic_get_stream_id(SSL *s)
|
uint64_t ossl_quic_get_stream_id(SSL *s)
|
||||||
{
|
{
|
||||||
QCTX ctx;
|
QCTX ctx;
|
||||||
|
uint64_t id;
|
||||||
|
|
||||||
if (!expect_quic_with_stream(s, /*remote_init=*/-1, &ctx))
|
if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, &ctx))
|
||||||
return UINT64_MAX;
|
return UINT64_MAX;
|
||||||
|
|
||||||
return ctx.xso->stream->id;
|
id = ctx.xso->stream->id;
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSL_set_default_stream_mode
|
||||||
|
* ---------------------------
|
||||||
|
*/
|
||||||
|
int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
|
||||||
|
{
|
||||||
|
QCTX ctx;
|
||||||
|
|
||||||
|
if (!expect_quic_conn_only(s, &ctx))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
quic_lock(ctx.qc);
|
||||||
|
|
||||||
|
if (ctx.qc->default_xso_created)
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
|
||||||
|
"too late to change default stream mode");
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case SSL_DEFAULT_STREAM_MODE_NONE:
|
||||||
|
case SSL_DEFAULT_STREAM_MODE_AUTO_BIDI:
|
||||||
|
case SSL_DEFAULT_STREAM_MODE_AUTO_UNI:
|
||||||
|
ctx.qc->default_stream_mode = mode;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_PASSED_INVALID_ARGUMENT,
|
||||||
|
"bad default stream type");
|
||||||
|
}
|
||||||
|
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSL_detach_stream
|
||||||
|
* -----------------
|
||||||
|
*/
|
||||||
|
SSL *ossl_quic_detach_stream(SSL *s)
|
||||||
|
{
|
||||||
|
QCTX ctx;
|
||||||
|
QUIC_XSO *xso;
|
||||||
|
|
||||||
|
if (!expect_quic_conn_only(s, &ctx))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
quic_lock(ctx.qc);
|
||||||
|
|
||||||
|
xso = ctx.qc->default_xso;
|
||||||
|
ctx.qc->default_xso = NULL;
|
||||||
|
|
||||||
|
/* Calling this function inhibits default XSO autocreation. */
|
||||||
|
ctx.qc->default_xso_created = 1;
|
||||||
|
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
|
||||||
|
return &xso->ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSL_attach_stream
|
||||||
|
* -----------------
|
||||||
|
*/
|
||||||
|
int ossl_quic_attach_stream(SSL *conn, SSL *stream)
|
||||||
|
{
|
||||||
|
QCTX ctx;
|
||||||
|
|
||||||
|
if (!expect_quic_conn_only(conn, &ctx))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (stream == NULL || stream->type != SSL_TYPE_QUIC_XSO)
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_PASSED_NULL_PARAMETER,
|
||||||
|
"stream to attach must be a valid QUIC stream");
|
||||||
|
|
||||||
|
quic_lock(ctx.qc);
|
||||||
|
|
||||||
|
if (ctx.qc->default_xso != NULL) {
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
|
||||||
|
"connection already has a default stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.qc->default_xso = (QUIC_XSO *)stream;
|
||||||
|
|
||||||
|
/* Calling this function inhibits default XSO autocreation. */
|
||||||
|
ctx.qc->default_xso_created = 1;
|
||||||
|
|
||||||
|
quic_unlock(ctx.qc);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -172,6 +172,9 @@ struct quic_conn_st {
|
|||||||
/* Have we created a default XSO yet? */
|
/* Have we created a default XSO yet? */
|
||||||
unsigned int default_xso_created : 1;
|
unsigned int default_xso_created : 1;
|
||||||
|
|
||||||
|
/* Default stream type. Defaults to SSL_DEFAULT_STREAM_MODE_AUTO_BIDI. */
|
||||||
|
uint32_t default_stream_mode;
|
||||||
|
|
||||||
/* SSL_set_mode. This is not used directly but inherited by new XSOs. */
|
/* SSL_set_mode. This is not used directly but inherited by new XSOs. */
|
||||||
uint32_t default_ssl_mode;
|
uint32_t default_ssl_mode;
|
||||||
|
|
||||||
|
@ -311,6 +311,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
|||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS),
|
||||||
"no shared signature algorithms"},
|
"no shared signature algorithms"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_STREAM), "no stream"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM),
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM),
|
||||||
"no suitable digest algorithm"},
|
"no suitable digest algorithm"},
|
||||||
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"},
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"},
|
||||||
|
@ -7352,6 +7352,42 @@ uint64_t SSL_get_stream_id(SSL *s)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SSL_set_default_stream_mode(SSL *s, uint32_t mode)
|
||||||
|
{
|
||||||
|
#ifndef OPENSSL_NO_QUIC
|
||||||
|
if (!IS_QUIC(s))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ossl_quic_set_default_stream_mode(s, mode);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL *SSL_detach_stream(SSL *s)
|
||||||
|
{
|
||||||
|
#ifndef OPENSSL_NO_QUIC
|
||||||
|
if (!IS_QUIC(s))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ossl_quic_detach_stream(s);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int SSL_attach_stream(SSL *conn, SSL *stream)
|
||||||
|
{
|
||||||
|
#ifndef OPENSSL_NO_QUIC
|
||||||
|
if (!IS_QUIC(conn))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ossl_quic_attach_stream(conn, stream);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
|
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
|
@ -564,3 +564,7 @@ SSL_new_stream ? 3_2_0 EXIST::FUNCTION:
|
|||||||
SSL_get0_connection ? 3_2_0 EXIST::FUNCTION:
|
SSL_get0_connection ? 3_2_0 EXIST::FUNCTION:
|
||||||
SSL_is_connection ? 3_2_0 EXIST::FUNCTION:
|
SSL_is_connection ? 3_2_0 EXIST::FUNCTION:
|
||||||
SSL_get_stream_type ? 3_2_0 EXIST::FUNCTION:
|
SSL_get_stream_type ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_get_stream_id ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_set_default_stream_mode ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_detach_stream ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
SSL_attach_stream ? 3_2_0 EXIST::FUNCTION:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user