1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cdma_sms_transport_message.h"
17
18 #include "telephony_log_wrapper.h"
19
20 namespace OHOS {
21 namespace Telephony {
22 static constexpr uint8_t PARAMETER_ID_BYTES = 1;
23 static constexpr uint8_t PARAMETER_LEN_BYTES = 1;
24 static constexpr uint16_t CAT_UNKNOWN = 0x8001;
25 static constexpr uint8_t PARAMETER_SIZE_MAX = 9;
26
~CdmaSmsTransportMessage()27 CdmaSmsTransportMessage::~CdmaSmsTransportMessage()
28 {
29 parameter_.clear();
30 parameter_.shrink_to_fit();
31 }
32
Encode(SmsWriteBuffer & pdu)33 bool CdmaSmsTransportMessage::Encode(SmsWriteBuffer &pdu)
34 {
35 if (pdu.IsEmpty()) {
36 TELEPHONY_LOGE("pdu is empty");
37 return false;
38 }
39 if (parameter_.size() == 0) {
40 TELEPHONY_LOGE("parameter is empty");
41 return false;
42 }
43
44 pdu.SetIndex(0);
45 if (!pdu.WriteByte(type_)) {
46 TELEPHONY_LOGE("type write error");
47 return false;
48 }
49 for (uint8_t i = 0; i < parameter_.size(); i++) {
50 if (parameter_[i] == nullptr || !parameter_[i]->Encode(pdu)) {
51 TELEPHONY_LOGE("parameter encode error");
52 return false;
53 }
54 }
55 return true;
56 }
57
Decode(SmsReadBuffer & pdu)58 bool CdmaSmsTransportMessage::Decode(SmsReadBuffer &pdu)
59 {
60 if (pdu.IsEmpty()) {
61 TELEPHONY_LOGE("pdu is empty");
62 return false;
63 }
64 if (parameter_.size() == 0) {
65 TELEPHONY_LOGE("parameter is empty");
66 return false;
67 }
68
69 pdu.SetIndex(0);
70 if (!pdu.ReadByte(type_)) {
71 TELEPHONY_LOGE("type read error");
72 return false;
73 }
74 if (type_ != P2P && type_ != BROADCAST && type_ != ACK) {
75 TELEPHONY_LOGE("type[%{public}d] is invalid", type_);
76 return false;
77 }
78 for (uint8_t i = 0; i < parameter_.size(); i++) {
79 if (parameter_[i] == nullptr || !parameter_[i]->Decode(pdu)) {
80 TELEPHONY_LOGE("parameter decode error");
81 return false;
82 }
83 }
84 return true;
85 }
86
IsEmpty()87 bool CdmaSmsTransportMessage::IsEmpty()
88 {
89 if (parameter_.size() == 0) {
90 TELEPHONY_LOGE("parameter is empty");
91 return true;
92 }
93 return false;
94 }
95
CreateTransportMessage(CdmaTransportMsg & msg)96 std::unique_ptr<CdmaSmsTransportMessage> CdmaSmsTransportMessage::CreateTransportMessage(CdmaTransportMsg &msg)
97 {
98 if (msg.type == CdmaTransportMsgType::P2P) {
99 return std::make_unique<CdmaSmsP2pMessage>(msg.data.p2p);
100 } else if (msg.type == CdmaTransportMsgType::BROADCAST) {
101 return std::make_unique<CdmaSmsBroadcastMessage>(msg.data.broadcast);
102 } else if (msg.type == CdmaTransportMsgType::ACK) {
103 return std::make_unique<CdmaSmsAckMessage>(msg.data.ack);
104 } else {
105 TELEPHONY_LOGW("CreateTransportMessage: type [%{public}d] not support", static_cast<uint8_t>(msg.type));
106 return nullptr;
107 }
108 }
109
CreateTransportMessage(CdmaTransportMsg & msg,SmsReadBuffer & pdu)110 std::unique_ptr<CdmaSmsTransportMessage> CdmaSmsTransportMessage::CreateTransportMessage(
111 CdmaTransportMsg &msg, SmsReadBuffer &pdu)
112 {
113 if (pdu.IsEmpty()) {
114 TELEPHONY_LOGE("pdu is empty");
115 return nullptr;
116 }
117
118 uint8_t type = RESERVED;
119 if (!pdu.ReadByte(type)) {
120 TELEPHONY_LOGE("type read error");
121 return nullptr;
122 }
123 if (type == P2P) {
124 msg.type = CdmaTransportMsgType::P2P;
125 return std::make_unique<CdmaSmsP2pMessage>(msg.data.p2p, pdu);
126 } else if (type == BROADCAST) {
127 msg.type = CdmaTransportMsgType::BROADCAST;
128 return std::make_unique<CdmaSmsBroadcastMessage>(msg.data.broadcast, pdu);
129 } else if (type == ACK) {
130 msg.type = CdmaTransportMsgType::ACK;
131 return std::make_unique<CdmaSmsAckMessage>(msg.data.ack, pdu);
132 } else {
133 msg.type = CdmaTransportMsgType::RESERVED;
134 TELEPHONY_LOGW("CreateTransportMessage: type [%{public}d] not support", type);
135 return nullptr;
136 }
137 }
138
CdmaSmsP2pMessage(CdmaP2PMsg & msg)139 CdmaSmsP2pMessage::CdmaSmsP2pMessage(CdmaP2PMsg &msg)
140 {
141 type_ = P2P;
142 // Teleservice Identifier
143 parameter_.push_back(std::make_unique<CdmaSmsTeleserviceId>(msg.teleserviceId));
144 // Service Category
145 if (msg.serviceCtg < CAT_UNKNOWN) {
146 parameter_.push_back(std::make_unique<CdmaSmsServiceCategory>(msg.serviceCtg));
147 }
148 // Destination Address
149 parameter_.push_back(std::make_unique<CdmaSmsAddressParameter>(msg.address, CdmaSmsParameterRecord::DEST_ADDRESS));
150 // Destination Subaddress
151 if (msg.subAddress.addrLen > 0) {
152 parameter_.push_back(
153 std::make_unique<CdmaSmsSubaddress>(msg.subAddress, CdmaSmsParameterRecord::DEST_SUB_ADDRESS));
154 }
155 // Bearer Reply Option
156 if (msg.replySeq > 0) {
157 parameter_.push_back(std::make_unique<CdmaSmsBearerReply>(msg.replySeq));
158 }
159 // Bearer Data
160 parameter_.push_back(std::make_unique<CdmaSmsBearerData>(msg.telesvcMsg));
161 }
162
CdmaSmsP2pMessage(CdmaP2PMsg & msg,SmsReadBuffer & pdu)163 CdmaSmsP2pMessage::CdmaSmsP2pMessage(CdmaP2PMsg &msg, SmsReadBuffer &pdu)
164 {
165 if (pdu.IsEmpty()) {
166 TELEPHONY_LOGE("pdu is empty");
167 return;
168 }
169
170 type_ = P2P;
171 msg.serviceCtg = CAT_UNKNOWN;
172 uint8_t id = 0;
173 uint8_t len = 0;
174 while ((parameter_.size() < PARAMETER_SIZE_MAX) && pdu.ReadByte(id) && pdu.ReadByte(len)) {
175 if (id == CdmaSmsParameterRecord::TELESERVICE_ID) {
176 parameter_.push_back(std::make_unique<CdmaSmsTeleserviceId>(msg.teleserviceId));
177 } else if (id == CdmaSmsParameterRecord::SERVICE_CATEGORY) {
178 parameter_.push_back(std::make_unique<CdmaSmsServiceCategory>(msg.serviceCtg));
179 } else if (id == CdmaSmsParameterRecord::ORG_ADDRESS || id == CdmaSmsParameterRecord::DEST_ADDRESS) {
180 parameter_.push_back(std::make_unique<CdmaSmsAddressParameter>(msg.address, id));
181 } else if (id == CdmaSmsParameterRecord::ORG_SUB_ADDRESS || id == CdmaSmsParameterRecord::DEST_SUB_ADDRESS) {
182 parameter_.push_back(std::make_unique<CdmaSmsSubaddress>(msg.subAddress, id));
183 } else if (id == CdmaSmsParameterRecord::BEARER_REPLY_OPTION) {
184 parameter_.push_back(std::make_unique<CdmaSmsBearerReply>(msg.replySeq));
185 } else if (id == CdmaSmsParameterRecord::BEARER_DATA) {
186 uint16_t index = pdu.GetIndex();
187 parameter_.push_back(std::make_unique<CdmaSmsBearerData>(msg.telesvcMsg, pdu));
188 pdu.SetIndex(index);
189 } else {
190 TELEPHONY_LOGE("parameter ID[%{public}d] not support", id);
191 return;
192 }
193 pdu.MoveForward(len);
194 }
195 }
196
CdmaSmsBroadcastMessage(CdmaBroadCastMsg & msg)197 CdmaSmsBroadcastMessage::CdmaSmsBroadcastMessage(CdmaBroadCastMsg &msg)
198 {
199 type_ = BROADCAST;
200 // Service Category
201 parameter_.push_back(std::make_unique<CdmaSmsServiceCategory>(msg.serviceCtg));
202 // Bearer Data
203 parameter_.push_back(std::make_unique<CdmaSmsBearerData>(msg.telesvcMsg));
204 }
205
CdmaSmsBroadcastMessage(CdmaBroadCastMsg & msg,SmsReadBuffer & pdu)206 CdmaSmsBroadcastMessage::CdmaSmsBroadcastMessage(CdmaBroadCastMsg &msg, SmsReadBuffer &pdu)
207 {
208 if (pdu.IsEmpty()) {
209 TELEPHONY_LOGE("pdu is empty");
210 return;
211 }
212
213 type_ = BROADCAST;
214 msg.serviceCtg = CAT_UNKNOWN;
215 uint8_t id = 0;
216 uint8_t len = 0;
217 while ((parameter_.size() < PARAMETER_SIZE_MAX) && pdu.ReadByte(id) && pdu.ReadByte(len)) {
218 if (id == CdmaSmsParameterRecord::SERVICE_CATEGORY) {
219 parameter_.push_back(std::make_unique<CdmaSmsServiceCategory>(msg.serviceCtg));
220 uint16_t index = pdu.GetIndex();
221 pdu.MoveBack(PARAMETER_ID_BYTES + PARAMETER_LEN_BYTES); // back to ID field
222 parameter_[parameter_.size() - 1]->Decode(pdu);
223 pdu.SetIndex(index);
224 } else if (id == CdmaSmsParameterRecord::BEARER_DATA) {
225 uint16_t index = pdu.GetIndex();
226 bool isCMAS = false;
227 if (msg.serviceCtg >= static_cast<uint16_t>(SmsServiceCtg::CMAS_PRESIDENTIAL) &&
228 msg.serviceCtg <= static_cast<uint16_t>(SmsServiceCtg::CMAS_TEST)) {
229 isCMAS = true;
230 }
231 parameter_.push_back(std::make_unique<CdmaSmsBearerData>(msg.telesvcMsg, pdu, isCMAS));
232 pdu.SetIndex(index);
233 } else {
234 TELEPHONY_LOGE("parameter ID[%{public}d] not support", id);
235 return;
236 }
237 pdu.MoveForward(len);
238 }
239 }
240
CdmaSmsAckMessage(CdmaAckMsg & msg)241 CdmaSmsAckMessage::CdmaSmsAckMessage(CdmaAckMsg &msg)
242 {
243 type_ = ACK;
244 // Destination Address
245 parameter_.push_back(std::make_unique<CdmaSmsAddressParameter>(msg.address, CdmaSmsParameterRecord::DEST_ADDRESS));
246 if (msg.subAddress.addrLen > 0) {
247 // Destination Subaddress
248 parameter_.push_back(
249 std::make_unique<CdmaSmsSubaddress>(msg.subAddress, CdmaSmsParameterRecord::DEST_SUB_ADDRESS));
250 }
251 // Cause Codes
252 parameter_.push_back(std::make_unique<CdmaSmsCauseCodes>(msg.causeCode));
253 }
254
CdmaSmsAckMessage(CdmaAckMsg & msg,SmsReadBuffer & pdu)255 CdmaSmsAckMessage::CdmaSmsAckMessage(CdmaAckMsg &msg, SmsReadBuffer &pdu)
256 {
257 if (pdu.IsEmpty()) {
258 TELEPHONY_LOGE("pdu is empty");
259 return;
260 }
261
262 type_ = ACK;
263 uint8_t id = 0;
264 uint8_t len = 0;
265 while ((parameter_.size() < PARAMETER_SIZE_MAX) && pdu.ReadByte(id) && pdu.ReadByte(len)) {
266 if (id == CdmaSmsParameterRecord::DEST_ADDRESS) {
267 parameter_.push_back(std::make_unique<CdmaSmsAddressParameter>(msg.address, id));
268 } else if (id == CdmaSmsParameterRecord::DEST_SUB_ADDRESS) {
269 parameter_.push_back(std::make_unique<CdmaSmsSubaddress>(msg.subAddress, id));
270 } else if (id == CdmaSmsParameterRecord::CAUSE_CODES) {
271 parameter_.push_back(std::make_unique<CdmaSmsCauseCodes>(msg.causeCode));
272 } else {
273 TELEPHONY_LOGE("parameter ID[%{public}d] not support", id);
274 return;
275 }
276 pdu.MoveForward(len);
277 }
278 }
279
280 } // namespace Telephony
281 } // namespace OHOS
282