WebSocketConnection
Adapts any Ktor DefaultWebSocketSession into a kuilt Connection — byte-transparent binary framing, single-collection incoming, idempotent close.
Works for both the client path (io.ktor.client.plugins.websocket.DefaultClientWebSocketSession) and the server path (io.ktor.server.websocket.DefaultWebSocketServerSession) — both extend DefaultWebSocketSession.
Primary use — in-process client spoke for testApplication tests. Open a client WebSocket session and wrap it into a kuilt Connection to build a spoke that handshakes against a KtorConnectionSource-mounted hub route:
testApplication {
val source = KtorConnectionSource(application, "/hub")
val client = createClient { install(WebSockets) }
client.webSocket("/hub") {
val clientSeam = meshSeam(PeerId("client"), listOf(WebSocketConnection(this)), dispatcher)
// clientSeam.peers now contains the hub's PeerId
}
}Wire format: byte-transparent. Each binary WebSocket frame's payload is the whole message, delivered verbatim; no framing prefix, no in-band handshake. A non-binary application frame is a protocol error and completes incoming exceptionally, which tears the seam down.
incoming: the session's binary frames, mapped to ByteArray. Single-collection (the seam collects it exactly once). Close/EOF/error end the channel, completing the flow so the seam transitions to Torn.
close: closes the underlying session. Idempotent — Ktor's io.ktor.websocket.close is a no-op once the session is already closing.