podcast manager
1import WebSocket from 'isomorphic-ws'
2import {format} from 'node:util'
3
4import {normalizeError, normalizeProtocolError} from '#common/errors'
5
6import {preauthHandler} from './handler-preauth'
7import {realmHandler} from './handler-realm'
8import {attachSocket, detachSocket} from './state'
9
10/** when the socket connects, we drive our protocol through handlers */
11export async function socketHandler(ws: WebSocket) {
12 try {
13 const auth = await preauthHandler(ws)
14 try {
15 await attachSocket(auth.realm, auth.identid, ws)
16 await realmHandler(ws, auth)
17 } finally {
18 await detachSocket(auth.realm, auth.identid, ws)
19 }
20 } catch (exc) {
21 const error = normalizeError(exc)
22 const failure = normalizeProtocolError(error)
23
24 if (failure.status >= 500) {
25 console.error('fatal:', error)
26 if (error.cause) console.error('cause:', error.cause)
27 }
28
29 const message = format('Error: %s', failure.message)
30 if (ws.readyState === ws.OPEN) ws.send(message)
31 } finally {
32 if (ws.readyState !== ws.CLOSED) {
33 ws.send(`kthxbye\n`)
34 ws.close()
35 }
36 }
37}