add ping/pong between client and server

the purpose of this is to hopefully prevent nginx from reaping the connection, since there's data flowing through it every so often
This commit is contained in:
liquidex 2024-09-02 23:17:00 +02:00
parent b3911b7af1
commit bf4d538651
3 changed files with 36 additions and 0 deletions

View file

@ -300,6 +300,10 @@ impl SessionLoop {
async fn process_request(&mut self, ws: &mut WebSocket, request: Request) -> eyre::Result<()> { async fn process_request(&mut self, ws: &mut WebSocket, request: Request) -> eyre::Result<()> {
match request { match request {
Request::Ping => {
ws.send(to_message(&Notify::Pong)).await?;
}
Request::Wall { wall_event } => { Request::Wall { wall_event } => {
match &wall_event { match &wall_event {
// This match only concerns itself with drawing-related events to offload // This match only concerns itself with drawing-related events to offload

View file

@ -69,6 +69,8 @@ pub enum LoginResponse {
rename_all_fields = "camelCase" rename_all_fields = "camelCase"
)] )]
pub enum Request { pub enum Request {
Ping,
Wall { Wall {
wall_event: wall::EventKind, wall_event: wall::EventKind,
}, },
@ -95,6 +97,8 @@ pub struct ChunkInfo {
rename_all_fields = "camelCase" rename_all_fields = "camelCase"
)] )]
pub enum Notify { pub enum Notify {
Pong,
Wall { Wall {
wall_event: wall::Event, wall_event: wall::Event,
}, },

View file

@ -75,6 +75,8 @@ export async function registerUser(nickname) {
} }
class Session extends EventTarget { class Session extends EventTarget {
#sentPing = false;
constructor(userId, secret) { constructor(userId, secret) {
super(); super();
this.userId = userId; this.userId = userId;
@ -193,6 +195,8 @@ class Session extends EventTarget {
} }
async eventLoop() { async eventLoop() {
this.#pingLoop();
try { try {
while (true) { while (true) {
let event = await listen([this.ws, "message"]); let event = await listen([this.ws, "message"]);
@ -207,7 +211,21 @@ class Session extends EventTarget {
} }
} }
#pingLoop() {
// Send small ping packets every 30 seconds to prevent reverse proxies from reaping the
// connection if the tab is in the background.
// (Browsers don't seem to send standard WebSocket pings if the tab is unfocused.)
// We don't actually use this packet for anything else, like establishing whether
// we still have a connection to the server, because the browser can handle that for us.
setInterval(() => this.sendPing(), 30000);
}
async #processNotify(notify) { async #processNotify(notify) {
if (notify.notify == "pong") {
console.debug("pong received");
this.#sentPing = false;
}
if (notify.notify == "wall") { if (notify.notify == "wall") {
this.dispatchEvent( this.dispatchEvent(
Object.assign(new Event("wallEvent"), { Object.assign(new Event("wallEvent"), {
@ -229,6 +247,16 @@ class Session extends EventTarget {
} }
} }
sendPing() {
if (!this.#sentPing) {
console.debug("ping sent; waiting for pong");
this.#sendJson({
request: "ping",
});
this.#sentPing = true;
}
}
sendCursor(x, y) { sendCursor(x, y) {
this.#sendJson({ this.#sendJson({
request: "wall", request: "wall",