int stream_flush = ((flags & SSL_SHUTDOWN_FLAG_NO_STREAM_FLUSH) == 0);
if (!expect_quic(s, &ctx))
- return 0;
+ return -1;
if (ctx.is_stream)
/* TODO(QUIC): Semantics currently undefined for QSSOs */
quic_lock(ctx.qc);
+ if (ossl_quic_channel_is_terminated(ctx.qc->ch)) {
+ quic_unlock(ctx.qc);
+ return 1;
+ }
+
/* Phase 1: Stream Flushing */
if (stream_flush) {
qc_shutdown_flush_init(ctx.qc);
*/
DEFINE_LHASH_OF_EX(QUIC_STREAM);
+static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs);
+
/* Circular list management. */
static void list_insert_tail(QUIC_STREAM_LIST_NODE *l,
QUIC_STREAM_LIST_NODE *n)
if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT
&& ossl_quic_sstream_is_totally_acked(s->sstream))
ossl_quic_stream_map_notify_totally_acked(qsm, s);
+ else if (s->shutdown_flush
+ && s->send_state == QUIC_SSTREAM_STATE_SEND
+ && ossl_quic_sstream_is_totally_acked(s->sstream))
+ shutdown_flush_done(qsm, s);
if (!s->ready_for_gc) {
s->ready_for_gc = qsm_ready_for_gc(qsm, s);
{
/*
* We only care about servicing the send part of a stream (if any) during
- * shutdown flush. A stream needs to have a final size and that final size
- * needs to be a result of normal conclusion of a stream via
- * SSL_stream_conclude (as opposed to due to reset). If the application did
- * not conclude a stream before deleting it we assume it does not care about
- * data being flushed during connection termination.
+ * shutdown flush. We make sure we flush a stream if it is either
+ * non-terminated or was terminated normally such as via
+ * SSL_stream_conclude. A stream which was terminated via a reset is not
+ * flushed, and we will have thrown away the send buffer in that case
+ * anyway.
*/
- return ossl_quic_stream_has_send_buffer(qs)
- && ossl_quic_stream_send_get_final_size(qs, NULL);
+ switch (qs->send_state) {
+ case QUIC_SSTREAM_STATE_SEND:
+ case QUIC_SSTREAM_STATE_DATA_SENT:
+ return !ossl_quic_sstream_is_totally_acked(qs->sstream);
+ default:
+ return 0;
+ }
}
static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)
}
/* When will CC let us send more? */
- deadline = ossl_time_min(deadline,
- txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
+ if (txp->args.cc_method->get_tx_allowance(txp->args.cc_data) == 0)
+ deadline = ossl_time_min(deadline,
+ txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
return deadline;
}