blob: 771e861466cc6e4c0ab95c73a51cb899d0929f7d [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
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>
19using 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
30uint32_t SmsMessage::mPos = 0;
31SmsMessage::SmsMessage(std::shared_ptr<SmsAddress> addr,std::shared_ptr<SmsEnvelope> env) {
32 mOriginatingAddress = addr;
33 mEnvelope = env;
34 createPdu();
35}
36
37SmsMessage::SmsMessage() {
38 // TODO Auto-generated constructor stub
39
40}
41
42SmsMessage::~SmsMessage() {
43 // TODO Auto-generated destructor stub
44}
45
46uint8_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
106void 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
113uint32_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
122void SmsMessage::writeVector(std::vector<uint8_t> v) {
123 mPdu.insert(mPdu.end(), v.begin(), v.end());
124}
125
126std::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
134void SmsMessage::writeByte(uint8_t data) {
135 mPdu.push_back(data);
136}
137
138uint8_t SmsMessage::readByte(std::vector<uint8_t> pdu) {
139 return mPdu[mPos++];
140}
141
142void 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
169void 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}
224std::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
240SmsConstants::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
248int 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 */
261int 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 */
270bool 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 */
278bool SmsMessage::isCphsMwiMessage() {
279 //Rlog.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
280 return false;
281}
282
283bool SmsMessage::isMWIClearMessage() {
284 return ((mBearerData != nullptr) && (mBearerData->numberOfMessages == 0));
285}
286
287bool SmsMessage::isMWISetMessage() {
288 return ((mBearerData != nullptr) && (mBearerData->numberOfMessages > 0));
289}
290
291bool 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 */
301int SmsMessage::getStatus() {
302 return (status << 16);
303}
304
305/** Return true iff the bearer data message type is DELIVERY_ACK. */
306bool 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 */
313bool SmsMessage::isReplyPathPresent() {
314 //Rlog.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
315 return false;
316}
317void 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
405std::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}