/* * Copyright (C) 2023 Huawei Device Co., Ltd. * 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 "gsm_user_data_encode.h" #include "gsm_pdu_hex_value.h" #include "gsm_sms_common_utils.h" #include "securec.h" #include "telephony_log_wrapper.h" namespace OHOS { namespace Telephony { using namespace std; static constexpr uint8_t NORMAL_BYTE_BITS = 8; static constexpr uint8_t GSM_ENCODE_BITS = 7; static constexpr uint8_t SLIDE_DATA_STEP = 2; static constexpr uint8_t MAX_TPDU_LEN = 255; static constexpr uint8_t HEX_07 = 0x07; static constexpr uint8_t HEX_08 = 0x08; const std::string CT_SMSC = "10659401"; GsmUserDataEncode::GsmUserDataEncode(std::shared_ptr data) { userData_ = data; } GsmUserDataEncode::~GsmUserDataEncode() {} bool GsmUserDataEncode::EncodeGsmPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData) { uint8_t fillBits = 0; if (!EncodeGsmHeadPdu(buffer, userData, fillBits)) { return false; } return EncodeGsmBodyPdu(buffer, userData, fillBits); } bool GsmUserDataEncode::EncodeGsmHeadPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData, uint8_t &fillBits) { if (userData == nullptr || userData_ == nullptr) { TELEPHONY_LOGE("nullptr error."); return false; } uint16_t location = buffer.GetIndex(); if (userData->headerCnt > 0) { buffer.MoveForward(SLIDE_DATA_STEP); } else { buffer.MoveForward(HEX_VALUE_01); } uint16_t udhl = buffer.GetIndex(); for (uint8_t i = 0; i < userData->headerCnt; i++) { userData_->EncodeHeader(buffer, userData->header[i]); } if (buffer.GetIndex() > udhl) { udhl = buffer.GetIndex() - udhl; } else { udhl = 0; } if (udhl > 0) { fillBits = ((udhl + 1) * NORMAL_BYTE_BITS) % GSM_ENCODE_BITS; /* + UDHL */ } if (fillBits > 0 && GSM_ENCODE_BITS > fillBits) { fillBits = GSM_ENCODE_BITS - fillBits; } else { fillBits = 0; } /* Set UDL, UDHL */ if (udhl > 0) { uint16_t value = ((udhl + 1) * HEX_08) + fillBits + (userData->length * HEX_07); if (!buffer.InsertByte((value / HEX_07), location)) { TELEPHONY_LOGE("write data error."); return false; } if (!buffer.InsertByte(static_cast(udhl), location + 1)) { TELEPHONY_LOGE("write data error."); return false; } } else { if (!buffer.InsertByte(userData->length, location)) { TELEPHONY_LOGE("write data error."); return false; } } return true; } bool GsmUserDataEncode::EncodeGsmBodyPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData, uint8_t fillBits) { if (userData == nullptr) { TELEPHONY_LOGE("nullptr error."); return false; } GsmSmsCommonUtils utils; bool packResult = utils.Pack7bitChar(buffer, reinterpret_cast(userData->data), userData->length, fillBits); return packResult; } bool GsmUserDataEncode::Encode8bitPdu( SmsWriteBuffer &buffer, const struct SmsUDPackage *userData, std::string &destAddr) { if (!Encode8bitHeadPdu(buffer, userData, destAddr)) { return false; } return Encode8bitBodyPdu(buffer, userData); } bool GsmUserDataEncode::Encode8bitHeadPdu( SmsWriteBuffer &buffer, const struct SmsUDPackage *userData, std::string &destAddr) { if (userData == nullptr || userData_ == nullptr) { TELEPHONY_LOGE("nullptr error."); return false; } uint16_t location = buffer.GetIndex(); if (userData->headerCnt > 0 && CT_SMSC.compare(destAddr) != 0) { buffer.MoveForward(SLIDE_DATA_STEP); } else { buffer.MoveForward(HEX_VALUE_01); } /* Encode User Data Header */ uint16_t udhl = buffer.GetIndex(); for (uint8_t index = 0; index < userData->headerCnt && CT_SMSC.compare(destAddr) != 0; index++) { userData_->EncodeHeader(buffer, userData->header[index]); } if (buffer.GetIndex() > udhl) { udhl = buffer.GetIndex() - udhl; } else { udhl = 0; } /* Set UDL, UDHL */ if (udhl > 0) { if (!buffer.InsertByte(static_cast(udhl + 1 + userData->length), location)) { TELEPHONY_LOGE("Encode8bitHeadPdu write data error."); return false; } if (!buffer.InsertByte(static_cast(udhl), location + 1)) { TELEPHONY_LOGE("Encode8bitHeadPdu write data error."); return false; } } else { if (!buffer.InsertByte(userData->length, location)) { TELEPHONY_LOGE("Encode8bitHeadPdu write data error."); return false; } } return true; } bool GsmUserDataEncode::Encode8bitBodyPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData) { if (userData == nullptr || buffer.data_ == nullptr) { TELEPHONY_LOGE("nullptr error"); return false; } if (buffer.GetIndex() >= MAX_TPDU_LEN || userData->length + buffer.GetIndex() > MAX_TPDU_LEN) { TELEPHONY_LOGE(" userData length error."); return false; } if (buffer.GetIndex() >= buffer.GetSize() || userData->length + buffer.GetIndex() > buffer.GetSize()) { TELEPHONY_LOGE("buffer error."); return false; } uint16_t destLen = MAX_TPDU_LEN - buffer.GetIndex() - HEX_VALUE_01; if (memcpy_s(buffer.data_.get() + buffer.GetIndex(), destLen, userData->data, userData->length) != EOK) { TELEPHONY_LOGE("memcpy_s error"); return false; } buffer.MoveForward(userData->length); return true; } bool GsmUserDataEncode::EncodeUcs2Pdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData) { if (!EncodeUcs2HeadPdu(buffer, userData)) { return false; } return EncodeUcs2BodyPdu(buffer, userData); } bool GsmUserDataEncode::EncodeUcs2HeadPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData) { if (userData == nullptr || userData_ == nullptr) { TELEPHONY_LOGE("nullptr error"); return false; } uint16_t location = buffer.GetIndex(); if (userData->headerCnt == 0) { buffer.MoveForward(1); } else { buffer.MoveForward(SLIDE_DATA_STEP); } /* Encode User Data Header */ uint16_t udhl = buffer.GetIndex(); for (uint8_t j = 0; j < userData->headerCnt; j++) { userData_->EncodeHeader(buffer, userData->header[j]); } if (buffer.GetIndex() > udhl) { udhl = buffer.GetIndex() - udhl; } else { udhl = 0; } /* Set UDL, UDHL */ if (udhl > 0) { if (!buffer.InsertByte(static_cast(udhl + 1 + userData->length), location)) { TELEPHONY_LOGE("EncodeUcs2HeadPdu write data error."); return false; } if (!buffer.InsertByte(static_cast(udhl), location + 1)) { TELEPHONY_LOGE("EncodeUcs2HeadPdu write data error."); return false; } } else { if (!buffer.InsertByte(userData->length, location)) { TELEPHONY_LOGE("EncodeUcs2HeadPdu write data error."); return false; } } return true; } bool GsmUserDataEncode::EncodeUcs2BodyPdu(SmsWriteBuffer &buffer, const struct SmsUDPackage *userData) { if (userData == nullptr) { TELEPHONY_LOGE("nullptr error"); return false; } if (userData->length + buffer.GetIndex() >= MAX_TPDU_LEN) { TELEPHONY_LOGE("data length error"); return false; } if (buffer.data_ == nullptr || (buffer.GetIndex() + userData->length) > buffer.GetSize()) { TELEPHONY_LOGE("buffer error."); return false; } uint16_t destLen = MAX_TPDU_LEN - buffer.GetIndex() - HEX_VALUE_01; if (memcpy_s(buffer.data_.get() + buffer.GetIndex(), destLen, userData->data, userData->length) != EOK) { TELEPHONY_LOGE("memcpy_s error"); return false; } buffer.MoveForward(userData->length); return true; } } // namespace Telephony } // namespace OHOS