diff --git a/dom/mms/src/Makefile.in b/dom/mms/src/Makefile.in index 6ad0076836da..7c00c5521eca 100644 --- a/dom/mms/src/Makefile.in +++ b/dom/mms/src/Makefile.in @@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk ifdef MOZ_B2G_RIL EXTRA_JS_MODULES = \ ril/wap_consts.js \ + ril/WapPushManager.js \ ril/WspPduHelper.jsm \ $(NULL) endif diff --git a/dom/mms/src/ril/WapPushManager.js b/dom/mms/src/ril/WapPushManager.js new file mode 100644 index 000000000000..70d1afd277c6 --- /dev/null +++ b/dom/mms/src/ril/WapPushManager.js @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.import("resource://gre/modules/WspPduHelper.jsm"); + +const DEBUG = false; // set to true to see debug messages + +/** + * Helpers for WAP PDU processing. + */ +let WapPushManager = { + + /** + * Parse raw PDU data and deliver to a proper target. + * + * @param data + * A wrapped object containing raw PDU data. + * @param options + * Extra context for decoding. + */ + processMessage: function processMessage(data, options) { + try { + PduHelper.parse(data, true, options); + debug("options: " + JSON.stringify(options)); + } catch (ex) { + debug("Failed to parse sessionless WSP PDU: " + ex.message); + return; + } + + let appid = options.headers["x-wap-application-id"]; + if (!appid) { + debug("Push message doesn't contains X-Wap-Application-Id."); + return; + } + + // FIXME: hand over to others + + debug("No WAP Push application registered for " + appid); + }, + + /** + * @param array + * A Uint8Array or an octet array representing raw PDU data. + * @param length + * Length of the array. + * @param offset + * Offset of the array that a raw PDU data begins. + * @param options + * WDP bearer information. + */ + receiveWdpPDU: function receiveWdpPDU(array, length, offset, options) { + if ((options.bearer == null) || !options.sourceAddress + || (options.sourcePort == null) || !array) { + debug("Incomplete WDP PDU"); + return; + } + + if (options.destinationPort != WDP_PORT_PUSH) { + debug("Not WAP Push port: " + options.destinationPort); + return; + } + + this.processMessage({array: array, offset: offset}, options); + }, +}; + +let debug; +if (DEBUG) { + debug = function (s) { + dump("-*- WapPushManager: " + s + "\n"); + }; +} else { + debug = function (s) {}; +} + +const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([ + "WapPushManager", +]); + diff --git a/dom/mms/src/ril/wap_consts.js b/dom/mms/src/ril/wap_consts.js index be92a8d13eca..322d0f370e5b 100644 --- a/dom/mms/src/ril/wap_consts.js +++ b/dom/mms/src/ril/wap_consts.js @@ -8,6 +8,14 @@ // @see WAP-230-WSP-20010705-a Appendix A. Assigned Numbers. const WSP_PDU_TYPE_PUSH = 0x06; +// Registered WDP Port Numbers +// @see WAP-259-WDP-20010614-a Appendix B. Port Number Definitions. +const WDP_PORT_PUSH = 2948; + +// Bearer Type Assignments +// @see WAP-259-WDP-20010614-a Appendix C. Network Bearer Table. +const WDP_BEARER_GSM_SMS_GSM_MSISDN = 0x03; + const ALL_CONST_SYMBOLS = Object.keys(this); const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS; diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 313839336e3a..a1878c5143c1 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -70,6 +70,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService", "@mozilla.org/settingsService;1", "nsISettingsService"); +XPCOMUtils.defineLazyGetter(this, "WAP", function () { + let WAP = {}; + Cu.import("resource://gre/modules/WapPushManager.js", WAP); + return WAP; +}); + function convertRILCallState(state) { switch (state) { case RIL.CALL_STATE_ACTIVE: @@ -173,7 +179,9 @@ function RadioInterfaceLayer() { Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); this._sentSmsEnvelopes = {}; + this.portAddressedSmsApps = {}; + this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this); } RadioInterfaceLayer.prototype = { @@ -583,10 +591,39 @@ RadioInterfaceLayer.prototype = { ppmm.sendAsyncMessage("RIL:CallError", message); }, + /** + * Handle WDP port push PDU. Constructor WDP bearer information and deliver + * to WapPushManager. + * + * @param message + * A SMS message. + */ + handleSmsWdpPortPush: function handleSmsWdpPortPush(message) { + if (message.encoding != RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) { + debug("Got port addressed SMS but not encoded in 8-bit alphabet. Drop!"); + return; + } + + let options = { + bearer: WAP.WDP_BEARER_GSM_SMS_GSM_MSISDN, + sourceAddress: message.sender, + sourcePort: message.header.originatorPort, + destinationAddress: this.radioState.icc.MSISDN, + destinationPort: message.header.destinationPort, + }; + WAP.WapPushManager.receiveWdpPDU(message.fullData, message.fullData.length, + 0, options); + }, + portAddressedSmsApps: null, handleSmsReceived: function handleSmsReceived(message) { debug("handleSmsReceived: " + JSON.stringify(message)); + // FIXME: Bug 737202 - Typed arrays become normal arrays when sent to/from workers + if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) { + message.fullData = new Uint8Array(message.fullData); + } + // Dispatch to registered handler if application port addressing is // available. Note that the destination port can possibly be zero when // representing a UDP/TCP port.