pub async fn websocket_handler<S>(
stream: S,
peer: SocketAddr,
services: Arc<HashMap<String, Arc<dyn Service>>>,
service_name: &str,
service_vers: &str,
) -> Result<(), Box<dyn Error>>Expand description
Handles a single WebSocket connection end-to-end.
The connection has already passed the dual-mode (TLS vs plain) detection
in start_local_server, so stream is the appropriate concrete stream
type. We wrap it in crate::prelude::BoxedStream and run the WS
handshake with [tokio_tungstenite::accept_hdr_async] so we can:
- Validate the
Originheader againstsharing::PNA_ALLOWED_ORIGINS(with wildcard subdomain / wildcard port matching). Disallowed origins get HTTP 403. - Inject
Access-Control-Allow-Private-Network: trueinto the 101 Switching Protocols response so Chrome’s PNA check passes.
After the handshake we read frames, serde_json-parse them, and
dispatch to process_request which routes by the TARGET field.
Note: Chrome does not send an OPTIONS preflight before a WebSocket upgrade for PNA — the PNA check happens inside the WS handshake itself. So we do not have a separate OPTIONS path.