Bug 1265914 - Remove Push UDP wake-up. r?dragana
MozReview-Commit-ID: 9uyrp75slCX
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -30,19 +30,19 @@ if (AppConstants.MOZ_B2G) {
"@mozilla.org/power/powermanagerservice;1",
"nsIPowerManagerService");
}
const kPUSHWSDB_DB_NAME = "pushapi";
const kPUSHWSDB_DB_VERSION = 5; // Change this if the IndexedDB format changes
const kPUSHWSDB_STORE_NAME = "pushapi";
-const kUDP_WAKEUP_WS_STATUS_CODE = 4774; // WebSocket Close status code sent
- // by server to signal that it can
- // wake client up using UDP.
+// WebSocket close code sent by the server to indicate that the client should
+// not automatically reconnect.
+const kBACKOFF_WS_STATUS_CODE = 4774;
// Maps ack statuses, unsubscribe reasons, and delivery error reasons to codes
// included in request payloads.
const kACK_STATUS_TO_CODE = {
[Ci.nsIPushErrorReporter.ACK_DELIVERED]: 100,
[Ci.nsIPushErrorReporter.ACK_DECRYPTION_ERROR]: 101,
[Ci.nsIPushErrorReporter.ACK_NOT_DELIVERED]: 102,
};
@@ -282,22 +282,22 @@ this.PushServiceWebSocket = {
_requestTimeoutTimer: null,
_retryFailCount: 0,
/**
* According to the WS spec, servers should immediately close the underlying
* TCP connection after they close a WebSocket. This causes wsOnStop to be
* called with error NS_BASE_STREAM_CLOSED. Since the client has to keep the
* WebSocket up, it should try to reconnect. But if the server closes the
- * WebSocket because it will wake up the client via UDP, then the client
- * shouldn't re-establish the connection. If the server says that it will
- * wake up the client over UDP, this is set to true in wsOnServerClose. It is
+ * WebSocket because it wants the client to back off, then the client
+ * shouldn't re-establish the connection. If the server sends the backoff
+ * close code, this field will be set to true in wsOnServerClose. It is
* checked in wsOnStop.
*/
- _willBeWokenUpByUDP: false,
+ _skipReconnect: false,
/** Indicates whether the server supports Web Push-style message delivery. */
_dataEnabled: false,
/**
* The last time the client sent a ping to the server. If non-zero, keeps the
* request timeout timer active. Reset to zero when the server responds with
* a pong or pending messages.
@@ -336,38 +336,31 @@ this.PushServiceWebSocket = {
// Override the default WebSocket factory function. The returned object
// must be null or satisfy the nsIWebSocketChannel interface. Used by
// the tests to provide a mock WebSocket implementation.
if (options.makeWebSocket) {
this._makeWebSocket = options.makeWebSocket;
}
- // Override the default UDP socket factory function. The returned object
- // must be null or satisfy the nsIUDPSocket interface. Used by the
- // UDP tests.
- if (options.makeUDPSocket) {
- this._makeUDPSocket = options.makeUDPSocket;
- }
-
this._requestTimeout = prefs.get("requestTimeout");
return Promise.resolve();
},
_reconnect: function () {
console.debug("reconnect()");
this._shutdownWS(false);
this._startBackoffTimer();
},
_shutdownWS: function(shouldCancelPending = true) {
console.debug("shutdownWS()");
this._currentState = STATE_SHUT_DOWN;
- this._willBeWokenUpByUDP = false;
+ this._skipReconnect = false;
prefs.ignore("userAgentID", this);
if (this._wsListener) {
this._wsListener._pushService = null;
}
try {
this._ws.close(0, null);
@@ -386,21 +379,16 @@ this.PushServiceWebSocket = {
if (this._notifyRequestQueue) {
this._notifyRequestQueue();
this._notifyRequestQueue = null;
}
},
uninit: function() {
- if (this._udpServer) {
- this._udpServer.close();
- this._udpServer = null;
- }
-
// All pending requests (ideally none) are dropped at this point. We
// shouldn't have any applications performing registration/unregistration
// or receiving notifications.
this._shutdownWS();
if (this._backoffTimer) {
this._backoffTimer.cancel();
}
@@ -409,19 +397,17 @@ this.PushServiceWebSocket = {
}
this._mainPushService = null;
this._dataEnabled = false;
},
/**
- * How retries work: The goal is to ensure websocket is always up on
- * networks not supporting UDP. So the websocket should only be shutdown if
- * onServerClose indicates UDP wakeup. If WS is closed due to socket error,
+ * How retries work: If the WS is closed due to a socket error,
* _startBackoffTimer() is called. The retry timer is started and when
* it times out, beginWSSetup() is called again.
*
* If we are in the middle of a timeout (i.e. waiting), but
* a register/unregister is called, we don't want to wait around anymore.
* _sendRequest will automatically call beginWSSetup(), which will cancel the
* timer. In addition since the state will have changed, even if a pending
* timer event comes in (because the timer fired the event before it was
@@ -993,19 +979,18 @@ this.PushServiceWebSocket = {
*
* If we do not explicitly call ws.close() then statusCode is always
* NS_BASE_STREAM_CLOSED, even on a successful close.
*/
_wsOnStop: function(context, statusCode) {
console.debug("wsOnStop()");
this._releaseWakeLock();
- if (statusCode != Cr.NS_OK &&
- !(statusCode == Cr.NS_BASE_STREAM_CLOSED && this._willBeWokenUpByUDP)) {
- console.debug("wsOnStop: Socket error", statusCode);
+ if (statusCode != Cr.NS_OK && !this._skipReconnect) {
+ console.debug("wsOnStop: Reconnecting after socket error", statusCode);
this._reconnect();
return;
}
this._shutdownWS();
},
_wsOnMessageAvailable: function(context, message) {
@@ -1071,95 +1056,38 @@ this.PushServiceWebSocket = {
},
/**
* The websocket should never be closed. Since we don't call ws.close(),
* _wsOnStop() receives error code NS_BASE_STREAM_CLOSED (see comment in that
* function), which calls reconnect and re-establishes the WebSocket
* connection.
*
- * If the server said it'll use UDP for wakeup, we set _willBeWokenUpByUDP
- * and stop reconnecting in _wsOnStop().
+ * If the server requested that we back off, we won't reconnect until the
+ * next network state change event, or until we need to send a new register
+ * request.
*/
_wsOnServerClose: function(context, aStatusCode, aReason) {
console.debug("wsOnServerClose()", aStatusCode, aReason);
- // Switch over to UDP.
- if (aStatusCode == kUDP_WAKEUP_WS_STATUS_CODE) {
- console.debug("wsOnServerClose: Server closed with promise to wake up");
- this._willBeWokenUpByUDP = true;
- // TODO: there should be no pending requests
+ if (aStatusCode == kBACKOFF_WS_STATUS_CODE) {
+ console.debug("wsOnServerClose: Skipping automatic reconnect");
+ this._skipReconnect = true;
}
},
/**
* Rejects all pending register requests with errors.
*/
_cancelRegisterRequests: function() {
for (let request of this._registerRequests.values()) {
request.reject(new Error("Register request aborted"));
}
this._registerRequests.clear();
},
-
- _makeUDPSocket: function() {
- return Cc["@mozilla.org/network/udp-socket;1"]
- .createInstance(Ci.nsIUDPSocket);
- },
-
- /**
- * This method should be called only if the device is on a mobile network!
- */
- _listenForUDPWakeup: function() {
- console.debug("listenForUDPWakeup()");
-
- if (this._udpServer) {
- console.warn("listenForUDPWakeup: UDP Server already running");
- return;
- }
-
- if (!prefs.get("udp.wakeupEnabled")) {
- console.debug("listenForUDPWakeup: UDP support disabled");
- return;
- }
-
- let socket = this._makeUDPSocket();
- if (!socket) {
- return;
- }
- this._udpServer = socket.QueryInterface(Ci.nsIUDPSocket);
- this._udpServer.init(-1, false, Services.scriptSecurityManager.getSystemPrincipal());
- this._udpServer.asyncListen(this);
- console.debug("listenForUDPWakeup: Listening on", this._udpServer.port);
-
- return this._udpServer.port;
- },
-
- /**
- * Called by UDP Server Socket. As soon as a ping is received via UDP,
- * reconnect the WebSocket and get the actual data.
- */
- onPacketReceived: function(aServ, aMessage) {
- console.debug("onPacketReceived: Recv UDP datagram on port",
- this._udpServer.port);
- this._beginWSSetup();
- },
-
- /**
- * Called by UDP Server Socket if the socket was closed for some reason.
- *
- * If this happens, we reconnect the WebSocket to not miss out on
- * notifications.
- */
- onStopListening: function(aServ, aStatus) {
- console.debug("onStopListening: UDP Server socket was shutdown. Status",
- aStatus);
- this._udpServer = undefined;
- this._beginWSSetup();
- },
};
function PushRecordWebSocket(record) {
PushRecord.call(this, record);
this.channelID = record.channelID;
this.version = record.version;
}
--- a/dom/push/test/xpcshell/head.js
+++ b/dom/push/test/xpcshell/head.js
@@ -135,18 +135,16 @@ function makeStub(target, stubs) {
*/
function setPrefs(prefs = {}) {
let defaultPrefs = Object.assign({
loglevel: 'all',
serverURL: 'wss://push.example.org',
'connection.enabled': true,
userAgentID: '',
enabled: true,
- // Disable UDP wake-up by default.
- 'udp.wakeupEnabled': false,
// Defaults taken from /modules/libpref/init/all.js.
requestTimeout: 10000,
retryBaseInterval: 5000,
pingInterval: 30 * 60 * 1000,
// Misc. defaults.
'http2.maxRetries': 2,
'http2.retryInterval': 500,
'http2.reset_retry_count_after_ms': 60000,
@@ -292,18 +290,17 @@ MockWebSocket.prototype = {
waterfall(
() => this._listener.onMessageAvailable(this._context, msg),
() => this._listener.onAcknowledge(this._context, 0)
);
},
/**
* Closes the server end of the connection, calling onServerClose()
- * followed by onStop(). Used to test abrupt connection termination
- * and UDP wake-up.
+ * followed by onStop(). Used to test abrupt connection termination.
*
* @param {Number} [statusCode] The WebSocket connection close code.
* @param {String} [reason] The connection close reason.
*/
serverClose(statusCode, reason = '') {
if (!isFinite(statusCode)) {
statusCode = WEBSOCKET_CLOSE_GOING_AWAY;
}
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4645,19 +4645,16 @@ pref("dom.push.retryBaseInterval", 5000)
// Interval at which to ping PushServer to check connection status. In
// milliseconds. If no reply is received within requestTimeout, the connection
// is considered closed.
pref("dom.push.pingInterval", 1800000); // 30 minutes
// How long before we timeout
pref("dom.push.requestTimeout", 10000);
-// enable udp wakeup support
-pref("dom.push.udp.wakeupEnabled", false);
-
// WebPush prefs:
pref("dom.push.http2.reset_retry_count_after_ms", 60000);
pref("dom.push.http2.maxRetries", 2);
pref("dom.push.http2.retryInterval", 5000);
// WebNetworkStats
pref("dom.mozNetworkStats.enabled", false);