Change:
<!-- Do Not Delete This! featurerequesttemplate --<!-- Please read our Rules of Conduct: --<!-- Please search existing issues to avoid creating duplicates. --<!-- Describe the feature you'd like. --Background: Modern reverse proxies like nginx or cloudflare use timeouts for dormant websocket connections. For nginx this defaults to 60s and for Cloudflare to 100s. In case of Cloudflare, this is not configurable for non-enterpise users. Due to the fixes in , the management connection is now typically being idle for extended periods of time. If the web-socket connection is being terminated by the reverse proxy, even if it can be reestablished immediately, a modal dialog is being shown, which disturbs the user immensely. For reference see In order to support Cloudflare it is essential, that we either implement a keep-alive ping (my proposal would by every 45s by default), or alternatively, make it so an immediate reconnect does not cause any negative consequences for the user.
any insights here?
<!-- AUTHORVERIFICATIONREQUEST --This bug has been fixed in the latest release of ! you can help us out by commenting if things are now working as expected. If things still don't seem right, please ensure you're on version of Insiders (today's or later - you can use in the command palette to check), and leave a comment letting us know what isn't working as expected. Happy Coding!
Version: 1.71.0-insider Commit: Date: 2022-08-26T23:24:52.456Z Browser: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 /verified I do no longer experience regular reconnects every 100 seconds behind cloudflare with the build above.

Discussion:
Disconnect = 5, ReplayRequest = 6, Pause = 7, <del> Resume = 8 </del> <ins> Resume = 8, KeepAlive = 9, </ins> } function protocolMessageTypeToString(messageType: ProtocolMessageType) {

case ProtocolMessageType.ReplayRequest: return 'ReplayRequest'; case ProtocolMessageType.Pause: return 'PauseWriting'; case ProtocolMessageType.Resume: return 'ResumeWriting'; <ins> case ProtocolMessageType.KeepAlive: return 'KeepAlive'; </ins> } }

private _incomingMsgLastTime: number; private _incomingAckTimeout: any | null; <ins> private _keepAliveInterval: any | null; </ins> private _lastReplayRequestTime: number; private _lastSocketTimeoutTime: number;

if (initialChunk) { this._socketReader.acceptChunk(initialChunk); } <ins> // send a message every 5s this._keepAliveInterval = setInterval(() => { this._sendKeepAlive(); }, 5000); </ins> } dispose(): void {

clearTimeout(this._incomingAckTimeout); this._incomingAckTimeout = null; } <ins> if (this._keepAliveInterval) { clearInterval(this._keepAliveInterval); this._keepAliveInterval = null; } </ins> this._socketDisposables = dispose(this._socketDisposables); }

break; } case ProtocolMessageType.Ack: { <del> // nothing to do </del> <ins> // nothing to do, .ack is handled above already </ins> break; } case ProtocolMessageType.Disconnect: {

this._socketWriter.resume(); break; } <ins> case ProtocolMessageType.KeepAlive: { // nothing to do break; } </ins> } }

const msg = new ProtocolMessage(ProtocolMessageType.Ack, 0, this._incomingAckId, getEmptyBuffer()); this._socketWriter.write(msg); } <ins> private _sendKeepAlive(): void { const msg = new ProtocolMessage(ProtocolMessageType.KeepAlive, 0, 0, getEmptyBuffer()); this._socketWriter.write(msg); } </ins> } // (() => {