diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2022-01-06 17:41:16 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-06 17:41:16 +0100 |
commit | 2067820714fea49be1692fa678754488ace8228b (patch) | |
tree | 2decf412d953016a5b4853e77b04f94466a588dc /ext/websocket/01_websocket.js | |
parent | 46f2ff120587cd1cb7b11e66d41ad6ad46fb09a8 (diff) |
feat(ext/websocket): server automatically handle ping/pong for incoming WebSocket (#13172)
Diffstat (limited to 'ext/websocket/01_websocket.js')
-rw-r--r-- | ext/websocket/01_websocket.js | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/ext/websocket/01_websocket.js b/ext/websocket/01_websocket.js index e11a2c55f..46cb58441 100644 --- a/ext/websocket/01_websocket.js +++ b/ext/websocket/01_websocket.js @@ -69,7 +69,11 @@ const _binaryType = Symbol("[[binaryType]]"); const _bufferedAmount = Symbol("[[bufferedAmount]]"); const _eventLoop = Symbol("[[eventLoop]]"); + const _server = Symbol("[[server]]"); + const _idleTimeoutDuration = Symbol("[[idleTimeout]]"); + const _idleTimeoutTimeout = Symbol("[[idleTimeoutTimeout]]"); + const _serverHandleIdleTimeout = Symbol("[[serverHandleIdleTimeout]]"); class WebSocket extends EventTarget { [_rid]; @@ -388,6 +392,7 @@ switch (kind) { case "string": { + this[_serverHandleIdleTimeout](); const event = new MessageEvent("message", { data: value, origin: this[_url], @@ -396,6 +401,7 @@ break; } case "binary": { + this[_serverHandleIdleTimeout](); let data; if (this.binaryType === "blob") { @@ -417,9 +423,14 @@ }); break; } + case "pong": { + this[_serverHandleIdleTimeout](); + break; + } case "closed": case "close": { this[_readyState] = CLOSED; + clearTimeout(this[_idleTimeoutTimeout]); const event = new CloseEvent("close", { wasClean: true, @@ -446,6 +457,40 @@ } } } + + [_serverHandleIdleTimeout]() { + if (this[_idleTimeoutDuration]) { + clearTimeout(this[_idleTimeoutTimeout]); + this[_idleTimeoutTimeout] = setTimeout(async () => { + await core.opAsync("op_ws_send", this[_rid], { + kind: "ping", + }); + this[_idleTimeoutTimeout] = setTimeout(async () => { + this[_readyState] = CLOSING; + const reason = "No response from ping frame."; + await core.opAsync("op_ws_close", { + rid: this[_rid], + code: 1001, + reason, + }); + this[_readyState] = CLOSED; + + const errEvent = new ErrorEvent("error", { + message: reason, + }); + this.dispatchEvent(errEvent); + + const event = new CloseEvent("close", { + wasClean: false, + code: 1001, + reason, + }); + this.dispatchEvent(event); + core.tryClose(this[_rid]); + }, (this[_idleTimeoutDuration] / 2) * 1000); + }, (this[_idleTimeoutDuration] / 2) * 1000); + } + } } ObjectDefineProperties(WebSocket, { @@ -477,5 +522,8 @@ _eventLoop, _protocol, _server, + _idleTimeoutDuration, + _idleTimeoutTimeout, + _serverHandleIdleTimeout, }; })(this); |