--- a/chat/modules/socket.jsm
+++ b/chat/modules/socket.jsm
@@ -137,16 +137,19 @@ const Socket = {
******************************* Public methods ******************************
*****************************************************************************
*/
// Synchronously open a connection.
connect: function(aHost, aPort, aSecurity, aProxy) {
if (Services.io.offline)
throw Cr.NS_ERROR_FAILURE;
+ // This won't work for Linux due to bug 758848.
+ Services.obs.addObserver(this, "wake_notification", false);
+
this.LOG("Connecting to: " + aHost + ":" + aPort);
this.host = aHost;
this.port = aPort;
this.disconnected = false;
this._pendingData = [];
delete this._stopRequestStatus;
@@ -206,16 +209,19 @@ const Socket = {
if (this._pingTimer) {
clearTimeout(this._pingTimer);
delete this._pingTimer;
delete this._resetPingTimerPending;
}
this.cancelDisconnectTimer();
+ delete this._lastAliveTime;
+ Services.obs.removeObserver(this, "wake_notification");
+
this.disconnected = true;
},
// Listen for a connection on a port.
// XXX take a timeout and then call stopListening
listen: function(port) {
this.LOG("Listening on port " + port);
@@ -277,41 +283,67 @@ const Socket = {
this.transport.securityInfo.QueryInterface(Ci.nsISSLSocketControl).StartTLS();
},
// If using the ping functionality, this should be called whenever a message is
// received (e.g. when it is known the socket is still open). Calling this for
// the first time enables the ping functionality.
resetPingTimer: function() {
// Clearing and setting timeouts is expensive, so we do it at most
- // once per eventloop spin cycle.
+ // once per eventloop spin cycle.
if (this._resetPingTimerPending)
return;
this._resetPingTimerPending = true;
executeSoon(this._delayedResetPingTimer.bind(this));
},
+ kTimeBeforePing: 120000, // 2 min
+ kTimeAfterPingBeforeDisconnect: 30000, // 30 s
_delayedResetPingTimer: function() {
if (!this._resetPingTimerPending)
return;
delete this._resetPingTimerPending;
if (this._pingTimer)
clearTimeout(this._pingTimer);
// Send a ping every 2 minutes if there's no traffic on the socket.
- this._pingTimer = setTimeout(this._sendPing.bind(this), 120000);
+ this._pingTimer = setTimeout(this._sendPing.bind(this), this.kTimeBeforePing);
},
// If using the ping functionality, this should be called when a ping receives
// a response.
cancelDisconnectTimer: function() {
if (!this._disconnectTimer)
return;
clearTimeout(this._disconnectTimer);
delete this._disconnectTimer;
},
+ // Plenty of time may have elapsed if the computer wakes from sleep, so check
+ // if we should reconnect immediately.
+ _lastAliveTime: null,
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic != "wake_notification")
+ return;
+ let elapsedTime = Date.now() - this._lastAliveTime;
+ // If there never was any activity before we went to sleep,
+ // or if we've been waiting for a ping response for over 30s,
+ // or if the last activity on the socket is longer ago than we usually
+ // allow before we timeout,
+ // declare the connection timed out immediately.
+ if (!this._lastAliveTime ||
+ (this._disconnectTimer && elapsedTime > this.kTimeAfterPingBeforeDisconnect) ||
+ elapsedTime > this.kTimeBeforePing + this.kTimeAfterPingBeforeDisconnect)
+ this.onConnectionTimedOut();
+ else if (this._pingTimer) {
+ // If there was a ping timer running when the computer went to sleep,
+ // ping immediately to discover if we are still connected.
+ clearTimeout(this._pingTimer);
+ this._sendPing();
+ }
+ },
+
/*
*****************************************************************************
***************************** Interface methods *****************************
*****************************************************************************
*/
/*
* nsIProtocolProxyCallback methods
*/
@@ -363,16 +395,17 @@ const Socket = {
/*
* nsIStreamListener methods
*/
// onDataAvailable, called by Mozilla's networking code.
// Buffers the data, and parses it into discrete messages.
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
if (this.disconnected)
return;
+ this._lastAliveTime = Date.now();
if (this.binaryMode) {
// Load the data from the stream
this._incomingDataBuffer = this._incomingDataBuffer
.concat(this._binaryInputStream
.readByteArray(aCount));
let size = this._incomingDataBuffer.length;
@@ -606,17 +639,17 @@ const Socket = {
},
_pingTimer: null,
_disconnectTimer: null,
_sendPing: function() {
delete this._pingTimer;
this.sendPing();
this._disconnectTimer = setTimeout(this.onConnectionTimedOut.bind(this),
- 30000);
+ this.kTimeAfterPingBeforeDisconnect);
},
/*
*****************************************************************************
********************* Methods for subtypes to override **********************
*****************************************************************************
*/
LOG: function(aString) { },