/* * 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 "sms_pdu_buffer.h" #include "securec.h" #include "telephony_log_wrapper.h" namespace OHOS { namespace Telephony { static constexpr uint16_t PDU_BUFFER_MAX_SIZE = 0xFF; static constexpr uint16_t PDU_BUFFER_MIN_SIZE = 2; SmsPduBuffer::~SmsPduBuffer() { if (data_ != nullptr) { data_.reset(); } } bool SmsPduBuffer::IsEmpty() { return data_ == nullptr; } uint16_t SmsPduBuffer::GetIndex() { return index_; } uint16_t SmsPduBuffer::GetSize() { return length_; } bool SmsPduBuffer::SetIndex(uint16_t index) { if (bitIndex_ != BIT0) { TELEPHONY_LOGE("buffer in bit mode"); return false; } if (index > length_) { TELEPHONY_LOGE("index over buffer"); return false; } index_ = index; return true; } uint16_t SmsPduBuffer::MoveForward(uint16_t len) { if (bitIndex_ != BIT0) { TELEPHONY_LOGE("buffer in bit mode"); return index_; } if (index_ + len > length_) { TELEPHONY_LOGE("move over buffer"); return index_; } uint16_t pos = index_; index_ += len; return pos; } uint16_t SmsPduBuffer::MoveBack(uint16_t len) { if (bitIndex_ != BIT0) { TELEPHONY_LOGE("buffer in bit mode"); return index_; } if (index_ < len) { TELEPHONY_LOGE("back over buffer"); return index_; } uint16_t pos = index_; index_ -= len; return pos; } uint16_t SmsPduBuffer::SkipBits() { if (bitIndex_ > BIT0) { index_++; bitIndex_ = BIT0; } return index_; } std::unique_ptr> SmsPduBuffer::GetPduBuffer() { if (data_ == nullptr || index_ == 0) { TELEPHONY_LOGE("data is null"); return nullptr; } if (bitIndex_ != BIT0) { TELEPHONY_LOGE("buffer in bit mode"); return nullptr; } if (index_ >= length_) { TELEPHONY_LOGE("data error."); return nullptr; } std::unique_ptr> data = std::make_unique>(data_.get(), data_.get() + index_); if (data == nullptr) { TELEPHONY_LOGE("make unique error"); return nullptr; } return data; } SmsReadBuffer::SmsReadBuffer(const std::string &hex) { size_t len = hex.length(); if (len < PDU_BUFFER_MIN_SIZE || len > PDU_BUFFER_MAX_SIZE + 1) { TELEPHONY_LOGE("invalid PDU"); return; } data_ = std::make_unique(len); if (data_ == nullptr) { TELEPHONY_LOGE("make_unique error"); return; } if (memset_s(data_.get(), len, 0x00, len) != EOK) { TELEPHONY_LOGE("memset_s error"); data_.reset(); data_ = nullptr; return; } if (memcpy_s(data_.get(), len, hex.c_str(), len) != EOK) { TELEPHONY_LOGE("memcpy_s error"); data_.reset(); data_ = nullptr; return; } length_ = len; } bool SmsReadBuffer::ReadByte(uint8_t &v) { if (data_ == nullptr) { TELEPHONY_LOGE("data is null"); return false; } if (bitIndex_ != BIT0) { return ReadBits(v, BIT8); } if (index_ == length_) { TELEPHONY_LOGW("read over buffer"); return false; } v = data_[index_++]; return true; } bool SmsReadBuffer::PickOneByte(uint8_t &v) { if (data_ == nullptr || index_ >= length_) { TELEPHONY_LOGE("peek one byte fail."); return false; } v = data_[index_]; return true; } bool SmsReadBuffer::PickOneByteFromIndex(uint16_t index, uint8_t &v) { if (data_ == nullptr || length_ == 0 || index >= length_) { TELEPHONY_LOGE("peek index byte fail."); return false; } v = data_[index]; return true; } bool SmsReadBuffer::ReadWord(uint16_t &v) { if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) { v = data_[index_++]; v = (v << BIT8) | data_[index_++]; return true; } TELEPHONY_LOGE("read word error"); return false; } bool SmsReadBuffer::ReadBits(uint8_t &v, uint8_t l) { if (data_ == nullptr) { TELEPHONY_LOGE("data is null"); return false; } if (l == BIT0 || l > BIT8) { TELEPHONY_LOGE("read bits : invalid length"); return false; } if (bitIndex_ + l <= BIT8) { if (index_ == length_) { TELEPHONY_LOGE("read bits over buffer"); return false; } v = data_[index_] << bitIndex_; v = v >> (BIT8 - l); bitIndex_ += l; if (bitIndex_ == BIT8) { bitIndex_ = BIT0; index_++; } } else { if (index_ == length_ - 1) { TELEPHONY_LOGE("read bits over buffer"); return false; } v = data_[index_++] << bitIndex_; bitIndex_ = l + bitIndex_ - BIT8; v = (v >> (BIT8 - l)) | (data_[index_] >> (BIT8 - bitIndex_)); } return true; } SmsWriteBuffer::SmsWriteBuffer() { length_ = PDU_BUFFER_MAX_SIZE + 1; data_ = std::make_unique(length_); if (data_ == nullptr) { TELEPHONY_LOGE("make_unique create data error"); length_ = 0; return; } } bool SmsWriteBuffer::WriteByte(uint8_t v) { if (bitIndex_ != BIT0) { return WriteBits(v, BIT8); } if (data_ != nullptr && index_ < length_) { data_[index_++] = v; return true; } TELEPHONY_LOGE("write byte error"); return false; } bool SmsWriteBuffer::WriteWord(uint16_t v) { if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) { data_[index_++] = (0xff00 & v) >> BIT8; data_[index_++] = (0x00ff & v); return true; } TELEPHONY_LOGE("write word error"); return false; } bool SmsWriteBuffer::WriteBits(uint8_t v, uint8_t l) { if (data_ == nullptr) { TELEPHONY_LOGE("data is null"); return false; } if (l == BIT0 || l > BIT8) { TELEPHONY_LOGE("write bits : invalid length"); return false; } if (bitIndex_ + l <= BIT8) { if (index_ == length_) { TELEPHONY_LOGE("write bits over buffer[%d]", l); return false; } data_[index_] |= v << (BIT8 - bitIndex_ - l); bitIndex_ += l; if (bitIndex_ == BIT8) { bitIndex_ = BIT0; index_++; } } else { if (index_ == length_ - 1) { TELEPHONY_LOGE("write bits over buffer[%d]", l); return false; } data_[index_++] |= v >> (l + bitIndex_ - BIT8); bitIndex_ = l + bitIndex_ - BIT8; data_[index_] |= v << (BIT8 - bitIndex_); } return true; } bool SmsWriteBuffer::InsertByte(uint8_t v, uint16_t index) { if (data_ != nullptr && index < length_ && bitIndex_ == BIT0) { data_[index] = v; return true; } TELEPHONY_LOGE("insert byte error"); return false; } bool SmsWriteBuffer::GetTopValue(uint8_t &oneByte) { if (data_ == nullptr || length_ == 0 || index_ >= length_) { TELEPHONY_LOGE("buffer error"); return false; } oneByte = data_[index_]; return true; } bool SmsWriteBuffer::GetValueFromIndex(uint16_t index, uint8_t &v) { if (data_ == nullptr || length_ == 0 || index >= length_) { TELEPHONY_LOGE("buffer error"); return false; } v = data_[index]; return true; } } // namespace Telephony } // namespace OHOS