The v0.20.0 Rust rewrite dropped two keepalive mechanisms that the
Node.js/Playwright daemon provided, causing CDP connections to remote
Browserless instances to silently die between commands when traversing
multi-hop proxy topologies (Istio Envoy, OpenResty, etc.).
Restore parity with v0.19.0 and improve on it:
1. TCP SO_KEEPALIVE (v0.19.0 parity): Playwright's WebSocketTransport
used HTTP agents with keepAlive: true, which set SO_KEEPALIVE on the
underlying TCP socket. Restored via socket2::SockRef on the
tokio_tungstenite stream before splitting.
2. WebSocket Ping frames (improvement): Send Ping frames every 30s on
idle connections. This goes beyond v0.19.0 because L7 proxies (Envoy,
nginx, OpenResty) can see WebSocket pings but not TCP keepalive
probes, making this effective through application-layer proxy hops.
The keepalive task is coordinated with the reader loop via a watch
channel and stops automatically when the connection closes.
Fixes#934
Co-authored-by: ctate <366502+ctate@users.noreply.github.com>