summaryrefslogtreecommitdiff
path: root/ext/websocket
diff options
context:
space:
mode:
Diffstat (limited to 'ext/websocket')
-rw-r--r--ext/websocket/01_websocket.js48
-rw-r--r--ext/websocket/lib.rs2
2 files changed, 50 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);
diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs
index 544423066..3e245afbd 100644
--- a/ext/websocket/lib.rs
+++ b/ext/websocket/lib.rs
@@ -376,6 +376,7 @@ pub enum SendValue {
Text(String),
Binary(ZeroCopyBuf),
Pong,
+ Ping,
}
pub async fn op_ws_send(
@@ -387,6 +388,7 @@ pub async fn op_ws_send(
SendValue::Text(text) => Message::Text(text),
SendValue::Binary(buf) => Message::Binary(buf.to_vec()),
SendValue::Pong => Message::Pong(vec![]),
+ SendValue::Ping => Message::Ping(vec![]),
};
let resource = state