gecko-dev/dom/voicemail/test/marionette/pdu_builder.js

153 lines
4.3 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let RIL = {};
SpecialPowers.Cu.import("resource://gre/modules/ril_consts.js", RIL);
// Only bring in what we need from ril_worker/RadioInterfaceLayer here. Reusing
// that code turns out to be a nightmare, so there is some code duplication.
let PDUBuilder = {
toHexString: function toHexString(n, length) {
let str = n.toString(16);
if (str.length < length) {
for (let i = 0; i < length - str.length; i++) {
str = "0" + str;
}
}
return str.toUpperCase();
},
writeUint16: function writeUint16(value) {
this.buf += (value & 0xff).toString(16).toUpperCase();
this.buf += ((value >> 8) & 0xff).toString(16).toUpperCase();
},
writeHexOctet: function writeHexOctet(octet) {
this.buf += this.toHexString(octet, 2);
},
writeSwappedNibbleBCD: function writeSwappedNibbleBCD(data) {
data = data.toString();
let zeroCharCode = '0'.charCodeAt(0);
for (let i = 0; i < data.length; i += 2) {
let low = data.charCodeAt(i) - zeroCharCode;
let high;
if (i + 1 < data.length) {
high = data.charCodeAt(i + 1) - zeroCharCode;
} else {
high = 0xF;
}
this.writeHexOctet((high << 4) | low);
}
},
writeStringAsSeptets: function writeStringAsSeptets(message,
paddingBits,
langIndex,
langShiftIndex)
{
const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[langIndex];
const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[langShiftIndex];
let dataBits = paddingBits;
let data = 0;
for (let i = 0; i < message.length; i++) {
let septet = langTable.indexOf(message[i]);
if (septet == RIL.PDU_NL_EXTENDED_ESCAPE) {
continue;
}
if (septet >= 0) {
data |= septet << dataBits;
dataBits += 7;
} else {
septet = langShiftTable.indexOf(message[i]);
if (septet == -1) {
throw new Error(message[i] + " not in 7 bit alphabet "
+ langIndex + ":" + langShiftIndex + "!");
}
if (septet == RIL.PDU_NL_RESERVED_CONTROL) {
continue;
}
data |= RIL.PDU_NL_EXTENDED_ESCAPE << dataBits;
dataBits += 7;
data |= septet << dataBits;
dataBits += 7;
}
for (; dataBits >= 8; dataBits -= 8) {
this.writeHexOctet(data & 0xFF);
data >>>= 8;
}
}
if (dataBits != 0) {
this.writeHexOctet(data & 0xFF);
}
},
buildAddress: function buildAddress(address) {
let addressFormat = RIL.PDU_TOA_ISDN; // 81
if (address[0] == '+') {
addressFormat = RIL.PDU_TOA_INTERNATIONAL | RIL.PDU_TOA_ISDN; // 91
address = address.substring(1);
}
this.buf = "";
this.writeHexOctet(address.length);
this.writeHexOctet(addressFormat);
this.writeSwappedNibbleBCD(address);
return this.buf;
},
// assumes 7 bit encoding
buildUserData: function buildUserData(options) {
let headerLength = 0;
this.buf = "";
if (options.headers) {
for each (let header in options.headers) {
headerLength += 2; // id + length octets
if (header.octets) {
headerLength += header.octets.length;
}
};
}
let encodedBodyLength = options.body.length;
let headerOctets = (headerLength ? headerLength + 1 : 0);
let paddingBits;
let userDataLengthInSeptets;
let headerSeptets = Math.ceil(headerOctets * 8 / 7);
userDataLengthInSeptets = headerSeptets + encodedBodyLength;
paddingBits = headerSeptets * 7 - headerOctets * 8;
this.writeHexOctet(userDataLengthInSeptets);
if (options.headers) {
this.writeHexOctet(headerLength);
for each (let header in options.headers) {
this.writeHexOctet(header.id);
this.writeHexOctet(header.length);
if (header.octets) {
for each (let octet in header.octets) {
this.writeHexOctet(octet);
}
}
}
}
this.writeStringAsSeptets(options.body, paddingBits,
RIL.PDU_NL_IDENTIFIER_DEFAULT,
RIL.PDU_NL_IDENTIFIER_DEFAULT);
return this.buf;
}
};