• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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