	/*
	 * 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) },

