From 876b1813128ec702d3ef1e7b0074a4613e88c332 Mon Sep 17 00:00:00 2001 From: Voxelli <69213593+legendhimself@users.noreply.github.com> Date: Sun, 1 Jan 2023 23:19:20 +0530 Subject: [PATCH] fix(WebSocketShard): Zombie connection fix (#8989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: zombie connection - Fix backport #7626 missing changes - Reverted the pull request #8956 - Removed unref of wsCloseTimeout - We are resuming the connection for zombie instead of starting a new Co-authored-by: DraftMan * refactor: ♻️ Format code and remove useless assignation Co-authored-by: DraftMan --- .../src/client/websocket/WebSocketShard.js | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/packages/discord.js/src/client/websocket/WebSocketShard.js b/packages/discord.js/src/client/websocket/WebSocketShard.js index 1c5d6ec4d294..c41b656360a7 100644 --- a/packages/discord.js/src/client/websocket/WebSocketShard.js +++ b/packages/discord.js/src/client/websocket/WebSocketShard.js @@ -375,7 +375,11 @@ class WebSocketShard extends EventEmitter { // Clearing the WebSocket close timeout as close was emitted. this.setWsCloseTimeout(-1); // If we still have a connection object, clean up its listeners - if (this.connection) this._cleanupConnection(); + if (this.connection) { + this._cleanupConnection(); + // Having this after _cleanupConnection to just clean up the connection and not listen to ws.onclose + this.destroy({ reset: !this.sessionId, emit: false, log: false }); + } this.status = Status.Disconnected; this.emitClose(event); } @@ -404,6 +408,7 @@ class WebSocketShard extends EventEmitter { */ this.emit(WebSocketShardEvents.Close, event); } + /** * Called whenever a packet is received. * @param {Object} packet The received packet @@ -589,9 +594,7 @@ class WebSocketShard extends EventEmitter { // Check if close event was emitted. if (this.closeEmitted) { this.debug( - `[WebSocket] was closed. | WS State: ${ - CONNECTION_STATE[this.connection?.readyState ?? WebSocket.CLOSED] - } | Close Emitted: ${this.closeEmitted}`, + `[WebSocket] was closed. | WS State: ${CONNECTION_STATE[this.connection?.readyState ?? WebSocket.CLOSED]}`, ); // Setting the variable false to check for zombie connections. this.closeEmitted = false; @@ -603,14 +606,14 @@ class WebSocketShard extends EventEmitter { ); // Cleanup connection listeners - if (this.connection) { - this._cleanupConnection(); - } - - this.emitClose(); - // Setting the variable false to check for zombie connections. - this.closeEmitted = false; - }, time).unref(); + if (this.connection) this._cleanupConnection(); + + this.emitClose({ + code: 4009, + reason: 'Session time out.', + wasClean: false, + }); + }, time); } /** @@ -837,25 +840,19 @@ class WebSocketShard extends EventEmitter { } // Emit the destroyed event if needed - if (emit) { - this._emitDestroyed(); - } else if ( - this.connection.readyState === WebSocket.CLOSING || - this.connection.readyState === WebSocket.CLOSED - ) { - this.closeEmitted = false; - this.debug( - `[WebSocket] Adding a WebSocket close timeout to ensure a correct WS reconnect. - Timeout: ${this.manager.client.options.closeTimeout}ms`, - ); - this.setWsCloseTimeout(this.manager.client.options.closeTimeout); - } + if (emit) this._emitDestroyed(); } } else if (emit) { // We requested a destroy, but we had no connection. Emit destroyed this._emitDestroyed(); } + this.debug( + `[WebSocket] Adding a WebSocket close timeout to ensure a correct WS reconnect. + Timeout: ${this.manager.client.options.closeTimeout}ms`, + ); + this.setWsCloseTimeout(this.manager.client.options.closeTimeout); + // Step 2: Null the connection object this.connection = null;