* 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<GsmUserDataPdu> 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;
}
if (fillBits > 0 && GSM_ENCODE_BITS > fillBits) {
fillBits = GSM_ENCODE_BITS - fillBits;
} else {
fillBits = 0;
}
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<uint8_t>(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<const uint8_t *>(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);
}
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;
}
if (udhl > 0) {
if (!buffer.InsertByte(static_cast<uint8_t>(udhl + 1 + userData->length), location)) {
TELEPHONY_LOGE("Encode8bitHeadPdu write data error.");
return false;
}
if (!buffer.InsertByte(static_cast<uint8_t>(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);
}
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;
}
if (udhl > 0) {
if (!buffer.InsertByte(static_cast<uint8_t>(udhl + 1 + userData->length), location)) {
TELEPHONY_LOGE("EncodeUcs2HeadPdu write data error.");
return false;
}
if (!buffer.InsertByte(static_cast<uint8_t>(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;
}
}
}