[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp
new file mode 100644
index 0000000..fccbfbf
--- /dev/null
+++ b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp
@@ -0,0 +1,1624 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string>
+#include <memory>
+#include <iostream>
+#include <list>
+#include <algorithm>
+using namespace std;
+
+#include "BearerData.h"
+#include "UserData.h"
+#include "SmsConstants.h"
+#include "HexDump.h"
+#include "IccUtils.h"
+#include "BitwiseInputStream.h"
+#include "CdmaSmsCbProgramData.h";
+#include "SmsHeader.h"
+#include "GsmAlphabet.h"
+#include "SmsEnvelope.h"
+
+extern "C" {
+ #include <glib.h>
+}
+
+BearerData::BearerData() {
+ // TODO Auto-generated constructor stub
+
+}
+
+BearerData::~BearerData() {
+ // TODO Auto-generated destructor stub
+}
+
+/**
+ * Decodes a CDMA style BCD byte like {@link #gsmBcdByteToInt}, but
+ * opposite nibble format. The least significant BCD digit
+ * is in the least significant nibble and the most significant
+ * is in the most significant nibble.
+ */
+int BearerData::cdmaBcdByteToInt(uint8_t b) {
+ int ret = 0;
+
+ // treat out-of-range BCD values as 0
+ if ((b & 0xf0) <= 0x90) {
+ ret = ((b >> 4) & 0xf) * 10;
+ }
+
+ if ((b & 0x0f) <= 0x09) {
+ ret += (b & 0xf);
+ }
+
+ return ret;
+}
+
+void BearerData::fromByteArray(std::vector<uint8_t> data, struct tm& ts) {
+ // C.S0015-B v2.0, 4.5.4: range is 1996-2095
+ int year = cdmaBcdByteToInt(data[0]);
+ if (year > 99 || year < 0) {
+ ts = {0};
+ return;
+ }
+ ts.tm_year = year /*>= 96 ? year + 1900 : year + 2000*/; //TBD
+ int month = cdmaBcdByteToInt(data[1]);
+ if (month < 1 || month > 12) {
+ ts = {0};
+ return;
+ }
+ ts.tm_mon = month - 1;
+ int day = cdmaBcdByteToInt(data[2]);
+ if (day < 1 || day > 31) {
+ ts = {0};
+ return;
+ }
+ ts.tm_mday = day;
+ int hour = cdmaBcdByteToInt(data[3]);
+ if (hour < 0 || hour > 23) {
+ ts = {0};
+ return;
+ }
+ ts.tm_hour = hour;
+ int minute = cdmaBcdByteToInt(data[4]);
+ if (minute < 0 || minute > 59) {
+ ts = {0};
+ return;
+ }
+ ts.tm_min = minute;
+ int second = cdmaBcdByteToInt(data[5]);
+ if (second < 0 || second > 59) {
+ ts = {0};
+ return;
+ }
+ ts.tm_sec = second;
+}
+
+void BearerData::encodeMessageId(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 3);
+ outStream->write(4, bData->messageType);
+ outStream->write(8, bData->messageId >> 8);
+ outStream->write(8, bData->messageId);
+ outStream->write(1, bData->hasUserDataHeader ? 1 : 0);
+ outStream->skip(3);
+}
+
+uint32_t BearerData::countAsciiSeptets(char* msg, bool force) {
+ string strmsg(msg);
+ int msgLen = strmsg.length();
+ if (force)
+ return msgLen;
+ for (int i = 0; i < msgLen; i++) {
+ if (UserData::charToAscii.find(msg[i]) == UserData::charToAscii.end()) {
+ return -1;
+ }
+ }
+ return msgLen;
+}
+
+std::vector<uint8_t> BearerData::encodeUtf16(std::string msg) {
+ GError *error = NULL;
+ gsize bytes_written = 0;
+ std::vector<uint8_t> data;
+ char *ret = g_convert (msg.c_str(), -1, "UCS-2BE", "UTF-8", NULL, &bytes_written, &error);
+ if (!ret) {
+ if (error) {
+ cout << "failed to convert UTF-8 to UCS-2BE character set: " << (error->code) << error->message << endl;
+ g_error_free (error);
+ }
+ return data;
+ }
+ for (int i = 0; i < bytes_written; i++) {
+ data.push_back(ret[i]);
+ }
+ g_free (ret);
+ return data;
+}
+
+//release byte[]
+std::vector<uint8_t> BearerData::encode7bitAscii(std::string msgs, bool force) {
+ string msg(msgs);
+ shared_ptr<BitwiseOutputStream> outStream = make_shared<BitwiseOutputStream>(
+ msg.length());
+ int msgLen = msg.length();
+ for (int i = 0; i < msgLen; i++) {
+ uint8_t charCode;
+ try {
+ charCode = UserData::charToAscii.at(msg[i]);
+ outStream->write(7, charCode);
+ } catch (const out_of_range &e) {
+ if (force) {
+ outStream->write(7, UserData::UNENCODABLE_7_BIT_CHAR);
+ }
+ //TBD log
+ }
+ }
+ return outStream->toByteVector();
+}
+
+BearerData::Gsm7bitCodingResult BearerData::encode7bitGsm(std::string msg, int septetOffset, bool force) {
+ std::vector<uint8_t> fullData = GsmAlphabet::stringToGsm7BitPacked(msg, septetOffset, !force, 0, 0);
+ Gsm7bitCodingResult result;
+ result.data.insert(result.data.begin(), fullData.begin() + 1, fullData.end());
+ result.septets = fullData[0] & 0x00FF;
+ return result;
+}
+
+void BearerData::encode7bitEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData, bool force) {
+ int udhBytes = udhData.size() + 1; // Add length octet.
+ int udhSeptets = ((udhBytes * 8) + 6) / 7;
+ BearerData::Gsm7bitCodingResult gcr = encode7bitGsm(uData->payloadStr, udhSeptets, force);
+ uData->msgEncoding = UserData::ENCODING_GSM_7BIT_ALPHABET;
+ uData->msgEncodingSet = true;
+ uData->numFields = gcr.septets;
+ uData->payload = gcr.data;
+ uData->payload.insert(uData->payload.begin()+1, udhData.begin(), udhData.end());
+ uData->payload[0] = (uint8_t)udhData.size();
+}
+
+void BearerData::encode16bitEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData) {
+ std::vector<uint8_t> payload = encodeUtf16(uData->payloadStr);
+ int udhBytes = udhData.size() + 1; // Add length octet.
+ int udhCodeUnits = (udhBytes + 1) / 2;
+ int payloadCodeUnits = payload.size() / 2;
+ uData->msgEncoding = UserData::ENCODING_UNICODE_16;
+ uData->msgEncodingSet = true;
+ uData->numFields = udhCodeUnits + payloadCodeUnits;
+ uData->payload.push_back(udhData.size());
+ (uData->payload).insert((uData->payload).begin() + 1, udhData.begin(), udhData.end());
+ (uData->payload).insert((uData->payload).begin() + udhBytes, payload.begin(), payload.end());
+}
+
+void BearerData::encodeOctetEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData) {
+ int udhBytes = udhData.size() + 1;
+ uData->msgEncoding = UserData::ENCODING_OCTET;
+ uData->msgEncodingSet = true;
+ uData->numFields = udhBytes + uData->payload.size();
+ //byte[] payload = new byte[uData.numFields];
+ std::vector<uint8_t> payload;
+ uData->payload.push_back(udhData.size());
+ (uData->payload).insert((uData->payload).begin() + 1, udhData.begin(), udhData.end());
+ (uData->payload).insert((uData->payload).begin() + udhBytes, payload.begin(), payload.end());
+}
+
+void BearerData::encodeEmsUserDataPayload(std::shared_ptr<UserData> uData) {
+ std::vector<uint8_t> headerData = SmsHeader::toByteArray(uData->userDataHeader);
+ if (uData->msgEncodingSet) {
+ if (uData->msgEncoding == UserData::ENCODING_GSM_7BIT_ALPHABET) {
+ encode7bitEms(uData, headerData, true);
+ } else if (uData->msgEncoding == UserData::ENCODING_OCTET) {
+ encodeOctetEms(uData, headerData);
+ } else if (uData->msgEncoding == UserData::ENCODING_UNICODE_16) {
+ encode16bitEms(uData, headerData);
+ } else {
+ cout << "unsupported EMS user data encoding (" << uData->msgEncoding << ")" <<endl;
+ }
+ } else {
+ encode7bitEms(uData, headerData, false);
+ }
+}
+//maybe free memory
+void BearerData::encodeUserDataPayload(std::shared_ptr<UserData> uData) {
+ if ((uData->payloadStr.empty())
+ && (uData->msgEncoding != UserData::ENCODING_OCTET)) {
+ //Rlog.e(LOG_TAG, "user data with null payloadStr");
+ uData->payloadStr = string("");
+ }
+
+ if (uData->userDataHeader != nullptr) {
+ encodeEmsUserDataPayload(uData);
+ return;
+ }
+
+ if (uData->msgEncodingSet) {
+ if (uData->msgEncoding == UserData::ENCODING_OCTET) {
+ if (uData->payload.empty()) {
+ //Rlog.e(LOG_TAG, "user data with octet encoding but null payload");
+ uData->payload.clear();
+ uData->numFields = 0;
+ } else {
+ uData->numFields = uData->payload.size(); //maybe wrong?
+ }
+ } else {
+ if (uData->payloadStr.empty()) {
+ //Rlog.e(LOG_TAG, "non-octet user data with null payloadStr");
+ uData->payloadStr = string("");
+ }
+// if (uData.msgEncoding == UserData::ENCODING_GSM_7BIT_ALPHABET) {
+// Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, 0, true);
+// uData.payload = gcr.data;
+// uData.numFields = gcr.septets;
+// } else
+
+ if (uData->msgEncoding == UserData::ENCODING_7BIT_ASCII) {
+ uData->payload = encode7bitAscii(uData->payloadStr, true);
+ uData->numFields = uData->payloadStr.size();
+ } else if (uData->msgEncoding == UserData::ENCODING_UNICODE_16) {
+ uData->payload = encodeUtf16(uData->payloadStr);
+ uData->numFields = string(uData->payloadStr).length();
+// } else if (uData->msgEncoding == UserData::ENCODING_SHIFT_JIS) {
+// uData->payload = encodeShiftJis(uData->payloadStr);
+// uData->numFields = string(uData->payloadStr).length();
+ } else {
+ cout << "unsupported user data encoding (" << uData->msgEncoding << ")"
+ << endl;
+ }
+ }
+ } else {
+ uData->payload = encode7bitAscii(uData->payloadStr, false);
+ string str1 = HexDump::toHexString(uData->payload);
+ //std::cout << "uData->payload: " << str1 << endl;
+ uData->msgEncoding = UserData::ENCODING_7BIT_ASCII;
+// try {
+// } catch (CodingException ex) {
+// uData.payload = encodeUtf16(uData.payloadStr);
+// uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+// }
+ uData->numFields = uData->payloadStr.size();
+ uData->msgEncodingSet = true;
+ }
+}
+
+void BearerData::encodeUserData(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ /*
+ * TODO(cleanup): Do we really need to set userData.payload as
+ * a side effect of encoding? If not, we could avoid data
+ * copies by passing outStream directly.
+ */
+ encodeUserDataPayload(bData->userData);
+ bData->hasUserDataHeader = false; //bData->userData->userDataHeader != null;
+
+ int length = bData->userData->payload.size();
+ if (length > SmsConstants::MAX_USER_DATA_BYTES) {
+ cout << "encoded user data too large (" << bData->userData->payload.size()
+ << " > " << SmsConstants::MAX_USER_DATA_BYTES << " bytes)" << endl;
+ return;
+ }
+
+ /*
+ * TODO(cleanup): figure out what the right answer is WRT paddingBits field
+ *
+ * userData->pad->ingBits = (userData->payload.length * 8) - (userData.numFields * 7);
+ * userData.paddingBits = 0; // XXX this seems better, but why?
+ *
+ */
+ int dataBits = (length * 8) - (bData->userData->paddingBits);
+ int paramBits = dataBits + 13;
+ if (((bData->userData->msgEncoding)
+ == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+ || ((bData->userData->msgEncoding) == UserData::ENCODING_GSM_DCS)) {
+ paramBits += 8;
+ }
+ int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+ int paddingBits = (paramBytes * 8) - paramBits;
+ outStream->write(8, paramBytes);
+ outStream->write(5, bData->userData->msgEncoding);
+ if ((bData->userData->msgEncoding == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+ || (bData->userData->msgEncoding == UserData::ENCODING_GSM_DCS)) {
+ outStream->write(8, bData->userData->msgType);
+ }
+ outStream->write(8, (bData->userData)->numFields);
+ outStream->writeByteVector(dataBits, (bData->userData)->payload);
+ if (paddingBits > 0)
+ outStream->write(paddingBits, 0);
+}
+
+void BearerData::encodeReplyOption(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(1, bData->userAckReq ? 1 : 0);
+ outStream->write(1, bData->deliveryAckReq ? 1 : 0);
+ outStream->write(1, bData->readAckReq ? 1 : 0);
+ outStream->write(1, bData->reportReq ? 1 : 0);
+ outStream->write(4, 0);
+}
+
+//free memory
+std::vector<uint8_t> BearerData::encodeDtmfSmsAddress(std::string address) {
+ int digits = address.length();
+ int dataBits = digits * 4;
+ int dataBytes = (dataBits / 8);
+ dataBytes += (dataBits % 8) > 0 ? 1 : 0;
+ //uint8_t* rawData = new uint8_t[dataBytes];
+ std::vector<uint8_t> rawData;
+ for (int i = 0; i < digits; i++) {
+ char c = address[i];
+ int val = 0;
+ if ((c >= '1') && (c <= '9'))
+ val = c - '0';
+ else if (c == '0')
+ val = 10;
+ else if (c == '*')
+ val = 11;
+ else if (c == '#')
+ val = 12;
+ else
+ return rawData;
+ int size = rawData.size();
+ if ((i / 2) < size) {
+ rawData[i / 2] |= val << (4 - ((i % 2) * 4));
+ } else {
+ rawData.push_back(val << (4 - ((i % 2) * 4)));
+ }
+ }
+ return rawData;
+}
+
+void BearerData::encodeCdmaSmsAddress(std::shared_ptr<CdmaSmsAddress> addr) {
+ if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+ //TBD
+// try {
+// addr.origBytes = addr.address.getBytes("US-ASCII");
+// } catch (java.io.UnsupportedEncodingException ex) {
+// throw new CodingException("invalid SMS address, cannot convert to ASCII");
+// }
+ } else {
+ addr->origBytes = encodeDtmfSmsAddress(addr->address);
+ }
+}
+
+void BearerData::encodeCallbackNumber(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ auto addr = bData->callbackNumber;
+ encodeCdmaSmsAddress(addr);
+ int paramBits = 9;
+ int dataBits = 0;
+ if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+ paramBits += 7;
+ dataBits = addr->numberOfDigits * 8;
+ } else {
+ dataBits = addr->numberOfDigits * 4;
+ }
+ paramBits += dataBits;
+ int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+ int paddingBits = (paramBytes * 8) - paramBits;
+ outStream->write(8, paramBytes);
+ outStream->write(1, addr->digitMode);
+ if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+ outStream->write(3, addr->ton);
+ outStream->write(4, addr->numberPlan);
+ }
+ outStream->write(8, addr->numberOfDigits);
+ outStream->writeByteVector(dataBits, addr->origBytes);
+ if (paddingBits > 0)
+ outStream->write(paddingBits, 0);
+}
+
+void BearerData::encodeMsgStatus(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(2, bData->errorClass);
+ outStream->write(6, bData->messageStatus);
+}
+void BearerData::encodeMsgCount(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(8, bData->numberOfMessages);
+}
+void BearerData::encodeValidityPeriodRel(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(8, bData->validityPeriodRelative);
+}
+void BearerData::encodePrivacyIndicator(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(2, bData->privacy);
+ outStream->skip(6);
+}
+void BearerData::encodeLanguageIndicator(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(8, bData->language);
+}
+void BearerData::encodeDisplayMode(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(2, bData->displayMode);
+ outStream->skip(6);
+}
+void BearerData::encodePriorityIndicator(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(2, bData->priority);
+ outStream->skip(6);
+}
+void BearerData::encodeMsgDeliveryAlert(BearerData* bData,
+ shared_ptr<BitwiseOutputStream> outStream) {
+ outStream->write(8, 1);
+ outStream->write(2, bData->alert);
+ outStream->skip(6);
+}
+std::vector<uint8_t> BearerData::encode(BearerData* bData) {
+ bData->hasUserDataHeader = false; //((bData->userData != nullptr) && (bData->userData->userDataHeader != null));
+ shared_ptr<BitwiseOutputStream> outStream = make_shared<BitwiseOutputStream>(
+ 200);
+ outStream->write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+ encodeMessageId(bData, outStream);
+ if (bData->userData != nullptr) {
+ outStream->write(8, SUBPARAM_USER_DATA);
+ encodeUserData(bData, outStream);
+ //cout << "userData" << endl;
+ }
+ if (bData->callbackNumber != nullptr) {
+ //cout << "callbackNumber" << endl;
+ outStream->write(8, SUBPARAM_CALLBACK_NUMBER);
+ encodeCallbackNumber(bData, outStream);
+ }
+ if (bData->userAckReq || bData->deliveryAckReq || bData->readAckReq
+ || bData->reportReq) {
+ //cout << "userAckReq" << endl;
+ outStream->write(8, SUBPARAM_REPLY_OPTION);
+ encodeReplyOption(bData, outStream);
+ }
+ if (bData->numberOfMessages != 0) {
+ //cout << "numberOfMessages" << endl;
+ outStream->write(8, SUBPARAM_NUMBER_OF_MESSAGES);
+ encodeMsgCount(bData, outStream);
+ }
+ if (bData->validityPeriodRelativeSet) {
+ //cout << "validityPeriodRelativeSet" << endl;
+ outStream->write(8, SUBPARAM_VALIDITY_PERIOD_RELATIVE);
+ encodeValidityPeriodRel(bData, outStream);
+ }
+ if (bData->privacyIndicatorSet) {
+ //cout << "privacyIndicatorSet" << endl;
+ outStream->write(8, SUBPARAM_PRIVACY_INDICATOR);
+ encodePrivacyIndicator(bData, outStream);
+ }
+ if (bData->languageIndicatorSet) {
+ //cout << "languageIndicatorSet" << endl;
+ outStream->write(8, SUBPARAM_LANGUAGE_INDICATOR);
+ encodeLanguageIndicator(bData, outStream);
+ }
+ if (bData->displayModeSet) {
+ //cout << "displayModeSet" << endl;
+ outStream->write(8, SUBPARAM_MESSAGE_DISPLAY_MODE);
+ encodeDisplayMode(bData, outStream);
+ }
+ if (bData->priorityIndicatorSet) {
+ //cout << "priorityIndicatorSet" << endl;
+ outStream->write(8, SUBPARAM_PRIORITY_INDICATOR);
+ encodePriorityIndicator(bData, outStream);
+ }
+ if (bData->alertIndicatorSet) {
+ //cout << "alertIndicatorSet" << endl;
+ outStream->write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY);
+ encodeMsgDeliveryAlert(bData, outStream);
+ }
+ if (bData->messageStatusSet) {
+ //cout << "messageStatusSet" << endl;
+ outStream->write(8, SUBPARAM_MESSAGE_STATUS);
+ encodeMsgStatus(bData, outStream);
+ }
+// if (bData->serviceCategoryProgramResults != null) {
+// outStream->write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
+// encodeScpResults(bData, outStream);
+// }
+ return outStream->toByteVector();
+}
+
+std::shared_ptr<BearerData> BearerData::decode(std::vector<uint8_t> smsData) {
+ return decode(smsData, 0);
+}
+
+bool BearerData::decodeMessageId(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 3 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->messageType = inStream->read(4);
+ bData->messageId = inStream->read(8) << 8;
+ bData->messageId |= inStream->read(8);
+ bData->hasUserDataHeader = (inStream->read(1) == 1);
+ inStream->skip(3);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+bool BearerData::decodeUserData(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ uint32_t paramBits = inStream->read((uint32_t) 8) * 8;
+ bData->userData = std::make_shared<UserData>();
+ bData->userData->msgEncoding = inStream->read(5);
+ bData->userData->msgEncodingSet = true;
+ bData->userData->msgType = 0;
+ int consumedBits = 5;
+ if ((bData->userData->msgEncoding == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+ || (bData->userData->msgEncoding == UserData::ENCODING_GSM_DCS)) {
+ bData->userData->msgType = inStream->read(8);
+ consumedBits += 8;
+ }
+ bData->userData->numFields = inStream->read(8);
+ consumedBits += 8;
+ int dataBits = paramBits - consumedBits;
+ bData->userData->payload = inStream->readByteVector(dataBits);
+ return true;
+}
+
+bool BearerData::decodeUserResponseCode(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const uint32_t EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ uint32_t paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->userResponseCode = inStream->read(8);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "USER_RESPONSE_CODE decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ bData->userResponseCodeSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeReplyOption(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->userAckReq = (inStream->read(1) == 1);
+ bData->deliveryAckReq = (inStream->read(1) == 1);
+ bData->readAckReq = (inStream->read(1) == 1);
+ bData->reportReq = (inStream->read(1) == 1);
+ inStream->skip(4);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog->d(LOG_TAG, "REPLY_OPTION decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+bool BearerData::decodeMsgCount(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->numberOfMessages = IccUtils::cdmaBcdByteToInt(
+ (uint8_t) inStream->read(8));
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+std::string BearerData::decodeDtmfSmsAddress(std::vector<uint8_t> rawData,
+ int numFields) {
+ /* DTMF 4-bit digit encoding, defined in at
+ * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
+ string strBuf;
+ for (int i = 0; i < numFields; i++) {
+ int val = 0x0F & (rawData[i / 2] >> (4 - ((i % 2) * 4)));
+ if ((val >= 1) && (val <= 9))
+ strBuf.append(to_string(val));
+ else if (val == 10)
+ strBuf.push_back('0');
+ else if (val == 11)
+ strBuf.push_back('*');
+ else if (val == 12)
+ strBuf.push_back('#');
+ else
+ throw runtime_error(
+ "invalid SMS address DTMF code (" + std::to_string(val) + ")");
+ }
+ return strBuf;
+}
+
+void BearerData::decodeSmsAddress(std::shared_ptr<CdmaSmsAddress> addr) {
+ if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+ //android not support
+// try {
+// /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
+// * just 7-bit ASCII encoding, with the MSB being zero. */
+// addr->address = new string(addr->origBytes, addr->origBytes_length);
+// } catch (exception& ex) {
+// throw runtime_error("invalid SMS address ASCII code");
+// }
+ } else {
+ addr->address = decodeDtmfSmsAddress(addr->origBytes, addr->numberOfDigits);
+ }
+}
+bool BearerData::decodeCallbackNumber(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8; //at least
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits < EXPECTED_PARAM_SIZE) {
+ inStream->skip(paramBits);
+ return false;
+ }
+ std::shared_ptr<CdmaSmsAddress> addr = make_shared<CdmaSmsAddress>();
+ addr->digitMode = inStream->read(1);
+ uint8_t fieldBits = 4;
+ uint8_t consumedBits = 1;
+ if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+ addr->ton = inStream->read(3);
+ addr->numberPlan = inStream->read(4);
+ fieldBits = 8;
+ consumedBits += 7;
+ }
+ addr->numberOfDigits = inStream->read(8);
+ consumedBits += 8;
+ int remainingBits = paramBits - consumedBits;
+ int dataBits = addr->numberOfDigits * fieldBits;
+ int paddingBits = remainingBits - dataBits;
+ if (remainingBits < dataBits) {
+ throw runtime_error(
+ string("CALLBACK_NUMBER subparam encoding size error (")
+ + string("remainingBits + ") + std::to_string(remainingBits)
+ + string(", dataBits + ") + std::to_string(dataBits)
+ + string(", paddingBits + ") + std::to_string(paddingBits)
+ + string(")"));
+ }
+ addr->origBytes = inStream->readByteVector(dataBits);
+ inStream->skip(paddingBits);
+ decodeSmsAddress(addr);
+ bData->callbackNumber = addr;
+ return true;
+}
+
+bool BearerData::decodeMsgStatus(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->errorClass = inStream->read(2);
+ bData->messageStatus = inStream->read(6);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "MESSAGE_STATUS decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ bData->messageStatusSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeMsgCenterTimeStamp(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 6 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ fromByteArray(inStream->readByteVector(6 * 8), bData->msgCenterTimeStamp);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+bool BearerData::decodeValidityAbs(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 6 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ fromByteArray(inStream->readByteVector(6 * 8),
+ bData->validityPeriodAbsolute);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+bool BearerData::decodeValidityRel(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ //bData->deferredDeliveryTimeRelative = inStream->read(8);
+ bData->validityPeriodRelative = inStream->read(8);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ //bData->deferredDeliveryTimeRelativeSet = decodeSuccess;
+ bData->validityPeriodRelativeSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeDeferredDeliveryAbs(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 6 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ fromByteArray(inStream->readByteVector(6 * 8),
+ bData->deferredDeliveryTimeAbsolute);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+bool BearerData::decodeDeferredDeliveryRel(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ //bData->validityPeriodRelative = inStream->read(8);
+ bData->deferredDeliveryTimeRelative = inStream->read(8);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ //bData->validityPeriodRelativeSet = decodeSuccess;
+ bData->deferredDeliveryTimeRelativeSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodePrivacyIndicator(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->privacy = inStream->read(2);
+ inStream->skip(6);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "PRIVACY_INDICATOR decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ bData->privacyIndicatorSet = decodeSuccess;
+ return decodeSuccess;
+}
+bool BearerData::decodeLanguageIndicator(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->language = inStream->read(8);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+ /* Rlog.d(LOG_TAG, "LANGUAGE_INDICATOR decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");*/
+ }
+ inStream->skip(paramBits);
+ bData->languageIndicatorSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeDisplayMode(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->displayMode = inStream->read(2);
+ inStream->skip(6);
+ }
+// if ((! decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "DISPLAY_MODE decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+// }
+ inStream->skip(paramBits);
+ bData->displayModeSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodePriorityIndicator(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->priority = inStream->read(2);
+ inStream->skip(6);
+ }
+// if ((! decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "PRIORITY_INDICATOR decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+// }
+ inStream->skip(paramBits);
+ bData->priorityIndicatorSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeMsgDeliveryAlert(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 1 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->alert = inStream->read(2);
+ inStream->skip(6);
+ }
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ")");
+ }
+ inStream->skip(paramBits);
+ bData->alertIndicatorSet = decodeSuccess;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeDepositIndex(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ const int EXPECTED_PARAM_SIZE = 2 * 8;
+ bool decodeSuccess = false;
+ int paramBits = inStream->read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData->depositIndex = (inStream->read(8) << 8) | inStream->read(8);
+ }
+ /* if ((! decodeSuccess) || (paramBits > 0)) {
+ Rlog.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }*/
+ inStream->skip(paramBits);
+ return decodeSuccess;
+}
+
+int BearerData::getBitsForNumFields(int msgEncoding, int numFields) {
+ switch (msgEncoding) {
+ case UserData::ENCODING_OCTET:
+ case UserData::ENCODING_SHIFT_JIS:
+ case UserData::ENCODING_KOREAN:
+ case UserData::ENCODING_LATIN:
+ case UserData::ENCODING_LATIN_HEBREW:
+ return numFields * 8;
+
+ case UserData::ENCODING_IA5:
+ case UserData::ENCODING_7BIT_ASCII:
+ case UserData::ENCODING_GSM_7BIT_ALPHABET:
+ return numFields * 7;
+
+ case UserData::ENCODING_UNICODE_16:
+ return numFields * 16;
+
+ default:
+ throw runtime_error("unsupported message encoding (" + msgEncoding + ')');
+ }
+}
+
+std::string BearerData::decodeUtf8(std::vector<uint8_t> data, int offset, int numFields)
+{
+ std::string str;
+ for (int i = offset; i < (offset + numFields); i++)
+ {
+ str.push_back((char)data[i]);
+ }
+ return str;
+}
+
+std::string BearerData::decodeLatin(std::vector<uint8_t> data, int offset, int numFields)
+{
+ std::string str;
+ for (int i = offset; i < (offset + numFields); i++)
+ {
+ str.push_back(data[i]);
+ }
+ char* text = g_convert (str.c_str(), numFields, "UTF-8", "ISO−8859−1", NULL, NULL, NULL);
+ if(!text) {
+ printf("convert (Latin) result is null\n");
+ return std::string("");
+ }
+ std::string ret(text);
+ g_free(text);
+ return ret;
+}
+
+std::string BearerData::decodeUtf16(std::vector<uint8_t> data, int offset, int numFields)
+{
+ std::string str;
+ for (int i = offset; i < (offset + numFields*2); i++)
+ {
+ str.push_back((char)data[i]);
+ }
+ char* text = g_convert (str.c_str(), numFields*2, "UTF-8", "UCS-2BE", NULL, NULL, NULL);
+ if(!text) {
+ printf("convert (Utf16) result is null\n");
+ return std::string("");
+ }
+ std::string ret(text);
+ g_free(text);
+ text = NULL;
+ return ret;
+}
+
+std::string BearerData::decode7bitAscii(std::vector<uint8_t> data, int offset,
+ int numFields) {
+ int headerSeptets = (offset * 8 + 6) / 7;
+ numFields -= headerSeptets;
+ std::string strBuf;
+ auto inStream = std::make_shared<BitwiseInputStream>(data);
+ int wantedBits = (headerSeptets + numFields) * 7;
+ if (inStream->available() < wantedBits) {
+ throw runtime_error(
+ "insufficient data (wanted " + std::to_string(wantedBits)
+ + " bits, but only have " + std::to_string(inStream->available())
+ + ")");
+ }
+ inStream->skip(headerSeptets * 7);
+ for (int i = 0; i < numFields; i++) {
+ int charCode = inStream->read(7);
+ if ((charCode >= UserData::ASCII_MAP_BASE_INDEX)
+ && (charCode <= UserData::ASCII_MAP_MAX_INDEX)) {
+ strBuf.push_back(
+ UserData::ASCII_MAP[charCode - UserData::ASCII_MAP_BASE_INDEX]);
+ } else if (charCode == UserData::ASCII_NL_INDEX) {
+ strBuf.push_back('\n');
+ } else if (charCode == UserData::ASCII_CR_INDEX) {
+ strBuf.push_back('\r');
+ } else {
+ /* For other charCodes, they are unprintable, and so simply use SPACE. */
+ strBuf.push_back(' ');
+ }
+ }
+ return strBuf;
+}
+
+std::string BearerData::decode7bitGsm(std::vector<uint8_t> data, int offset,
+ int numFields) {
+ // Start reading from the next 7-bit aligned boundary after offset.
+ int offsetBits = offset * 8;
+ int offsetSeptets = (offsetBits + 6) / 7;
+ numFields -= offsetSeptets;
+ int paddingBits = (offsetSeptets * 7) - offsetBits;
+ string result = GsmAlphabet::gsm7BitPackedToString(data, offset, numFields,
+ paddingBits, 0, 0);
+ if (result.empty()) {
+ throw runtime_error("7bit GSM decoding failed");
+ }
+ return result;
+}
+
+std::string BearerData::decodeGsmDcs(std::vector<uint8_t> data, int offset,
+ int numFields, int msgType) {
+ if ((msgType & 0xC0) != 0) {
+ throw runtime_error(
+ "unsupported coding group (" + std::to_string(msgType) + ")");
+ }
+
+ switch ((msgType >> 2) & 0x3) {
+ case UserData::ENCODING_GSM_DCS_7BIT:
+ return decode7bitGsm(data, offset, numFields);
+// case UserData.ENCODING_GSM_DCS_8BIT:
+// return decodeUtf8(data, offset, numFields);
+// case UserData.ENCODING_GSM_DCS_16BIT:
+// return decodeUtf16(data, offset, numFields);
+ default:
+ throw runtime_error(
+ "unsupported user msgType encoding (" + std::to_string(msgType) + ")");
+ }
+}
+
+void BearerData::decodeUserDataPayload(std::shared_ptr<UserData> userData,
+ bool hasUserDataHeader) {
+ int offset = 0;
+ //printf("1st,%s\n",userData->toString().c_str());
+ if (hasUserDataHeader) {
+ int udhLen = userData->payload[0] & 0x00FF;
+ offset += udhLen + 1;
+ /* byte[] headerData = new byte[udhLen];
+ System.arraycopy(userData.payload, 1, headerData, 0, udhLen)*/;
+ std::vector<uint8_t> v;
+ v.insert(v.end(), userData->payload.begin() + 1,
+ userData->payload.begin() + udhLen);
+ userData->userDataHeader = SmsHeader::fromByteArray(v);
+ //for test cdma long sms, SmsHeader::fromByteArray get the sequence number,but it will always be the last sequence,
+ //maybe overwriten by the last sms part. we print here directly as a temporary solution.
+ if(udhLen == 5 && (userData->payload[1] & 0x00FF)==0x00)//0x00 is the concatenated SMS id
+ {
+ printf("udhLen=%d,refNumber=%d,msgCount=%d, seqNumber=%d\n", udhLen,
+ userData->payload[3] & 0x00FF,userData->payload[4] & 0x00FF,userData->payload[5] & 0x00FF);
+ }
+ else{
+ printf("udhLen=%d, not for test format!\n",udhLen);
+ }
+ }
+ //add for long sms test begin
+ //printf("offset: %d\n",offset);
+ //printf("2nd,%s\n",userData->toString().c_str());
+ //add for long sms test end
+ switch (userData->msgEncoding) {
+ case UserData::ENCODING_OCTET: {
+ /*
+ * Octet decoding depends on the carrier service.
+ */
+ bool decodingtypeUTF8 = true;
+
+ // Strip off any padding bytes, meaning any differences between the length of the
+ // array and the target length specified by numFields. This is to avoid any
+ // confusion by code elsewhere that only considers the payload array length.
+ int copyLen = userData->numFields < userData->payload.size() ? userData->numFields : userData->payload.size();
+ std::vector<uint8_t> payload;
+ payload.insert(payload.end(), userData->payload.begin(), userData->payload.begin() + copyLen);
+ userData->payload = payload;
+
+ if (!decodingtypeUTF8) {
+ // There are many devices in the market that send 8bit text sms (latin encoded) as
+ // octet encoded.
+ userData->payloadStr = decodeLatin(userData->payload, offset, userData->numFields);
+ } else {
+ userData->payloadStr = decodeUtf8(userData->payload, offset, userData->numFields);
+ }
+ break;
+ }
+ case UserData::ENCODING_IA5:
+ case UserData::ENCODING_7BIT_ASCII: {
+ userData->payloadStr = decode7bitAscii(userData->payload, offset, userData->numFields);
+ break;
+ case UserData::ENCODING_UNICODE_16:
+ userData->payloadStr = decodeUtf16(userData->payload, offset, userData->numFields);
+ break;
+ }
+ case UserData::ENCODING_GSM_7BIT_ALPHABET: {
+ userData->payloadStr = decode7bitGsm(userData->payload, offset, userData->numFields);
+ break;
+ }
+ case UserData::ENCODING_LATIN:
+ userData->payloadStr = decodeLatin(userData->payload, offset, userData->numFields);
+ break;
+// case UserData::ENCODING_SHIFT_JIS:
+// // userData->payloadStr = decodeShiftJis(userData->payload, offset, userData->numFields);
+// //TBD "unsupported user data encoding"
+// break;
+ case UserData::ENCODING_GSM_DCS: {
+ userData->payloadStr = decodeGsmDcs(userData->payload, offset,
+ userData->numFields, userData->msgType);
+ break;
+ }
+ default:
+ printf("unsupported user data encoding : %\n" ,std::to_string(userData->msgEncoding));
+// throw runtime_error(
+// "unsupported user data encoding ("
+// + std::to_string(userData->msgEncoding) + ")");
+ }
+}
+bool BearerData::decodeServiceCategoryProgramData(
+ std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream) {
+ if (inStream->available() < 13) {
+ throw runtime_error(
+ string("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only ")
+ + std::to_string(inStream->available())
+ + string(" bits available"));
+ }
+
+ int paramBits = inStream->read(8) * 8;
+ int msgEncoding = inStream->read(5);
+ paramBits -= 5;
+
+ if (inStream->available() < paramBits) {
+ throw runtime_error(
+ string("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only ")
+ + std::to_string(inStream->available())
+ + string(" bits available (") + std::to_string(paramBits)
+ + string(" bits expected)"));
+ }
+
+ auto programDataList = make_shared<list<shared_ptr<CdmaSmsCbProgramData>>>();
+ const int CATEGORY_FIELD_MIN_SIZE = 6 * 8;
+ bool decodeSuccess = false;
+ while (paramBits >= CATEGORY_FIELD_MIN_SIZE) {
+ int operation = inStream->read(4);
+ int category = (inStream->read(8) << 8) | inStream->read(8);
+ int language = inStream->read(8);
+ int maxMessages = inStream->read(8);
+ int alertOption = inStream->read(4);
+ int numFields = inStream->read(8);
+ paramBits -= CATEGORY_FIELD_MIN_SIZE;
+
+ int textBits = getBitsForNumFields(msgEncoding, numFields);
+ if (paramBits < textBits) {
+ throw runtime_error(
+ string("category name is ") + std::to_string(textBits)
+ + string(" bits in length,") + string(" but there are only ")
+ + std::to_string(paramBits) + string(" bits available"));
+ }
+
+ auto userData = make_shared<UserData>();
+ userData->msgEncoding = msgEncoding;
+ userData->msgEncodingSet = true;
+ userData->numFields = numFields;
+ userData->payload = inStream->readByteVector(textBits);
+ paramBits -= textBits;
+
+ decodeUserDataPayload(userData, false);
+ string categoryName = userData->payloadStr;
+ auto programData = std::make_shared<CdmaSmsCbProgramData>(operation,
+ category, language, maxMessages, alertOption, categoryName);
+ programDataList->push_back(programData);
+
+ decodeSuccess = true;
+ }
+
+ if ((!decodeSuccess) || (paramBits > 0)) {
+// Rlog.d(LOG_TAG, "SERVICE_CATEGORY_PROGRAM_DATA decode " +
+// (decodeSuccess ? "succeeded" : "failed") +
+// " (extra bits = " + paramBits + ')');
+ }
+
+ inStream->skip(paramBits);
+ bData->serviceCategoryProgramData = programDataList;
+ return decodeSuccess;
+}
+
+bool BearerData::decodeReserved(std::shared_ptr<BearerData> bData,
+ std::shared_ptr<BitwiseInputStream> inStream, int subparamId) {
+ bool decodeSuccess = false;
+ int subparamLen = inStream->read(8); // SUBPARAM_LEN
+ int paramBits = subparamLen * 8;
+ if (paramBits <= inStream->available()) {
+ decodeSuccess = true;
+ inStream->skip(paramBits);
+ }
+// Rlog.d(LOG_TAG, "RESERVED bearer data subparameter " + subparamId + " decode "
+// + (decodeSuccess ? "succeeded" : "failed") + " (param bits = " + paramBits + ")");
+ if (!decodeSuccess) {
+ throw runtime_error(
+ "RESERVED bearer data subparameter " + std::to_string(subparamId)
+ + " had invalid SUBPARAM_LEN " + std::to_string(subparamLen));
+ }
+
+ return decodeSuccess;
+}
+bool BearerData::isCmasAlertCategory(int category) {
+ return category >= SmsEnvelope::SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT
+ && category <= SmsEnvelope::SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE;
+}
+
+int BearerData::serviceCategoryToCmasMessageClass(int serviceCategory) {
+ switch (serviceCategory) {
+ case SmsEnvelope::SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT:
+ return SmsCbCmasInfo::CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
+
+ case SmsEnvelope::SERVICE_CATEGORY_CMAS_EXTREME_THREAT:
+ return SmsCbCmasInfo::CMAS_CLASS_EXTREME_THREAT;
+
+ case SmsEnvelope::SERVICE_CATEGORY_CMAS_SEVERE_THREAT:
+ return SmsCbCmasInfo::CMAS_CLASS_SEVERE_THREAT;
+
+ case SmsEnvelope::SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY:
+ return SmsCbCmasInfo::CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
+
+ case SmsEnvelope::SERVICE_CATEGORY_CMAS_TEST_MESSAGE:
+ return SmsCbCmasInfo::CMAS_CLASS_REQUIRED_MONTHLY_TEST;
+
+ default:
+ return SmsCbCmasInfo::CMAS_CLASS_UNKNOWN;
+ }
+}
+void BearerData::decodeCmasUserData(std::shared_ptr<BearerData> bData,
+ int serviceCategory) {
+ //uint8_t array[bData->userData->payload.size()];
+ //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+ auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+
+ if (inStream->available() < 8) {
+ throw runtime_error("emergency CB with no CMAE_protocol_version");
+ }
+ int protocolVersion = inStream->read(8);
+ if (protocolVersion != 0) {
+ throw runtime_error("unsupported CMAE_protocol_version " + protocolVersion);
+ }
+
+ int messageClass = serviceCategoryToCmasMessageClass(serviceCategory);
+ int category = SmsCbCmasInfo::CMAS_CATEGORY_UNKNOWN;
+ int responseType = SmsCbCmasInfo::CMAS_RESPONSE_TYPE_UNKNOWN;
+ int severity = SmsCbCmasInfo::CMAS_SEVERITY_UNKNOWN;
+ int urgency = SmsCbCmasInfo::CMAS_URGENCY_UNKNOWN;
+ int certainty = SmsCbCmasInfo::CMAS_CERTAINTY_UNKNOWN;
+
+ while (inStream->available() >= 16) {
+ int recordType = inStream->read(8);
+ int recordLen = inStream->read(8);
+ switch (recordType) {
+ case 0: // Type 0 elements (Alert text)
+ {
+ auto alertUserData = make_shared<UserData>();
+ alertUserData->msgEncoding = inStream->read(5);
+ alertUserData->msgEncodingSet = true;
+ alertUserData->msgType = 0;
+
+ int numFields; // number of chars to decode
+ switch (alertUserData->msgEncoding) {
+ case UserData::ENCODING_OCTET:
+ case UserData::ENCODING_LATIN:
+ numFields = recordLen - 1; // subtract 1 byte for encoding
+ break;
+
+ case UserData::ENCODING_IA5:
+ case UserData::ENCODING_7BIT_ASCII:
+ case UserData::ENCODING_GSM_7BIT_ALPHABET:
+ numFields = ((recordLen * 8) - 5) / 7; // subtract 5 bits for encoding
+ break;
+
+ case UserData::ENCODING_UNICODE_16:
+ numFields = (recordLen - 1) / 2;
+ break;
+
+ default:
+ numFields = 0; // unsupported encoding
+ }
+
+ alertUserData->numFields = numFields;
+ alertUserData->payload = inStream->readByteVector(recordLen * 8 - 5);
+ decodeUserDataPayload(alertUserData, false);
+ bData->userData = alertUserData;
+ break;
+ }
+ case 1: // Type 1 elements
+ {
+ category = inStream->read(8);
+ responseType = inStream->read(8);
+ severity = inStream->read(4);
+ urgency = inStream->read(4);
+ certainty = inStream->read(4);
+ inStream->skip(recordLen * 8 - 28);
+ break;
+ }
+ default:
+ //Rlog.w(LOG_TAG, "skipping unsupported CMAS record type " + recordType);
+ inStream->skip(recordLen * 8);
+ break;
+ }
+ }
+
+ bData->cmasWarningInfo = make_shared<SmsCbCmasInfo>(messageClass, category,
+ responseType, severity, urgency, certainty);
+}
+
+void BearerData::decodeIs91VoicemailStatus(std::shared_ptr<BearerData> bData) {
+ //uint8_t array[bData->userData->payload.size()];
+ //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+ auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+
+ int dataLen = inStream->available() / 6; // 6-bit packed character encoding.
+ int numFields = bData->userData->numFields;
+ if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+ throw runtime_error("IS-91 voicemail status decoding failed");
+ }
+ string strbuf;
+ while (inStream->available() >= 6) {
+ strbuf.push_back(UserData::ASCII_MAP[inStream->read(6)]);
+ }
+ string data = strbuf;
+ bData->numberOfMessages = std::stoi(data.substr(0, 2));
+ char prioCode = data.at(2);
+ if (prioCode == ' ') {
+ bData->priority = PRIORITY_NORMAL;
+ } else if (prioCode == '!') {
+ bData->priority = PRIORITY_URGENT;
+ } else {
+ throw runtime_error(
+ string("IS-91 voicemail status decoding failed: ")
+ + string("illegal priority setting (") + std::to_string(prioCode)
+ + string(")"));
+ }
+ bData->priorityIndicatorSet = true;
+ bData->userData->payloadStr = data.substr(3, numFields - 6);
+}
+void BearerData::decodeIs91Cli(std::shared_ptr<BearerData> bData) {
+ //uint8_t array[bData->userData->payload.size()];
+ //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+ auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+ int dataLen = inStream->available() / 4; // 4-bit packed DTMF digit encoding.
+ int numFields = bData->userData->numFields;
+ if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+ throw runtime_error("IS-91 voicemail status decoding failed");
+ }
+ auto addr = make_shared<CdmaSmsAddress>();
+ addr->digitMode = CdmaSmsAddress::DIGIT_MODE_4BIT_DTMF;
+ addr->origBytes = bData->userData->payload;
+ addr->numberOfDigits = (uint8_t) numFields;
+ decodeSmsAddress(addr);
+ bData->callbackNumber = addr;
+}
+
+void BearerData::decodeIs91ShortMessage(std::shared_ptr<BearerData> bData) {
+ //uint8_t array[bData->userData->payload.size()];
+ //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+ auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+ int dataLen = inStream->available() / 6; // 6-bit packed character encoding.
+ int numFields = bData->userData->numFields;
+ // dataLen may be > 14 characters due to octet padding
+ if ((numFields > 14) || (dataLen < numFields)) {
+ throw runtime_error("IS-91 short message decoding failed");
+ }
+ string strbuf;
+ for (int i = 0; i < numFields; i++) {
+ strbuf.push_back(UserData::ASCII_MAP[inStream->read(6)]);
+ }
+ bData->userData->payloadStr = strbuf;
+}
+
+void BearerData::decodeIs91(std::shared_ptr<BearerData> bData) {
+ switch (bData->userData->msgType) {
+ case UserData::IS91_MSG_TYPE_VOICEMAIL_STATUS:
+ decodeIs91VoicemailStatus(bData);
+ break;
+ case UserData::IS91_MSG_TYPE_CLI:
+ decodeIs91Cli(bData);
+ break;
+ case UserData::IS91_MSG_TYPE_SHORT_MESSAGE_FULL:
+ case UserData::IS91_MSG_TYPE_SHORT_MESSAGE:
+ decodeIs91ShortMessage(bData);
+ break;
+ default:
+ throw runtime_error(
+ string("unsupported IS-91 message type (")
+ + std::to_string(bData->userData->msgType) + string(")"));
+ }
+}
+std::shared_ptr<BearerData> BearerData::decode(std::vector<uint8_t> smsData,
+ int serviceCategory) {
+ //uint8_t array[smsData.size()];
+ //std::copy(smsData.begin(), smsData.end(), array);
+ auto inStream = make_shared<BitwiseInputStream>(smsData);
+ shared_ptr<BearerData> bData = make_shared<BearerData>();
+ int foundSubparamMask = 0;
+ while (inStream->available() > 0) {
+ uint32_t subparamId = inStream->read((uint32_t) 8);
+ int subparamIdBit = 1 << subparamId;
+ // int is 4 bytes. This duplicate check has a limit to Id number up to 32 (4*8)
+ // as 32th bit is the max bit in int.
+ // Per 3GPP2 C.S0015-B Table 4.5-1 Bearer Data Subparameter Identifiers:
+ // last defined subparam ID is 23 (00010111 = 0x17 = 23).
+ // Only do duplicate subparam ID check if subparam is within defined value as
+ // reserved subparams are just skipped.
+ if ((foundSubparamMask & subparamIdBit) != 0
+ && (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER
+ && subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+ throw runtime_error(
+ string("illegal duplicate subparameter (")
+ + std::to_string(subparamId) + string(")"));
+ }
+ bool decodeSuccess;
+ switch (subparamId) {
+ case SUBPARAM_MESSAGE_IDENTIFIER:
+ decodeSuccess = decodeMessageId(bData, inStream);
+ break;
+ case SUBPARAM_USER_DATA:
+ decodeSuccess = decodeUserData(bData, inStream);
+ break;
+ case SUBPARAM_USER_RESPONSE_CODE:
+ decodeSuccess = decodeUserResponseCode(bData, inStream);
+ break;
+ case SUBPARAM_REPLY_OPTION:
+ decodeSuccess = decodeReplyOption(bData, inStream);
+ break;
+ case SUBPARAM_NUMBER_OF_MESSAGES:
+ decodeSuccess = decodeMsgCount(bData, inStream);
+ break;
+ case SUBPARAM_CALLBACK_NUMBER:
+ decodeSuccess = decodeCallbackNumber(bData, inStream);
+ break;
+ case SUBPARAM_MESSAGE_STATUS:
+ decodeSuccess = decodeMsgStatus(bData, inStream);
+ break;
+ case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
+ decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream);
+ break;
+ case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE:
+ decodeSuccess = decodeValidityAbs(bData, inStream);
+ break;
+ case SUBPARAM_VALIDITY_PERIOD_RELATIVE:
+ decodeSuccess = decodeValidityRel(bData, inStream);
+ break;
+ case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE:
+ decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream);
+ break;
+ case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE:
+ decodeSuccess = decodeDeferredDeliveryRel(bData, inStream);
+ break;
+ case SUBPARAM_PRIVACY_INDICATOR:
+ decodeSuccess = decodePrivacyIndicator(bData, inStream);
+ break;
+ case SUBPARAM_LANGUAGE_INDICATOR:
+ decodeSuccess = decodeLanguageIndicator(bData, inStream);
+ break;
+ case SUBPARAM_MESSAGE_DISPLAY_MODE:
+ decodeSuccess = decodeDisplayMode(bData, inStream);
+ break;
+ case SUBPARAM_PRIORITY_INDICATOR:
+ decodeSuccess = decodePriorityIndicator(bData, inStream);
+ break;
+ case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
+ decodeSuccess = decodeMsgDeliveryAlert(bData, inStream);
+ break;
+ case SUBPARAM_MESSAGE_DEPOSIT_INDEX:
+ decodeSuccess = decodeDepositIndex(bData, inStream);
+ break;
+ case SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA:
+ decodeSuccess = decodeServiceCategoryProgramData(bData, inStream);
+ break;
+ default:
+ decodeSuccess = decodeReserved(bData, inStream, subparamId);
+ }
+ if (decodeSuccess
+ && (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER
+ && subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+ foundSubparamMask |= subparamIdBit;
+ }
+ }
+ if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
+ throw runtime_error("missing MESSAGE_IDENTIFIER subparam");
+ }
+ if (bData->userData != nullptr) {
+ if (isCmasAlertCategory(serviceCategory)) {
+ decodeCmasUserData(bData, serviceCategory);
+ } else if (bData->userData->msgEncoding
+ == UserData::ENCODING_IS91_EXTENDED_PROTOCOL) {
+ if ((foundSubparamMask ^ (1 << SUBPARAM_MESSAGE_IDENTIFIER)
+ ^ (1 << SUBPARAM_USER_DATA)) != 0) {
+// Rlog.e(LOG_TAG, "IS-91 must occur without extra subparams (" +
+// foundSubparamMask + ")");
+ }
+ decodeIs91(bData);
+ } else {
+ decodeUserDataPayload(bData->userData, bData->hasUserDataHeader);
+ }
+ }
+ return bData;
+}
+
+std::string BearerData::toString() {
+ string builder;
+ builder.append("BearerData ");
+ builder.append("{ messageType=" + std::to_string(messageType));
+ builder.append(", messageId=" + std::to_string(messageId));
+ builder.append(
+ string(", priority=")
+ + (priorityIndicatorSet ? std::to_string(priority) : "unset"));
+ builder.append(
+ string(", privacy=")
+ + (privacyIndicatorSet ? std::to_string(privacy) : "unset"));
+ builder.append(
+ string(", alert=")
+ + (alertIndicatorSet ? std::to_string(alert) : "unset"));
+ builder.append(
+ string(", displayMode=")
+ + (displayModeSet ? std::to_string(displayMode) : "unset"));
+ builder.append(
+ string(", language=")
+ + (languageIndicatorSet ? std::to_string(language) : "unset"));
+ builder.append(
+ string(", errorClass=")
+ + (messageStatusSet ? std::to_string(errorClass) : "unset"));
+ builder.append(
+ string(", msgStatus=")
+ + (messageStatusSet ? std::to_string(messageStatus) : "unset"));
+ builder.append(
+ string(
+ ", msgCenterTimeStamp= unset") /*+ string (std::asctime(&msgCenterTimeStamp))*/);
+ builder.append(
+ string(
+ ", validityPeriodAbsolute= unset")/* + string(std::asctime(&validityPeriodAbsolute)))*/);
+ builder.append(
+ string(", validityPeriodRelative= ")
+ + ((validityPeriodRelativeSet) ?
+ std::to_string(validityPeriodRelative) : "unset"));
+ builder.append(
+ string(
+ ", deferredDeliveryTimeAbsolute= ") /*+ string(std::asctime(&deferredDeliveryTimeAbsolute))*/);
+ builder.append(
+ string(", deferredDeliveryTimeRelative=")
+ + ((deferredDeliveryTimeRelativeSet) ?
+ std::to_string(deferredDeliveryTimeRelative) : "unset"));
+ builder.append(", userAckReq=" + std::to_string(userAckReq));
+ builder.append(", deliveryAckReq=" + std::to_string(deliveryAckReq));
+ builder.append(", readAckReq=" + std::to_string(readAckReq));
+ builder.append(", reportReq=" + std::to_string(reportReq));
+ builder.append(", numberOfMessages=" + std::to_string(numberOfMessages));
+ builder.append(string(", callbackNumber=") + string(callbackNumber ? callbackNumber->toString() : "unset"));
+ builder.append(", depositIndex=" + std::to_string(depositIndex));
+ builder.append(", hasUserDataHeader=" + std::to_string(hasUserDataHeader));
+ builder.append(
+ ", userData=" + string(userData ? userData->toString() : "unset"));
+ builder.append(" }");
+ return builder;
+}