#define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */
#define QUIC_FL_CONN_NOTIFY_CLOSE (1U << 27) /* MUX notified about quic-conn imminent closure (idle-timeout or CONNECTION_CLOSE emission/reception) */
#define QUIC_FL_CONN_EXP_TIMER (1U << 28) /* timer has expired, quic-conn can be freed */
-#define QUIC_FL_CONN_CLOSING (1U << 29)
-#define QUIC_FL_CONN_DRAINING (1U << 30)
-#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31)
+#define QUIC_FL_CONN_CLOSING (1U << 29) /* closing state, entered on CONNECTION_CLOSE emission */
+#define QUIC_FL_CONN_DRAINING (1U << 30) /* draining state, entered on CONNECTION_CLOSE reception */
+#define QUIC_FL_CONN_IMMEDIATE_CLOSE (1U << 31) /* A CONNECTION_CLOSE must be sent */
struct quic_conn {
const struct quic_version *original_version;
* Rearm the idle timeout only one time when entering draining
* state.
*/
- qc_idle_timer_do_rearm(qc);
qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE;
+ qc_idle_timer_do_rearm(qc);
qc_notify_close(qc);
}
break;
{
unsigned int expire;
- expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
- qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire));
- task_queue(qc->idle_timer_task);
+ if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
+ TRACE_STATE("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc);
+ task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
+ }
+ else {
+ expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
+ qc->idle_timer_task->expire = tick_add(now_ms, MS_TO_TICKS(expire));
+ task_queue(qc->idle_timer_task);
+ }
}
/* Rearm the idle timer for <qc> QUIC connection depending on <read> boolean
goto leave;
}
+ /* Schedule a CONNECTION_CLOSE emission. If process stopping is in
+ * progress, quic-conn idle-timer will be scheduled immediately after
+ * its emission to ensure an immediate connection closing.
+ */
qc_check_close_on_released_mux(qc);
leave:
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);