rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2008 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | #include <memory> |
| 17 | #include <iostream> |
| 18 | #include <numeric> |
| 19 | using namespace std; |
| 20 | |
| 21 | #include <log/log.h> |
| 22 | |
| 23 | #include "SmsMessage.h" |
| 24 | #include "BearerData.h" |
| 25 | #include "HexDump.h"; |
| 26 | |
| 27 | #undef LOG_TAG |
| 28 | #define LOG_TAG "DEMO_CDMA_SMS" |
| 29 | |
| 30 | uint32_t SmsMessage::mPos = 0; |
| 31 | SmsMessage::SmsMessage(std::shared_ptr<SmsAddress> addr,std::shared_ptr<SmsEnvelope> env) { |
| 32 | mOriginatingAddress = addr; |
| 33 | mEnvelope = env; |
| 34 | createPdu(); |
| 35 | } |
| 36 | |
| 37 | SmsMessage::SmsMessage() { |
| 38 | // TODO Auto-generated constructor stub |
| 39 | |
| 40 | } |
| 41 | |
| 42 | SmsMessage::~SmsMessage() { |
| 43 | // TODO Auto-generated destructor stub |
| 44 | } |
| 45 | |
| 46 | uint8_t SmsMessage::convertDtmfToAscii(uint8_t dtmfDigit) { |
| 47 | uint8_t asciiDigit; |
| 48 | |
| 49 | switch (dtmfDigit) { |
| 50 | case 0: |
| 51 | asciiDigit = 68; |
| 52 | break; // 'D' |
| 53 | case 1: |
| 54 | asciiDigit = 49; |
| 55 | break; // '1' |
| 56 | case 2: |
| 57 | asciiDigit = 50; |
| 58 | break; // '2' |
| 59 | case 3: |
| 60 | asciiDigit = 51; |
| 61 | break; // '3' |
| 62 | case 4: |
| 63 | asciiDigit = 52; |
| 64 | break; // '4' |
| 65 | case 5: |
| 66 | asciiDigit = 53; |
| 67 | break; // '5' |
| 68 | case 6: |
| 69 | asciiDigit = 54; |
| 70 | break; // '6' |
| 71 | case 7: |
| 72 | asciiDigit = 55; |
| 73 | break; // '7' |
| 74 | case 8: |
| 75 | asciiDigit = 56; |
| 76 | break; // '8' |
| 77 | case 9: |
| 78 | asciiDigit = 57; |
| 79 | break; // '9' |
| 80 | case 10: |
| 81 | asciiDigit = 48; |
| 82 | break; // '0' |
| 83 | case 11: |
| 84 | asciiDigit = 42; |
| 85 | break; // '*' |
| 86 | case 12: |
| 87 | asciiDigit = 35; |
| 88 | break; // '#' |
| 89 | case 13: |
| 90 | asciiDigit = 65; |
| 91 | break; // 'A' |
| 92 | case 14: |
| 93 | asciiDigit = 66; |
| 94 | break; // 'B' |
| 95 | case 15: |
| 96 | asciiDigit = 67; |
| 97 | break; // 'C' |
| 98 | default: |
| 99 | asciiDigit = 32; // Invalid DTMF code |
| 100 | break; |
| 101 | } |
| 102 | |
| 103 | return asciiDigit; |
| 104 | } |
| 105 | |
| 106 | void SmsMessage::writeInt(uint32_t data) { |
| 107 | mPdu.push_back((data >> 24) & 0xFF); |
| 108 | mPdu.push_back((data >> 16) & 0xFF); |
| 109 | mPdu.push_back((data >> 8) & 0xFF); |
| 110 | mPdu.push_back((data >> 0) & 0xFF); |
| 111 | } |
| 112 | |
| 113 | uint32_t SmsMessage::readInt(std::vector<uint8_t> pdu) { |
| 114 | uint32_t temp = 0; |
| 115 | temp = (pdu[mPos++] << 24) & 0xFF000000; |
| 116 | temp |= (pdu[mPos++] << 16) & 0xFF0000; |
| 117 | temp |= (pdu[mPos++] << 8) & 0xFF00; |
| 118 | temp |= (pdu[mPos++] << 0) & 0xFF; |
| 119 | return temp; |
| 120 | } |
| 121 | |
| 122 | void SmsMessage::writeVector(std::vector<uint8_t> v) { |
| 123 | mPdu.insert(mPdu.end(), v.begin(), v.end()); |
| 124 | } |
| 125 | |
| 126 | std::vector<uint8_t> SmsMessage::readVector(std::vector<uint8_t> v, |
| 127 | int length) { |
| 128 | std::vector<uint8_t> temp; |
| 129 | temp.insert(temp.end(), v.begin() + mPos, v.begin() + mPos + length); |
| 130 | mPos += length; |
| 131 | return temp; |
| 132 | } |
| 133 | |
| 134 | void SmsMessage::writeByte(uint8_t data) { |
| 135 | mPdu.push_back(data); |
| 136 | } |
| 137 | |
| 138 | uint8_t SmsMessage::readByte(std::vector<uint8_t> pdu) { |
| 139 | return mPdu[mPos++]; |
| 140 | } |
| 141 | |
| 142 | void SmsMessage::createPdu() { |
| 143 | auto env = mEnvelope; |
| 144 | auto addr = env->origAddress; |
| 145 | //ByteArrayOutputStream baos = new ByteArrayOutputStream(100); |
| 146 | //DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos)); |
| 147 | |
| 148 | writeInt(env->messageType); |
| 149 | writeInt(env->teleService); |
| 150 | writeInt(env->serviceCategory); |
| 151 | |
| 152 | writeByte(addr->digitMode); |
| 153 | writeByte(addr->numberMode); |
| 154 | writeByte(addr->ton); |
| 155 | writeByte(addr->numberPlan); |
| 156 | writeByte(addr->numberOfDigits); |
| 157 | writeVector(addr->origBytes); // digits |
| 158 | |
| 159 | writeInt(env->bearerReply); |
| 160 | // CauseCode values: |
| 161 | writeByte(env->replySeqNo); |
| 162 | writeByte(env->errorClass); |
| 163 | writeByte(env->causeCode); |
| 164 | //encoded BearerData: |
| 165 | writeInt(env->bearerData.size()); |
| 166 | writeVector(env->bearerData); |
| 167 | } |
| 168 | |
| 169 | void SmsMessage::parsePdu(std::vector<uint8_t> pdu) { |
| 170 | int length; |
| 171 | int bearerDataLength; |
| 172 | auto env = std::make_shared<SmsEnvelope>(); |
| 173 | auto addr = std::make_shared<CdmaSmsAddress>(); |
| 174 | // We currently do not parse subaddress in PDU, but it is required when determining |
| 175 | // fingerprint (see getIncomingSmsFingerprint()). |
| 176 | auto subaddr = std::make_shared<CdmaSmsSubaddress>(); |
| 177 | mPos = 0; |
| 178 | env->messageType = readInt(pdu); |
| 179 | env->teleService = readInt(pdu); |
| 180 | env->serviceCategory = readInt(pdu); |
| 181 | |
| 182 | addr->digitMode = readByte(pdu); |
| 183 | addr->numberMode = readByte(pdu); |
| 184 | addr->ton = readByte(pdu); |
| 185 | addr->numberPlan = readByte(pdu); |
| 186 | |
| 187 | length = readByte(pdu); |
| 188 | addr->numberOfDigits = length; |
| 189 | |
| 190 | // sanity check on the length |
| 191 | if (length > pdu.size()) { |
| 192 | throw runtime_error( |
| 193 | "createFromPdu: Invalid pdu, addr.numberOfDigits " |
| 194 | + std::to_string(length) + " > pdu len " |
| 195 | + std::to_string(pdu.size())); |
| 196 | } |
| 197 | addr->origBytes = readVector(pdu, length); // digits |
| 198 | env->bearerReply = readInt(pdu); |
| 199 | // CauseCode values: |
| 200 | env->replySeqNo = readByte(pdu); |
| 201 | env->errorClass = readByte(pdu); |
| 202 | env->causeCode = readByte(pdu); |
| 203 | |
| 204 | //encoded BearerData: |
| 205 | bearerDataLength = readInt(pdu); |
| 206 | // sanity check on the length |
| 207 | if (bearerDataLength > pdu.size()) { |
| 208 | throw runtime_error( |
| 209 | "createFromPdu: Invalid pdu, bearerDataLength " |
| 210 | + std::to_string(bearerDataLength) + " > pdu len " |
| 211 | + std::to_string(pdu.size())); |
| 212 | } |
| 213 | env->bearerData = readVector(pdu, bearerDataLength); |
| 214 | mPos = 0; // reset |
| 215 | // link the filled objects to this SMS |
| 216 | mOriginatingAddress = addr; |
| 217 | env->origAddress = addr; |
| 218 | env->origSubaddress = subaddr; |
| 219 | mEnvelope = env; |
| 220 | mPdu = pdu; |
| 221 | |
| 222 | parseSms(); |
| 223 | } |
| 224 | std::shared_ptr<SmsMessage> SmsMessage::createFromPdu( |
| 225 | std::vector<uint8_t> pdu) { |
| 226 | shared_ptr<SmsMessage> msg = make_shared<SmsMessage>(); |
| 227 | |
| 228 | msg->parsePdu(pdu); |
| 229 | return msg; |
| 230 | // try { |
| 231 | // } catch (RuntimeException ex) { |
| 232 | // Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex); |
| 233 | // return null; |
| 234 | // } catch (OutOfMemoryError e) { |
| 235 | // Log.e(LOG_TAG, "SMS PDU parsing failed with out of memory: ", e); |
| 236 | // return null; |
| 237 | // } |
| 238 | } |
| 239 | |
| 240 | SmsConstants::MessageClass SmsMessage::getMessageClass() { |
| 241 | if (BearerData::DISPLAY_MODE_IMMEDIATE == mBearerData->displayMode) { |
| 242 | return SmsConstants::MessageClass::CLASS_0; |
| 243 | } else { |
| 244 | return SmsConstants::MessageClass::UNKNOWN; |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | int SmsMessage::getMessageType() { |
| 249 | // NOTE: mEnvelope.messageType is not set correctly for cell broadcasts with some RILs. |
| 250 | // Use the service category parameter to detect CMAS and other cell broadcast messages. |
| 251 | if (mEnvelope->serviceCategory != 0) { |
| 252 | return SmsEnvelope::MESSAGE_TYPE_BROADCAST; |
| 253 | } else { |
| 254 | return SmsEnvelope::MESSAGE_TYPE_POINT_TO_POINT; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | /** |
| 259 | * Note: This function is a GSM specific functionality which is not supported in CDMA mode. |
| 260 | */ |
| 261 | int SmsMessage::getProtocolIdentifier() { |
| 262 | //Rlog.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode."); |
| 263 | // (3GPP TS 23.040): "no interworking, but SME to SME protocol": |
| 264 | return 0; |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * Note: This function is a GSM specific functionality which is not supported in CDMA mode. |
| 269 | */ |
| 270 | bool SmsMessage::isReplace() { |
| 271 | //Rlog.w(LOG_TAG, "isReplace: is not supported in CDMA mode."); |
| 272 | return false; |
| 273 | } |
| 274 | |
| 275 | /** |
| 276 | * Note: This function is a GSM specific functionality which is not supported in CDMA mode. |
| 277 | */ |
| 278 | bool SmsMessage::isCphsMwiMessage() { |
| 279 | //Rlog.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode."); |
| 280 | return false; |
| 281 | } |
| 282 | |
| 283 | bool SmsMessage::isMWIClearMessage() { |
| 284 | return ((mBearerData != nullptr) && (mBearerData->numberOfMessages == 0)); |
| 285 | } |
| 286 | |
| 287 | bool SmsMessage::isMWISetMessage() { |
| 288 | return ((mBearerData != nullptr) && (mBearerData->numberOfMessages > 0)); |
| 289 | } |
| 290 | |
| 291 | bool SmsMessage::isMwiDontStore() { |
| 292 | return ((mBearerData != nullptr) && (mBearerData->numberOfMessages > 0) |
| 293 | && (mBearerData->userData == nullptr)); |
| 294 | } |
| 295 | |
| 296 | /** |
| 297 | * Returns the status for a previously submitted message. |
| 298 | * For not interfering with status codes from GSM, this status code is |
| 299 | * shifted to the bits 31-16. |
| 300 | */ |
| 301 | int SmsMessage::getStatus() { |
| 302 | return (status << 16); |
| 303 | } |
| 304 | |
| 305 | /** Return true iff the bearer data message type is DELIVERY_ACK. */ |
| 306 | bool SmsMessage::isStatusReportMessage() { |
| 307 | return (mBearerData->messageType == BearerData::MESSAGE_TYPE_DELIVERY_ACK); |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * Note: This function is a GSM specific functionality which is not supported in CDMA mode. |
| 312 | */ |
| 313 | bool SmsMessage::isReplyPathPresent() { |
| 314 | //Rlog.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode."); |
| 315 | return false; |
| 316 | } |
| 317 | void SmsMessage::parseSms() { |
| 318 | // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6 |
| 319 | // It contains only an 8-bit number with the number of messages waiting |
| 320 | if (mEnvelope->teleService == SmsEnvelope::TELESERVICE_MWI) { |
| 321 | mBearerData = make_shared<BearerData>(); |
| 322 | if (mEnvelope->bearerData.empty()) { |
| 323 | mBearerData->numberOfMessages = 0x000000FF & mEnvelope->bearerData[0]; |
| 324 | } |
| 325 | std::cout << "parseSms: get MWI " << mBearerData->numberOfMessages << endl; |
| 326 | /* if (VDBG) { |
| 327 | Rlog.d(LOG_TAG, "parseSms: get MWI " + |
| 328 | Integer.toString(mBearerData.numberOfMessages)); |
| 329 | }*/ |
| 330 | return; |
| 331 | } |
| 332 | mBearerData = BearerData::decode(mEnvelope->bearerData); |
| 333 | RLOGD("MT raw BearerData = '%s'", (HexDump::toHexString(mEnvelope->bearerData)).c_str()); |
| 334 | RLOGD("MT raw BearerData = '%s'",(mBearerData->toString()).c_str()); |
| 335 | //std::cout << "MT raw BearerData = '" |
| 336 | // << HexDump::toHexString(mEnvelope->bearerData) << "'" << endl; |
| 337 | //std::cout << "MT (decoded) BearerData = " << mBearerData->toString() << endl; |
| 338 | // if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) { |
| 339 | // Rlog.d(LOG_TAG, "MT raw BearerData = '" + |
| 340 | // HexDump.toHexString(mEnvelope.bearerData) + "'"); |
| 341 | // Rlog.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData); |
| 342 | // } |
| 343 | mMessageRef = mBearerData->messageId; |
| 344 | if (mBearerData->userData != nullptr) { |
| 345 | mUserData = mBearerData->userData->payload; |
| 346 | mUserDataHeader = mBearerData->userData->userDataHeader; |
| 347 | mMessageBody = mBearerData->userData->payloadStr; |
| 348 | } |
| 349 | |
| 350 | if (mOriginatingAddress != nullptr) { |
| 351 | for(auto c: mOriginatingAddress->origBytes) { |
| 352 | mOriginatingAddress->address.push_back(c); |
| 353 | } |
| 354 | //std::accumulate(mOriginatingAddress->origBytes.begin(), mOriginatingAddress->origBytes.end(), mOriginatingAddress->address); |
| 355 | //mOriginatingAddress->address = HexDump::toHexString(mOriginatingAddress->origBytes); // modify |
| 356 | if (mOriginatingAddress->ton == CdmaSmsAddress::TON_INTERNATIONAL_OR_IP) { |
| 357 | if (mOriginatingAddress->address.at(0) != '+') { |
| 358 | mOriginatingAddress->address = "+" + mOriginatingAddress->address; |
| 359 | } |
| 360 | } |
| 361 | //std::cout << "SMS originating address: " << mOriginatingAddress->address<< endl; |
| 362 | // if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: " |
| 363 | // + mOriginatingAddress.address); |
| 364 | } |
| 365 | |
| 366 | //if (mBearerData->msgCenterTimeStamp != nullptr) { |
| 367 | //mScTimeMillis = mBearerData->msgCenterTimeStamp.toMillis(true); |
| 368 | //} |
| 369 | |
| 370 | //if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis); |
| 371 | |
| 372 | // Message Type (See 3GPP2 C.S0015-B, v2, 4.5.1) |
| 373 | if (mBearerData->messageType == BearerData::MESSAGE_TYPE_DELIVERY_ACK) { |
| 374 | // The BearerData MsgStatus subparameter should only be |
| 375 | // included for DELIVERY_ACK messages. If it occurred for |
| 376 | // other messages, it would be unclear what the status |
| 377 | // being reported refers to. The MsgStatus subparameter |
| 378 | // is primarily useful to indicate error conditions -- a |
| 379 | // message without this subparameter is assumed to |
| 380 | // indicate successful delivery (status == 0). |
| 381 | if (!mBearerData->messageStatusSet) { |
| 382 | std::cout << "DELIVERY_ACK message without msgStatus (" |
| 383 | << (mUserData.empty() ? "also missing" : "does have") << " userData)." |
| 384 | << endl; |
| 385 | // Rlog.d(LOG_TAG, "DELIVERY_ACK message without msgStatus (" + |
| 386 | // (mUserData == null ? "also missing" : "does have") + |
| 387 | // " userData)."); |
| 388 | status = 0; |
| 389 | } else { |
| 390 | status = mBearerData->errorClass << 8; |
| 391 | status |= mBearerData->messageStatus; |
| 392 | } |
| 393 | } else if (mBearerData->messageType != BearerData::MESSAGE_TYPE_DELIVER) { |
| 394 | throw runtime_error( |
| 395 | "Unsupported message type: " + mBearerData->messageType); |
| 396 | } |
| 397 | |
| 398 | if (!mMessageBody.empty()) { |
| 399 | //std::cout << "SMS message body: '" << mMessageBody << "'" << endl; |
| 400 | //if (VDBG) Rlog.v(LOG_TAG, "SMS message body: '" + mMessageBody + "'"); |
| 401 | parseMessageBody(); |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | std::vector<std::uint8_t> SmsMessage::getIncomingSmsFingerprint() { |
| 406 | RLOGD("getIncomingSmsFingerprint: category=%d, teleservices=%d", mEnvelope->serviceCategory, mEnvelope->teleService); |
| 407 | std::vector<uint8_t> output; |
| 408 | output.push_back(static_cast<uint8_t> (mEnvelope->serviceCategory)); |
| 409 | output.push_back(static_cast<uint8_t> (mEnvelope->teleService)); |
| 410 | output.insert(output.end(), (mEnvelope->origAddress->origBytes).begin(), (mEnvelope->origAddress->origBytes).end()); |
| 411 | output.insert(output.end(), (mEnvelope->bearerData).begin(), (mEnvelope->bearerData).end()); |
| 412 | if(mEnvelope->origSubaddress && (!(mEnvelope->origSubaddress->origBytes).empty())) { |
| 413 | output.insert(output.end(), (mEnvelope->origSubaddress->origBytes).begin(), (mEnvelope->origSubaddress->origBytes).end()); |
| 414 | } |
| 415 | return output; |
| 416 | } |