@startuml

[*] --> IDLE

ESTABLISHING : PROBE_TIMEOUT: SendProbeIfAnySentPktsUnacked() [default]

state ACTIVE {
    state ESTABLISHING {
        PROACTIVE_VER_NEG :
        PRE_INITIAL :
        INITIAL_EXCHANGE_A :
        REACTIVE_VER_NEG :
        INITIAL_EXCHANGE_B :
        INITIAL_EXCHANGE_CONTINUED :
        HANDSHAKE :
        HANDSHAKE_CONTINUED :
        HANDSHAKE_COMPLETED :
        HANDSHAKE_CONFIRMED :

        [*] --> PROACTIVE_VER_NEG : use proactive VN?
        [*] --> PRE_INITIAL : else
        PROACTIVE_VER_NEG --> PRE_INITIAL : RX:VER_NEG
        PROACTIVE_VER_NEG --> PROACTIVE_VER_NEG : PROBE_TIMEOUT
        PRE_INITIAL --> INITIAL_EXCHANGE_A : ε
        INITIAL_EXCHANGE_A --> INITIAL_EXCHANGE_B : RX:RETRY
        INITIAL_EXCHANGE_A --> INITIAL_EXCHANGE_CONTINUED : RX:INITIAL
        INITIAL_EXCHANGE_A --> REACTIVE_VER_NEG : RX:VER_NEG

        REACTIVE_VER_NEG --> PRE_INITIAL : ε

        INITIAL_EXCHANGE_B --> INITIAL_EXCHANGE_CONTINUED : RX:INITIAL
        INITIAL_EXCHANGE_CONTINUED --> HANDSHAKE : TLS:HAVE_EL(HANDSHAKE)

        HANDSHAKE --> HANDSHAKE_CONTINUED : RX:HANDSHAKE
        HANDSHAKE_CONTINUED --> HANDSHAKE_COMPLETED : TLS:HANDSHAKE_COMPLETE
        HANDSHAKE_COMPLETED --> HANDSHAKE_CONFIRMED : RX:1RTT[HANDSHAKE_DONE]
    }
    OPEN :
    [*] --> ESTABLISHING
}

state TERMINATING {
    CLOSING :
    DRAINING :
    CLOSING --> DRAINING : RX:ANY[CONNECTION_CLOSE]
}

HANDSHAKE_CONFIRMED --> OPEN : ε

IDLE --> ACTIVE : APP:CONNECT

IDLE --> TERMINATED : APP:CLOSE
TERMINATING --> TERMINATED : TERMINATING_TIMEOUT, RX:STATELESS_RESET

ACTIVE --> CLOSING : APP:CLOSE
ACTIVE --> DRAINING : RX:ANY[CONNECTION_CLOSE]
ACTIVE --> TERMINATED : IDLE_TIMEOUT, RX:STATELESS_RESET

@enduml
