Add websocket ping

This commit is contained in:
2022-08-29 22:45:10 +02:00
parent 2cce1a3dbf
commit 0c0dafbecf

View File

@ -3,6 +3,8 @@
const DNS_RE = /^([a-z0-9_-]+\.)+[a-z]{2,}$/i; const DNS_RE = /^([a-z0-9_-]+\.)+[a-z]{2,}$/i;
const UUID_RE = /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i; const UUID_RE = /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i;
const WEBSOCKET_KEEP_ALIVE = 5 * 60; // [sec]
type DomainJson = { type DomainJson = {
name: string, name: string,
id: string, id: string,
@ -295,6 +297,7 @@ export class Session {
httpBaseUrl: string | null; httpBaseUrl: string | null;
websocket: WebSocket | null; websocket: WebSocket | null;
websocketPingInterval: number | null;
numRequests: number; numRequests: number;
requestNumDiscriminator: number; requestNumDiscriminator: number;
subscriptions: { subscriptions: {
@ -314,6 +317,7 @@ export class Session {
this.token = null; this.token = null;
this.httpBaseUrl = null; this.httpBaseUrl = null;
this.websocket = null; this.websocket = null;
this.websocketPingInterval = null;
this.subscriptions = []; this.subscriptions = [];
this.subscriptionEndpoints = []; this.subscriptionEndpoints = [];
} }
@ -329,13 +333,29 @@ export class Session {
async close(keepEndpoints: boolean = false) { async close(keepEndpoints: boolean = false) {
await this.unsubscribeAll(keepEndpoints); await this.unsubscribeAll(keepEndpoints);
if (this.websocket && (this.websocket.readyState !== WebSocket.CLOSING && this.websocket.readyState !== WebSocket.CLOSED)) { if (this.websocket && (this.websocket.readyState !== WebSocket.CLOSING && this.websocket.readyState !== WebSocket.CLOSED)) {
this.websocket.close(); this.closeWebsocket()
this.subscriptions = []; this.subscriptions = [];
this.websocket = null;
this.server = null; this.server = null;
} }
} }
private setWebsocketNull() {
if (this.websocketPingInterval) clearInterval(this.websocketPingInterval);
this.websocket = null;
this.websocketPingInterval = null;
}
closeWebsocket() {
if (this.websocket) {
this.websocket.close();
this.setWebsocketNull();
}
}
hasWebsocket(): boolean {
return this.websocket !== null;
}
async sleep() { async sleep() {
await this.close(true); await this.close(true);
} }
@ -359,8 +379,11 @@ export class Session {
this.websocket = new WebSocket(`wss://${host}:${protocols.wss}/_usimp/websocket`, ["usimp"]); this.websocket = new WebSocket(`wss://${host}:${protocols.wss}/_usimp/websocket`, ["usimp"]);
this.websocket.addEventListener("error", (error) => { this.websocket.addEventListener("error", (error) => {
console.error(error); console.error(error);
this.websocket = null; this.setWebsocketNull();
}); });
this.websocketPingInterval = setInterval(() => {
if (this.hasWebsocket()) this.send("ping", {})
}, WEBSOCKET_KEEP_ALIVE * 1000);
} }
if ("https" in protocols) { if ("https" in protocols) {
@ -520,10 +543,8 @@ export class Session {
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error);
if (this.websocket !== null) { if (this.hasWebsocket()) this.closeWebsocket();
this.websocket.close();
this.websocket = null;
}
this.httpBaseUrl = null; this.httpBaseUrl = null;
if (this.server !== null) { if (this.server !== null) {
this.domain.invalidServers.push(this.server); this.domain.invalidServers.push(this.server);
@ -539,7 +560,7 @@ export class Session {
const resHttp = await this.send("ping", {}, undefined, true); const resHttp = await this.send("ping", {}, undefined, true);
result.http = resHttp.duration; result.http = resHttp.duration;
if (this.websocket) { if (this.hasWebsocket()) {
const resWs = await this.send("ping", {}); const resWs = await this.send("ping", {});
result.ws = resWs.duration; result.ws = resWs.duration;
} }
@ -575,7 +596,7 @@ export class Session {
} }
private async _subscribe(cb: EventHandler) { private async _subscribe(cb: EventHandler) {
if (this.websocket !== null) { if (this.hasWebsocket()) {
const subscription = await this.send('subscribe', {}, 60_000, false, undefined, (res) => { const subscription = await this.send('subscribe', {}, 60_000, false, undefined, (res) => {
if (res.action === 'push') { if (res.action === 'push') {
if (isEventPushEnvelopeJson(res.data)) { if (isEventPushEnvelopeJson(res.data)) {
@ -621,7 +642,7 @@ export class Session {
} }
private async unsubscribe(requestNr: number | undefined = undefined, abortController: AbortController | undefined = undefined) { private async unsubscribe(requestNr: number | undefined = undefined, abortController: AbortController | undefined = undefined) {
if (this.websocket !== null) { if (this.hasWebsocket()) {
await this.send('unsubscribe', {'request_nr': requestNr}) await this.send('unsubscribe', {'request_nr': requestNr})
} else { } else {
if (abortController) abortController.abort('unsubscribe'); if (abortController) abortController.abort('unsubscribe');