commit 4100963928c13ffe66e78a4eed689b21ba018a2c Author: Cecylia Bocovich cohosh@torproject.org Date: Thu May 7 13:22:20 2020 -0400
Close stale connection
If we stop getting keep-alive pings for some timeout period, close the stale connection. This solves bug #31278 where chrome proxies hang open on an idle connection. --- config.js | 3 +++ proxypair.js | 21 +++++++++++++++++++-- snowflake.js | 2 +- spec/proxypair.spec.js | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/config.js b/config.js index 3f632ca..8c67532 100644 --- a/config.js +++ b/config.js @@ -31,6 +31,9 @@ Config.prototype.pollAdjustment = 300.0 * 1000; // Timeout after sending answer before datachannel is opened Config.prototype.datachannelTimeout = 20 * 1000;
+// Timeout to close proxypair if no messages are sent +Config.prototype.messageTimeout = 30 * 1000; + Config.prototype.maxNumClients = 1;
Config.prototype.proxyType = ""; diff --git a/proxypair.js b/proxypair.js index afcacb1..1153ee3 100644 --- a/proxypair.js +++ b/proxypair.js @@ -16,7 +16,7 @@ class ProxyPair { - @relayAddr is the destination relay - @rateLimit specifies a rate limit on traffic */ - constructor(relayAddr, rateLimit, pcConfig) { + constructor(relayAddr, rateLimit, config) { this.prepareDataChannel = this.prepareDataChannel.bind(this); this.connectRelay = this.connectRelay.bind(this); this.onClientToRelayMessage = this.onClientToRelayMessage.bind(this); @@ -26,7 +26,8 @@ class ProxyPair {
this.relayAddr = relayAddr; this.rateLimit = rateLimit; - this.pcConfig = pcConfig; + this.config = config; + this.pcConfig = config.pcConfig; this.id = Util.genSnowflakeID(); this.c2rSchedule = []; this.r2cSchedule = []; @@ -148,8 +149,19 @@ class ProxyPair {
// WebRTC --> websocket onClientToRelayMessage(msg) { + if (this.messageTimer) { + clearTimeout(this.messageTimer); + } dbg('WebRTC --> websocket data: ' + msg.data.byteLength + ' bytes'); this.c2rSchedule.push(msg.data); + + // if we don't receive any keep-alive messages from the client, close the + // connection + this.messageTimer = setTimeout((() => { + console.log("Closing stale connection."); + this.flush() + this.close() + }), this.config.messageTimeout); return this.flush(); }
@@ -173,6 +185,10 @@ class ProxyPair { clearTimeout(this.timer); this.timer = 0; } + if (this.messageTimer) { + clearTimeout(this.messageTimer); + this.messageTimer = 0; + } if (this.webrtcIsReady()) { this.client.close(); } @@ -244,6 +260,7 @@ ProxyPair.prototype.client = null; // WebRTC Data channel ProxyPair.prototype.relay = null; // websocket
ProxyPair.prototype.timer = 0; +ProxyPair.prototype.messageTimer = 0; ProxyPair.prototype.flush_timeout_id = null;
ProxyPair.prototype.onCleanup = null; diff --git a/snowflake.js b/snowflake.js index be475ec..1021c78 100644 --- a/snowflake.js +++ b/snowflake.js @@ -134,7 +134,7 @@ class Snowflake { return null; } var pair; - pair = new ProxyPair(this.relayAddr, this.rateLimit, this.config.pcConfig); + pair = new ProxyPair(this.relayAddr, this.rateLimit, this.config); this.proxyPairs.push(pair);
log('Snowflake IDs: ' + (this.proxyPairs.map(function(p) { diff --git a/spec/proxypair.spec.js b/spec/proxypair.spec.js index f15d6d2..992b4c1 100644 --- a/spec/proxypair.spec.js +++ b/spec/proxypair.spec.js @@ -43,7 +43,7 @@ describe('ProxyPair', function() { destination = [];
// Using the mock PeerConnection definition from spec/snowflake.spec.js - var pp = new ProxyPair(fakeRelay, rateLimit, config.pcConfig); + var pp = new ProxyPair(fakeRelay, rateLimit, config);
beforeEach(function() { return pp.begin();
tor-commits@lists.torproject.org