From 45198bc1e48df71623e3f0f04c1f9376051e10dc Mon Sep 17 00:00:00 2001 From: Vicamo Yang Date: Fri, 16 Mar 2012 17:02:06 -0700 Subject: [PATCH] Bug 712933 - Part 6: Support receiving multipart SMS. r=philikon DONTBUILD because NPTOB --- dom/system/gonk/RadioInterfaceLayer.js | 4 +- dom/system/gonk/ril_worker.js | 96 +++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index dc4695103613..85b0ad8c699d 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -408,13 +408,13 @@ RadioInterfaceLayer.prototype = { handleSmsReceived: function handleSmsReceived(message) { debug("handleSmsReceived: " + JSON.stringify(message)); let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null, - message.body || null, + message.fullBody || null, message.timestamp); let sms = gSmsService.createSmsMessage(id, DOM_SMS_DELIVERY_RECEIVED, message.sender || null, message.receiver || null, - message.body || null, + message.fullBody || null, message.timestamp); Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null); }, diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index f91128f3d5e2..29bfad85f340 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -604,6 +604,13 @@ let RIL = { */ currentDataCalls: {}, + /** + * Hash map for received multipart sms fragments. Messages are hashed with + * its sender address and concatenation reference number. Three additional + * attributes `segmentMaxSeq`, `receivedSegments`, `segments` are inserted. + */ + _receivedSmsSegmentsMap: {}, + /** * Mute or unmute the radio. */ @@ -1378,6 +1385,59 @@ let RIL = { this.muted = Object.getOwnPropertyNames(this.currentCalls).length == 0; }, + /** + * Helper for processing received multipart SMS. + * + * @return null for handled segments, and an object containing full message + * body once all segments are received. + */ + _processReceivedSmsSegment: function _processReceivedSmsSegment(original) { + let hash = original.sender + ":" + original.header.segmentRef; + let seq = original.header.segmentSeq; + + let options = this._receivedSmsSegmentsMap[hash]; + if (!options) { + options = original; + this._receivedSmsSegmentsMap[hash] = options; + + options.segmentMaxSeq = original.header.segmentMaxSeq; + options.receivedSegments = 0; + options.segments = []; + } else if (options.segments[seq]) { + // Duplicated segment? + if (DEBUG) { + debug("Got duplicated segment no." + seq + " of a multipart SMS: " + + JSON.stringify(original)); + } + return null; + } + + options.segments[seq] = original.body; + options.receivedSegments++; + if (options.receivedSegments < options.segmentMaxSeq) { + if (DEBUG) { + debug("Got segment no." + seq + " of a multipart SMS: " + + JSON.stringify(options)); + } + return null; + } + + // Remove from map + delete this._receivedSmsSegmentsMap[hash]; + + // Rebuild full body + options.fullBody = ""; + for (let i = 1; i <= options.segmentMaxSeq; i++) { + options.fullBody += options.segments[i]; + } + + if (DEBUG) { + debug("Got full multipart SMS: " + JSON.stringify(options)); + } + + return options; + }, + _handleChangedCallState: function _handleChangedCallState(changedCall) { let message = {type: "callStateChange", call: {callIndex: changedCall.callIndex, @@ -1955,8 +2015,16 @@ RIL[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length } } - message.type = "sms-received"; - this.sendDOMMessage(message); + if (message.header && (message.header.segmentMaxSeq > 1)) { + message = this._processReceivedSmsSegment(message); + } else { + message.fullBody = message.body; + } + + if (message) { + message.type = "sms-received"; + this.sendDOMMessage(message); + } //TODO: this might be a lie? do we want to wait for the mainthread to // report back? @@ -2413,6 +2481,30 @@ let GsmPDUHelper = { dataAvailable -= 2; switch (id) { + case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: { + let ref = this.readHexOctet(); + let max = this.readHexOctet(); + let seq = this.readHexOctet(); + dataAvailable -= 3; + if (max && seq && (seq <= max)) { + header.segmentRef = ref; + header.segmentMaxSeq = max; + header.segmentSeq = seq; + } + break; + } + case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: { + let ref = (this.readHexOctet() << 8) | this.readHexOctet(); + let max = this.readHexOctet(); + let seq = this.readHexOctet(); + dataAvailable -= 4; + if (max && seq && (seq <= max)) { + header.segmentRef = ref; + header.segmentMaxSeq = max; + header.segmentSeq = seq; + } + break; + } case PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT: let langShiftIndex = this.readHexOctet(); --dataAvailable;