- if (!remote_init) {
- /*
- * We are writing to the stream first, so this is a locally-initiated
- * 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);
- if (qc->default_xso == NULL) {
- ossl_quic_stream_map_release(ossl_quic_channel_get_qsm(qc->ch), qs);
+ /* Create a locally-initiated stream. */
+ if (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
+ flags |= SSL_STREAM_FLAG_UNI;
+
+ qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, flags);
+ if (qc->default_xso == NULL)
+ return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
+
+ 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 */