| /*
* the transport finished: a server starts on the request, an h1 client
* on sending one, an mqtt client on its CONNECT, the rest are up
*/
{ "h1", "C", LRS_UNCONNECTED, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 }, /* inherited from an idle leader */
{ "h1", "C", LRS_WAITING_SSL, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "h2", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "mqtt", "C", LRS_UNCONNECTED, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_MQTTC_IDLE },
{ "mqtt", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_MQTTC_IDLE },
{ "mqtt", "C", LRS_WAITING_SSL, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_MQTTC_IDLE },
{ "mqtt", "C", LRS_WAITING_SOCKS_CONNECT_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_MQTTC_IDLE },
{ "mqtt", "C", LRS_WAITING_PROXY_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_MQTTC_IDLE },
{ "raw-skt", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-skt", "C", LRS_WAITING_SSL, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-skt", "C", LRS_WAITING_SOCKS_CONNECT_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-skt", "C", LRS_WAITING_PROXY_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
/* the raw proxy's onward connections are raw clients too */
{ "raw-proxy", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-proxy", "C", LRS_WAITING_SSL, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-proxy", "C", LRS_WAITING_SOCKS_CONNECT_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "raw-proxy", "C", LRS_WAITING_PROXY_REPLY, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "quic", "C", LRS_WAITING_SSL, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "quic", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "quic", "S", LRS_SSL_INIT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "h1", "S", LRS_SSL_ACK_PENDING, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_HEADERS },
{ "h1", "S", LRS_AWAITING_SSL_ACCEPT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_HEADERS },
{ "h1", "S", LRS_SSL_INIT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_HEADERS },
{ "*", "S", LRS_SSL_ACK_PENDING, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "*", "S", LRS_AWAITING_SSL_ACCEPT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
{ "*", "S", LRS_SSL_INIT, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
/* the non-tls fallback already established the wsi before the accept path reports the transport up */
{ "*", "S", LRS_ESTABLISHED, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
/* 0-RTT: the ALPN migration ran inside the handshake, so handshake-done finds the new nwsi established */
{ "quic", "*", LRS_ESTABLISHED, LWS_WSIEV_TRANSPORT_UP, NULL, NULL, LRS_ESTABLISHED },
/* an h1 client's tcp is up before its tls */
{ "h1", "C", LRS_WAITING_CONNECT, LWS_WSIEV_SOCKET_CONNECTED, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE },
/* a socks or http CONNECT tunnel coming up is the socket connecting, for the protocol */
{ "h1", "C", LRS_WAITING_SOCKS_CONNECT_REPLY, LWS_WSIEV_SOCKET_CONNECTED, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE },
{ "h1", "C", LRS_WAITING_PROXY_REPLY, LWS_WSIEV_SOCKET_CONNECTED, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_SOCKET_CONNECTED, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
/* a client request queued on, or issued by, a connection */
/* any client role may queue behind a leader: raw-skt and mqtt do too */
{ "*", "C", LRS_UNCONNECTED, LWS_WSIEV_QUEUED, NULL, NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "C", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_QUEUED, NULL, NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "h1", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_ISSUE, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "quic", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_ISSUE, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 }, /* h3 queue pickup */
{ "h1", "C", LRS_ESTABLISHED, LWS_WSIEV_REQ_ISSUE, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_IDLING, LWS_WSIEV_REQ_ISSUE, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
{ "h1", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_REQ_ISSUE, NULL, NULL, LRS_H1C_ISSUE_HANDSHAKE2 },
/* the request goes out, then its response is pending */
{ "h1", "C", LRS_WAITING_SSL, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h1", "C", LRS_WAITING_CONNECT, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h2", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h3", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_HDRS_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h1", "C", LRS_WAITING_SSL, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "h1", "C", LRS_WAITING_CONNECT, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "h2", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "h3", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_REQ_HDRS_SENT_BODY, NULL, NULL, LRS_ISSUE_HTTP_BODY },
{ "*", "C", LRS_ISSUE_HTTP_BODY, LWS_WSIEV_REQ_BODY_SENT, NULL, NULL, LRS_WAITING_SERVER_REPLY },
{ "h1", "C", LRS_ESTABLISHED, LWS_WSIEV_RESP_INTERIM, NULL, NULL, LRS_WAITING_SERVER_REPLY },
/* a ws client takes no response headers but the 101's: it is still waiting */
{ "h1", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_RESP_INTERIM, NULL, NULL, LRS_WAITING_SERVER_REPLY },
/* the response is done: idle, or an idle connection is picked up */
{ "h1", "C", LRS_ESTABLISHED, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_IDLING },
{ "*", "C", LRS_IDLING, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_IDLING },
{ "h2", "C", LRS_ESTABLISHED, LWS_WSIEV_LAST_STREAM_CLOSED, NULL, NULL, LRS_IDLING },
{ "quic", "C", LRS_ESTABLISHED, LWS_WSIEV_LAST_STREAM_CLOSED, NULL, NULL, LRS_IDLING },
{ "h2", "C", LRS_IDLING, LWS_WSIEV_CONN_REUSED, NULL, NULL, LRS_ESTABLISHED },
{ "quic", "C", LRS_IDLING, LWS_WSIEV_CONN_REUSED, NULL, NULL, LRS_ESTABLISHED },
/* mqtt client handshake */
{ "mqtt", "C", LRS_MQTTC_IDLE, LWS_WSIEV_MQTT_CONNECT_SENT, NULL, NULL, LRS_MQTTC_AWAIT_CONNACK },
{ "mqtt", "C", LRS_MQTTC_AWAIT_CONNACK, LWS_WSIEV_MQTT_CONNACK, NULL, NULL, LRS_ESTABLISHED },
/* h2 connection preface */
{ "h2", "S", LRS_H2_AWAIT_PREFACE, LWS_WSIEV_H2_PREFACE_RX, NULL, NULL, LRS_H2_AWAIT_SETTINGS },
{ "h2", "S", LRS_H2_AWAIT_SETTINGS, LWS_WSIEV_H2_SETTINGS_ACKED, NULL, NULL, LRS_ESTABLISHED },
/* request headers: h1 decides on the upgrade, mux streams defer the action */
{ "h1", "S", LRS_HEADERS, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_H1_UPGRADE },
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_H1_UPGRADE },
{ "h2", "S", LRS_HEADERS, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_DEFERRING_ACTION },
{ "h2", "S", LRS_ESTABLISHED, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_DEFERRING_ACTION },
{ "h3", "S", LRS_HEADERS, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_DEFERRING_ACTION },
{ "h3", "S", LRS_ESTABLISHED, LWS_WSIEV_REQ_HDRS_COMPLETE, NULL, NULL, LRS_DEFERRING_ACTION },
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_REQ_PLAIN_HTTP, NULL, NULL, LRS_ESTABLISHED },
{ "h2", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_ACTION_DEFERRED_RUN, NULL, NULL, LRS_ESTABLISHED },
{ "h3", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_ACTION_DEFERRED_RUN, NULL, NULL, LRS_ESTABLISHED },
/* acting on the request */
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_ACTION_BEGIN, NULL, NULL, LRS_DOING_TRANSACTION },
{ "h2", "S", LRS_HEADERS, LWS_WSIEV_ACTION_BEGIN, NULL, NULL, LRS_DOING_TRANSACTION },
{ "h2", "S", LRS_ESTABLISHED, LWS_WSIEV_ACTION_BEGIN, NULL, NULL, LRS_DOING_TRANSACTION },
{ "h3", "S", LRS_HEADERS, LWS_WSIEV_ACTION_BEGIN, NULL, NULL, LRS_DOING_TRANSACTION },
{ "h3", "S", LRS_ESTABLISHED, LWS_WSIEV_ACTION_BEGIN, NULL, NULL, LRS_DOING_TRANSACTION },
/* request body */
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY },
{ "h1", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY },
{ "h2", "*", LRS_ESTABLISHED, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY },
{ "h2", "*", LRS_HEADERS, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY },
{ "h3", "*", LRS_ESTABLISHED, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY },
{ "h3", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY }, /* action ran, body follows: as h1 */
{ "h2", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_BEGIN, NULL, NULL, LRS_BODY }, /* same on h2 */
/*
* an h1 body is complete before its answer is: the connection's next
* request, pipelined behind it, waits parked for the transaction
*/
{ "h1", "S", LRS_BODY, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_DOING_TRANSACTION },
{ "h2", "S", LRS_BODY, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_ESTABLISHED },
{ "h3", "S", LRS_BODY, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_ESTABLISHED },
/* the body completion callback may itself have started serving a file (C-522) */
{ "h2", "S", LRS_ISSUING_FILE, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_ISSUING_FILE },
{ "h3", "S", LRS_ISSUING_FILE, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_ISSUING_FILE },
{ "h2", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_AWAITING_FILE_READ },
{ "h3", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_BODY_COMPLETE, NULL, NULL, LRS_AWAITING_FILE_READ },
{ "h1", "S", LRS_BODY, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
/* the user may complete the transaction before the body was ever delivered */
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h1", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h1", "S", LRS_ISSUING_FILE, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
/* the completion runs for mux streams too: there DISCARD_BODY drops the stash and closes the stream */
{ "h2", "S", LRS_ESTABLISHED, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_ESTABLISHED, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_HEADERS, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_HEADERS, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_BODY, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_BODY, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_ISSUING_FILE, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_ISSUING_FILE, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
/* ...or abandoned with a read of the file out on a worker, reaped by the completion */
{ "h1", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
/* the h1 transaction ends and the connection is reused */
/*
* the user completed it with its response still queued: completion
* waits for that to go, from wherever the transaction had got to
*/
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_DISCARD_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_TXN_COMPLETED, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_ISSUING_FILE, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h1", "S", LRS_TXN_COMPLETING, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_HEADERS, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_ESTABLISHED, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_DISCARD_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_ISSUING_FILE, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_TXN_COMPLETING, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_HEADERS, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_DEFERRING_ACTION, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_ESTABLISHED, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_DISCARD_BODY, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_ISSUING_FILE, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_TXN_COMPLETING, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
/*
* a file being served, a read of it out on a worker, that the app
* completed from under (an h2 / h3 body completion, its own timer):
* the completion waits for the answer queued so far as any other
*/
{ "h1", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h2", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
{ "h3", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_TXN_COMPLETING, NULL, NULL, LRS_TXN_COMPLETING },
/* ...and once it has, it completes, or first discards an unread body */
{ "h1", "S", LRS_TXN_COMPLETING, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_TXN_COMPLETING, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h2", "S", LRS_TXN_COMPLETING, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h3", "S", LRS_TXN_COMPLETING, LWS_WSIEV_BODY_DISCARD, NULL, NULL, LRS_DISCARD_BODY },
{ "h1", "S", LRS_ESTABLISHED, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_BODY, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_DISCARD_BODY, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED }, /* upgrade refused */
{ "h1", "S", LRS_TXN_COMPLETED, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED },
{ "h1", "S", LRS_ISSUING_FILE, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED }, /* completed from the file-complete callback */
{ "h1", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_TXN_COMPLETED, NULL, NULL, LRS_TXN_COMPLETED }, /* or abandoned with a read out on a worker */
{ "h1", "S", LRS_TXN_COMPLETED, LWS_WSIEV_TXN_DRAINED, NULL, NULL, LRS_HEADERS },
/* serving a file */
{ "*", "S", LRS_ESTABLISHED, LWS_WSIEV_FILE_BEGIN, NULL, NULL, LRS_ISSUING_FILE },
{ "h2", "S", LRS_HEADERS, LWS_WSIEV_FILE_BEGIN, NULL, NULL, LRS_ISSUING_FILE }, /* h2c upgrade stream 1 */
{ "*", "S", LRS_DOING_TRANSACTION, LWS_WSIEV_FILE_BEGIN, NULL, NULL, LRS_ISSUING_FILE },
{ "*", "S", LRS_BODY, LWS_WSIEV_FILE_BEGIN, NULL, NULL, LRS_ISSUING_FILE }, /* served from HTTP_BODY_COMPLETION */
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_FILE_BEGIN, NULL, NULL, LRS_ISSUING_FILE }, /* served from HTTP_CONFIRM_UPGRADE */
{ "*", "S", LRS_ISSUING_FILE, LWS_WSIEV_FILE_READ_QUEUED, NULL, NULL, LRS_AWAITING_FILE_READ },
{ "*", "S", LRS_AWAITING_FILE_READ, LWS_WSIEV_FILE_READ_DONE, NULL, NULL, LRS_ISSUING_FILE },
{ "*", "S", LRS_ISSUING_FILE, LWS_WSIEV_FILE_COMPLETE, NULL, NULL, LRS_ESTABLISHED },
/* ---- role changes ---- */
/* birth on a server, adoption, the client bind, a restart */
{ "(none)", "-", LRS_UNCONNECTED, LWS_WSIEV_SERVER_SIDE, NULL, "S", LRS_UNCONNECTED },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_ADOPTED_TLS, "?", NULL, LRS_SSL_INIT },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_ADOPTED, "h1", NULL, LRS_HEADERS },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_ADOPTED, "?", NULL, LRS_ESTABLISHED },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_CLIENT_BIND, "?", "C", LRS_UNCONNECTED },
{ "*", "C", ANY, LWS_WSIEV_RESTART, "?", "C", LRS_UNCONNECTED },
/* mux children: a fresh child is its parent's; a server's opened stream reads its request */
{ "(none)", "*", LRS_UNCONNECTED, LWS_WSIEV_MUX_INSERTED, "P", "P", LRS_UNCONNECTED },
{ "h2", "S", LRS_UNCONNECTED, LWS_WSIEV_STREAM_OPENED, NULL, NULL, LRS_HEADERS },
{ "h2", "C", LRS_UNCONNECTED, LWS_WSIEV_STREAM_OPENED, NULL, NULL, LRS_UNCONNECTED },
{ "quic", "S", LRS_UNCONNECTED, LWS_WSIEV_STREAM_OPENED, "h3", NULL, LRS_HEADERS },
{ "quic", "C", LRS_UNCONNECTED, LWS_WSIEV_STREAM_OPENED, "h3", NULL, LRS_ESTABLISHED },
{ "quic", "*", LRS_UNCONNECTED, LWS_WSIEV_STREAM_OPENED, "quic", NULL, LRS_ESTABLISHED },
/* a client stream is let onto its connection: h2 / h3 send a request, mqtt is up */
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_MUX_STREAM_ADOPTED, "h2", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_MUX_STREAM_ADOPTED, "h2", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_MUX_STREAM_ADOPTED, "h2", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_MUX_STREAM_ADOPTED, "h3", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_H1C_ISSUE_HANDSHAKE2, LWS_WSIEV_MUX_STREAM_ADOPTED, "h3", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_WAITING_CONNECT, LWS_WSIEV_MUX_STREAM_ADOPTED, "h3", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_WAITING_SSL, LWS_WSIEV_MUX_STREAM_ADOPTED, "h3", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_MUX_STREAM_ADOPTED, "h3", "P", LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "*", LRS_UNCONNECTED, LWS_WSIEV_MUX_STREAM_ADOPTED, "mqtt", "P", LRS_ESTABLISHED },
{ "*", "*", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_MUX_STREAM_ADOPTED, "mqtt", "P", LRS_ESTABLISHED },
{ "*", "*", LRS_ESTABLISHED, LWS_WSIEV_MUX_STREAM_ADOPTED, "mqtt", "P", LRS_ESTABLISHED },
/* our own h3 unidirectional streams, and a wsi taking over a quic connection */
{ "(none)", "*", LRS_UNCONNECTED, LWS_WSIEV_CONTROL_STREAM_OPENED, "h3", "L", LRS_ESTABLISHED },
{ "(none)", "*", LRS_UNCONNECTED, LWS_WSIEV_CONN_TAKEOVER, "?", "L", LRS_ESTABLISHED },
/* the quic handshake chose h3 (a client stream sends, a server stream reads) or not */
{ "*", "C", LRS_UNCONNECTED, LWS_WSIEV_ALPN_DONE, "h3", NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "*", "C", LRS_WAITING_CONNECT, LWS_WSIEV_ALPN_DONE, "h3", NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "quic", "C", ANY, LWS_WSIEV_ALPN_DONE, "h3", NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
{ "quic", "S", ANY, LWS_WSIEV_ALPN_DONE, "h3", NULL, LRS_HEADERS },
{ "quic", "*", ANY, LWS_WSIEV_ALPN_DONE, "quic", NULL, LRS_ESTABLISHED },
/*
* the h2 client nwsi hands its own request to the sid-1 child and is
* from then on the carrier of streams only: established
*/
{ "h2", "C", LRS_H2_WAITING_TO_SEND_HEADERS, LWS_WSIEV_MUX_MIGRATED, NULL, NULL, LRS_ESTABLISHED },
/* h2: chosen by alpn, h2c upgrade or prior knowledge; the client preface */
{ "h1", "S", LRS_HEADERS, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "(none)", "S", LRS_UNCONNECTED, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "h1", "C", LRS_H1C_ISSUE_HANDSHAKE, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "h1", "C", LRS_WAITING_SSL, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "h1", "C", LRS_UNCONNECTED, LWS_WSIEV_H2_SELECTED, "h2", NULL, LRS_H2_AWAIT_PREFACE },
{ "h2", "C", LRS_H2_AWAIT_PREFACE, LWS_WSIEV_H2_PREFACE_SENT, NULL, NULL, LRS_H2_WAITING_TO_SEND_HEADERS },
/* ws upgrade, on a server from the upgrade decision, on a client from the 101 */
{ "h1", "S", LRS_H1_UPGRADE, LWS_WSIEV_WS_UPGRADED, "ws", NULL, LRS_ESTABLISHED },
{ "h2", "S", LRS_ESTABLISHED, LWS_WSIEV_WS_UPGRADED, "ws", "Se", LRS_ESTABLISHED },
{ "h3", "S", LRS_ESTABLISHED, LWS_WSIEV_WS_UPGRADED, "ws", "Se", LRS_ESTABLISHED }, /* RFC 9220 */
{ "h1", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_WS_UPGRADED, "ws", NULL, LRS_ESTABLISHED },
{ "h2", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_WS_UPGRADED, "ws", "Ce", LRS_ESTABLISHED },
/* the client's response headers; webtransport; raw */
{ "*", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_RESP_HDRS, NULL, NULL, LRS_ESTABLISHED },
/* a server may answer before the request body is finished (401, 413...) */
{ "*", "C", LRS_ISSUE_HTTP_BODY, LWS_WSIEV_RESP_HDRS, NULL, NULL, LRS_ESTABLISHED },
{ "h3", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_WT_SESSION, "wt", NULL, LRS_ESTABLISHED },
{ "h3", "S", ANY, LWS_WSIEV_WT_SESSION, "wt", NULL, LRS_ESTABLISHED },
{ "h3", "*", ANY, LWS_WSIEV_WT_STREAM, "wt", NULL, LRS_ESTABLISHED },
{ "(none)", "*", LRS_UNCONNECTED, LWS_WSIEV_WT_STREAM, "wt", "L", LRS_ESTABLISHED },
{ "*", "S", LRS_HEADERS, LWS_WSIEV_RAW_UPGRADED, "?", NULL, LRS_ESTABLISHED },
{ "*", "S", LRS_H1_UPGRADE, LWS_WSIEV_RAW_UPGRADED, "?", NULL, LRS_ESTABLISHED },
/* the non-tls fallback on a tls listener, from the first byte peek in the accept */
{ "*", "S", LRS_SSL_INIT, LWS_WSIEV_RAW_UPGRADED, "?", NULL, LRS_ESTABLISHED },
{ "*", "S", LRS_SSL_ACK_PENDING, LWS_WSIEV_RAW_UPGRADED, "?", NULL, LRS_ESTABLISHED },
/* a later request on a kept-alive connection, and a listener already in the raw role */
{ "*", "S", LRS_ESTABLISHED, LWS_WSIEV_RAW_UPGRADED, "?", NULL, LRS_ESTABLISHED },
{ "h1", "C", LRS_ESTABLISHED, LWS_WSIEV_RAW_UPGRADED, "raw-skt", NULL, LRS_ESTABLISHED },
{ "h1", "C", LRS_WAITING_SERVER_REPLY, LWS_WSIEV_RAW_UPGRADED, "raw-skt", NULL, LRS_ESTABLISHED },
/* ---- transport machine ---- */
{ "*", "C", LRS_UNCONNECTED, LWS_WSIEV_DNS_START, NULL, NULL, XT(LTS_WAITING_DNS) },
{ "*", "C", LRS_WAITING_DNS, LWS_WSIEV_DNS_RETRY, NULL, NULL, XT(LTS_NONE) },
{ "*", "C", LRS_UNCONNECTED, LWS_WSIEV_CONNECT_START, NULL, NULL, XT(LTS_WAITING_CONNECT) },
{ "*", "C", LRS_WAITING_DNS, LWS_WSIEV_CONNECT_START, NULL, NULL, XT(LTS_WAITING_CONNECT) },
{ "*", "C", LRS_WAITING_CONNECT, LWS_WSIEV_CONNECT_START, NULL, NULL, XT(LTS_WAITING_CONNECT) }, /* next address */
{ "*", "C", LRS_WAITING_SSL, LWS_WSIEV_CONNECT_START, NULL, NULL, XT(LTS_WAITING_CONNECT) }, /* quic to tcp */
{ "*", "C", LRS_WAITING_CONNECT, LWS_WSIEV_PROXY_CONNECT_SENT, NULL, NULL, XT(LTS_WAITING_PROXY_REPLY) },
{ "*", "C", LRS_WAITING_CONNECT, LWS_WSIEV_SOCKS_GREETING_SENT, NULL, NULL, XT(LTS_WAITING_SOCKS_GREETING_REPLY) },
{ "*", "C", LRS_WAITING_SOCKS_GREETING_REPLY, LWS_WSIEV_SOCKS_AUTH_SENT, NULL, NULL, XT(LTS_WAITING_SOCKS_AUTH_REPLY) },
{ "*", "C", LRS_WAITING_SOCKS_GREETING_REPLY, LWS_WSIEV_SOCKS_CONNECT_SENT, NULL, NULL, XT(LTS_WAITING_SOCKS_CONNECT_REPLY) },
{ "*", "C", LRS_WAITING_SOCKS_AUTH_REPLY, LWS_WSIEV_SOCKS_CONNECT_SENT, NULL, NULL, XT(LTS_WAITING_SOCKS_CONNECT_REPLY) },
{ "*", "C", LRS_WAITING_CONNECT, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) },
{ "*", "C", LRS_WAITING_PROXY_REPLY, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) },
{ "*", "C", LRS_WAITING_SOCKS_CONNECT_REPLY, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) },
{ "*", "C", LRS_H1C_ISSUE_HANDSHAKE, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) },
{ "*", "C", LRS_WAITING_SSL, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) }, /* more service */
/* STARTTLS: an established raw client starts tls inside its protocol */
{ "raw-skt", "C", LRS_ESTABLISHED, LWS_WSIEV_TLS_START, NULL, NULL, XT(LTS_WAITING_SSL) },
{ "*", "S", LRS_SSL_INIT, LWS_WSIEV_TLS_ACCEPT_PENDING, NULL, NULL, XT(LTS_SSL_ACK_PENDING) },
{ "*", "S", LRS_SSL_ACK_PENDING, LWS_WSIEV_TLS_ACCEPT_PENDING, NULL, NULL, XT(LTS_SSL_ACK_PENDING) },
{ "*", "S", LRS_AWAITING_SSL_ACCEPT, LWS_WSIEV_TLS_ACCEPT_PENDING, NULL, NULL, XT(LTS_SSL_ACK_PENDING) },
{ "*", "S", LRS_SSL_INIT, LWS_WSIEV_TLS_ACCEPT_QUEUED, NULL, NULL, XT(LTS_AWAITING_SSL_ACCEPT) },
{ "*", "S", LRS_SSL_ACK_PENDING, LWS_WSIEV_TLS_ACCEPT_QUEUED, NULL, NULL, XT(LTS_AWAITING_SSL_ACCEPT) },
{ "*", "C", ANY, LWS_WSIEV_CONN_FAILED, NULL, NULL, XT(LTS_FAILED) },
{ "*", "C", ANY, LWS_WSIEV_RETARGET, NULL, NULL, XT(LTS_RESTARTING) },
/* ---- close machine: the polite ws close is specific, the rest can come from anywhere ---- */
{ "ws", "*", LRS_ESTABLISHED, LWS_WSIEV_WS_CLOSE_INITIATED, NULL, NULL, XC(LCS_WAITING_TO_SEND_CLOSE) },
{ "ws", "*", LRS_WAITING_TO_SEND_CLOSE, LWS_WSIEV_WS_CLOSE_SENT, NULL, NULL, XC(LCS_AWAITING_CLOSE_ACK) },
{ "ws", "*", LRS_ESTABLISHED, LWS_WSIEV_WS_PEER_CLOSE, NULL, NULL, XC(LCS_RETURNED_CLOSE) },
/* his CLOSE beat the one we were about to send: answer his and drop ours */
{ "ws", "*", LRS_WAITING_TO_SEND_CLOSE, LWS_WSIEV_WS_PEER_CLOSE, NULL, NULL, XC(LCS_RETURNED_CLOSE) },
/*
* the close is entered: a flush the live connection had begun is now
* the close's own, else the close has begun with nothing to wait for
*/
{ "*", "*", LRS_FLUSHING_BEFORE_CLOSE, LWS_WSIEV_CLOSE_ENTERED, NULL, NULL, XC(LCS_FLUSHING_BEFORE_CLOSE) },
{ "*", "*", ANY, LWS_WSIEV_CLOSE_ENTERED, NULL, NULL, XC(LCS_CLOSING) },
{ "*", "*", ANY, LWS_WSIEV_CLOSE_FLUSH, NULL, NULL, XC(LCS_FLUSHING_BEFORE_CLOSE) },
{ "*", "*", ANY, LWS_WSIEV_CLOSE_WHEN_FLUSHED, NULL, NULL, XC(LCS_CLOSE_WHEN_FLUSHED) },
{ "*", "S", ANY, LWS_WSIEV_CLOSE_STAGED, NULL, NULL, XC(LCS_SHUTDOWN) },
{ "*", "*", ANY, LWS_WSIEV_SOCKET_GONE, NULL, NULL, XC(LCS_DEAD_SOCKET) },
{ "*", "*", LRS_DEAD_SOCKET, LWS_WSIEV_USER_TOLD, NULL, NULL, XC(LCS_USER_TOLD) },
|