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#define LOG_TAG "TlvObject" 17#include "tlv_object.h" 18#include "logger.h" 19 20namespace OHOS { 21namespace UDMF { 22TLVObject::TLVObject(std::vector<std::uint8_t> &buffer) 23{ 24 total_ += buffer.size(); 25 buffer_ = &buffer; 26 cursor_ = 0; 27 file_ = nullptr; 28} 29 30void TLVObject::SetFile(std::FILE *file) 31{ 32 file_ = file; 33 if (fseek(file_, 0, SEEK_END) != 0) { 34 LOG_ERROR(UDMF_SERVICE, "fseek to end error!"); 35 } 36 37 auto total = ftell(file_); 38 if (total < 0) { 39 LOG_ERROR(UDMF_SERVICE, "Values are out of range, total:%{public}ld", total); 40 return; 41 } 42 total_ = static_cast<size_t>(total); 43 ResetCursor(); 44} 45 46void TLVObject::UpdateSize() 47{ 48 if (file_ != nullptr) { 49 return; 50 } 51 buffer_->resize(total_); 52} 53 54std::vector<std::uint8_t> TLVObject::GetBuffer() 55{ 56 return *buffer_; 57} 58 59size_t TLVObject::GetTotal() 60{ 61 return total_; 62} 63 64size_t TLVObject::GetCursor() 65{ 66 return cursor_; 67} 68 69size_t TLVObject::OffsetHead() 70{ 71 if (file_ != nullptr) { 72 if (fseek(file_, sizeof(TLVHead), SEEK_CUR) != 0) { 73 LOG_ERROR(UDMF_SERVICE, "OffsetHead file error!"); 74 return 0; 75 } 76 } 77 cursor_ += sizeof(TLVHead); 78 return cursor_; 79} 80 81void TLVObject::ResetCursor() 82{ 83 cursor_ = 0; 84 if (file_ != nullptr) { 85 if (fseek(file_, 0, SEEK_SET) != 0) { 86 LOG_ERROR(UDMF_SERVICE, "ResetCursor file error!"); 87 } 88 } 89} 90 91size_t TLVObject::Count(const std::string &value) 92{ 93 auto size = sizeof(TLVHead) + value.size(); 94 total_ += size; 95 return size; 96} 97 98size_t TLVObject::Count(const std::vector<uint8_t> &value) 99{ 100 auto size = sizeof(TLVHead) + value.size(); 101 total_ += size; 102 return size; 103} 104 105size_t TLVObject::Count(const OHOS::AAFwk::Want &value) 106{ 107 Parcel parcel; 108 if (!value.Marshalling(parcel)) { 109 LOG_ERROR(UDMF_FRAMEWORK, "Marshalling want error when Count"); 110 return 0; 111 } 112 auto size = sizeof(TLVHead) + parcel.GetDataSize(); 113 total_ += size; 114 return size; 115} 116 117size_t TLVObject::Count(const std::monostate &value) 118{ 119 auto size = sizeof(TLVHead); 120 total_ += size; 121 return size; 122} 123 124size_t TLVObject::Count(const void *value) 125{ 126 auto size = sizeof(TLVHead); 127 total_ += size; 128 return size; 129} 130 131bool TLVObject::Write(TAG tag, const std::string &value) 132{ 133 if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { 134 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write. tag=%{public}hu, value=%{public}s", tag, 135 value.c_str()); 136 return false; 137 } 138 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor()); 139 tlvHead->tag = HostToNet(static_cast<uint16_t>(tag)); 140 tlvHead->len = HostToNet((uint32_t)value.size()); 141 if (!value.empty()) { 142 auto err = memcpy_s(tlvHead->value, value.size(), value.c_str(), value.size()); 143 if (err != EOK) { 144 LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write. tag=%{public}hu, value=%{public}s", tag, 145 value.c_str()); 146 return false; 147 } 148 } 149 cursor_ += sizeof(TLVHead) + value.size(); 150 return SaveBufferToFile(); 151} 152 153bool TLVObject::Read(std::string &value, const TLVHead &head) 154{ 155 if (!HasExpectBuffer(head.len)) { 156 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read string. tag=%{public}hu", head.tag); 157 return false; 158 } 159 if (!LoadBufferFormFile(head.len)) { 160 LOG_ERROR(UDMF_FRAMEWORK, "LoadBufferFormFile error in tlv read string. tag=%{public}hu", head.tag); 161 return false; 162 } 163 auto startCursor = GetStartCursor(); 164 value.append(reinterpret_cast<const char *>(startCursor), head.len); 165 cursor_ += head.len; 166 return true; 167} 168 169bool TLVObject::Write(TAG tag, const std::vector<uint8_t> &value) 170{ 171 if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { 172 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write u8 vector. tag=%{public}hu", tag); 173 return false; 174 } 175 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor()); 176 tlvHead->tag = HostToNet(static_cast<uint16_t>(tag)); 177 tlvHead->len = HostToNet(static_cast<uint32_t>(value.size())); 178 if (!value.empty()) { 179 auto err = memcpy_s(tlvHead->value, value.size(), value.data(), value.size()); 180 if (err != EOK) { 181 LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write u8 vector. tag=%{public}hu", tag); 182 return false; 183 } 184 } 185 cursor_ += sizeof(TLVHead) + value.size(); 186 return SaveBufferToFile(); 187} 188 189 190bool TLVObject::Read(std::vector<uint8_t> &value, const TLVHead &head) 191{ 192 if (!HasExpectBuffer(head.len)) { 193 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read u8 vector. tag=%{public}hu", head.tag); 194 return false; 195 } 196 if (!LoadBufferFormFile(head.len)) { 197 LOG_ERROR(UDMF_FRAMEWORK, "LoadBufferFormFile error in tlv read u8 vector. tag=%{public}hu", head.tag); 198 return false; 199 } 200 auto startCursor = GetStartCursor(); 201 std::vector<uint8_t> buff(startCursor, startCursor + head.len); 202 value = std::move(buff); 203 cursor_ += head.len; 204 return true; 205} 206 207bool TLVObject::Write(TAG tag, const OHOS::AAFwk::Want &value) 208{ 209 Parcel parcel; 210 if (!value.Marshalling(parcel)) { 211 LOG_ERROR(UDMF_FRAMEWORK, "Marshalling want error in tlv write. tag=%{public}hu", tag); 212 return false; 213 } 214 auto size = parcel.GetDataSize(); 215 auto buffer = parcel.GetData(); 216 217 if (!HasExpectBuffer(sizeof(TLVHead) + size)) { 218 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write want. tag=%{public}hu", tag); 219 return false; 220 } 221 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor()); 222 tlvHead->tag = HostToNet(static_cast<uint16_t>(tag)); 223 tlvHead->len = HostToNet(static_cast<uint32_t>(size)); 224 if (size != 0) { 225 auto err = memcpy_s(tlvHead->value, size, reinterpret_cast<const void *>(buffer), size); 226 if (err != EOK) { 227 LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write want. tag=%{public}hu", tag); 228 return false; 229 } 230 } 231 cursor_ += sizeof(TLVHead) + size; 232 return SaveBufferToFile(); 233} 234 235bool TLVObject::Read(OHOS::AAFwk::Want &value, const TLVHead &head) 236{ 237 if (!HasExpectBuffer(head.len)) { 238 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read want. tag=%{public}hu", head.tag); 239 return false; 240 } 241 if (!LoadBufferFormFile(head.len)) { 242 LOG_ERROR(UDMF_FRAMEWORK, "LoadBufferFormFile error in tlv read want. tag=%{public}hu", head.tag); 243 return false; 244 } 245 auto startCursor = GetStartCursor(); 246 std::vector<uint8_t> buff(startCursor, startCursor + head.len); 247 248 auto buffer = (uintptr_t)(buff.data() + cursor_); 249 cursor_ += head.len; 250 251 Parcel parcel; 252 if (!parcel.ParseFrom(buffer, head.len)) { 253 LOG_ERROR(UDMF_FRAMEWORK, "ParseFrom error in tlv read want. tag=%{public}hu", head.tag); 254 return false; 255 } 256 auto want = AAFwk::Want::Unmarshalling(parcel); 257 if (want == nullptr) { 258 LOG_ERROR(UDMF_FRAMEWORK, "Unmarshalling want error in tlv read. tag=%{public}hu", head.tag); 259 return false; 260 } 261 value = *want; 262 return true; 263} 264 265bool TLVObject::Write(TAG tag, const std::monostate &value) 266{ 267 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0); 268} 269 270bool TLVObject::Read(std::monostate &value, const TLVHead &head) 271{ 272 return true; 273} 274 275bool TLVObject::Write(TAG tag, const void *value) 276{ 277 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0); 278} 279 280 281bool TLVObject::Read(void *value, const TLVHead &head) 282{ 283 value = nullptr; 284 return true; 285} 286 287size_t TLVObject::CountHead() 288{ 289 total_ += sizeof(TLVHead); 290 return sizeof(TLVHead); 291} 292 293bool TLVObject::WriteHead(uint16_t tag, uint32_t len) 294{ 295 if (!HasExpectBuffer(sizeof(TLVHead))) { 296 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write head. tag=%{public}hu", tag); 297 return false; 298 } 299 PrepareBufferForFile(sizeof(TLVHead)); 300 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor()); 301 tlvHead->tag = HostToNet(tag); 302 tlvHead->len = HostToNet(len); 303 cursor_ += sizeof(TLVHead); 304 return SaveBufferToFile(); 305} 306 307bool TLVObject::WriteBackHead(uint16_t tag, size_t tagCursor, uint32_t len) 308{ 309 auto startCursor = buffer_->data(); 310 if (file_ == nullptr) { 311 startCursor += tagCursor; 312 } 313 auto tlvHead = reinterpret_cast<TLVHead *>(startCursor); 314 tlvHead->tag = HostToNet(tag); 315 tlvHead->len = HostToNet(len); 316 return SaveBufferToFileFront(tagCursor, sizeof(TLVHead)); 317} 318 319bool TLVObject::ReadHead(TLVHead &head) 320{ 321 if (!HasExpectBuffer(sizeof(TLVHead))) { 322 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read head. tag=%{public}hu", head.tag); 323 return false; 324 } 325 if (!LoadBufferFormFile(sizeof(TLVHead))) { 326 LOG_ERROR(UDMF_FRAMEWORK, "LoadBufferFormFile error in tlv read head. tag=%{public}hu", head.tag); 327 return false; 328 } 329 auto startCursor = GetStartCursor(); 330 const auto *pHead = reinterpret_cast<const TLVHead *>(startCursor); 331 auto len = NetToHost(pHead->len); 332 if (file_ == nullptr) { 333 if (!HasExpectBuffer(len + sizeof(TLVHead))) { 334 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read head and len. tag=%{public}hu", head.tag); 335 return false; 336 } 337 } 338 339 head.tag = NetToHost(pHead->tag); 340 head.len = len; 341 cursor_ += sizeof(TLVHead); 342 return true; 343} 344 345bool TLVObject::Skip(TLVHead &head) 346{ 347 if (file_ != nullptr) { 348 cursor_ += head.len; 349 return fseek(file_, head.len * sizeof(uint8_t), SEEK_CUR) == 0; 350 } 351 if (total_ < head.len || total_ - head.len < cursor_) { 352 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv skip. tag=%{public}hu", head.tag); 353 return false; 354 } 355 cursor_ += head.len; 356 return true; 357} 358 359bool TLVObject::HasExpectBuffer(const uint32_t expectLen) const 360{ 361 if (buffer_ == nullptr) { 362 return false; 363 } 364 if (file_ != nullptr) { 365 buffer_->resize(expectLen); 366 return true; 367 } 368 return buffer_->size() >= cursor_ && buffer_->size() - cursor_ >= expectLen; 369} 370 371void TLVObject::PrepareBufferForFile(size_t size) 372{ 373 if (file_ == nullptr) { 374 return; 375 } 376 buffer_->resize(size); 377} 378 379std::uint8_t *TLVObject::GetStartCursor() 380{ 381 auto startCursor = buffer_->data(); 382 if (file_ == nullptr) { 383 startCursor += cursor_; 384 } 385 return startCursor; 386} 387 388bool TLVObject::SaveBufferToFile() 389{ 390 if (file_ == nullptr) { 391 return true; 392 } 393 auto count = fwrite(buffer_->data(), sizeof(uint8_t), buffer_->size(), file_); 394 if (count != buffer_->size()) { 395 LOG_ERROR(UDMF_FRAMEWORK, "fwrite error!"); 396 return false; 397 } 398 return true; 399} 400 401bool TLVObject::SaveBufferToFileFront(size_t tagCursor, uint32_t len) 402{ 403 if (file_ == nullptr) { 404 return true; 405 } 406 int32_t leftOffset = 407 -((static_cast<int32_t>(cursor_) - static_cast<int32_t>(tagCursor))) * static_cast<int32_t>(sizeof(uint8_t)); 408 if (fseek(file_, leftOffset * sizeof(uint8_t), SEEK_CUR) != 0) { 409 LOG_ERROR(UDMF_FRAMEWORK, "file fseek left error!"); 410 return false; 411 } 412 auto count = fwrite(buffer_->data(), sizeof(uint8_t), sizeof(TLVHead), file_); 413 if (count != sizeof(TLVHead)) { 414 LOG_ERROR(UDMF_FRAMEWORK, "file write error!"); 415 return false; 416 } 417 int32_t rightOffset = 418 static_cast<int32_t>(cursor_) - static_cast<int32_t>(tagCursor) - static_cast<int32_t>(sizeof(TLVHead)); 419 if (fseek(file_, rightOffset * sizeof(uint8_t), SEEK_CUR) != 0) { 420 LOG_ERROR(UDMF_FRAMEWORK, "file fseek right error!"); 421 return false; 422 } 423 return true; 424} 425 426bool TLVObject::LoadBufferFormFile(size_t size) 427{ 428 if (file_ == nullptr) { 429 return true; 430 } 431 auto count = fread(buffer_->data(), sizeof(uint8_t), buffer_->size(), file_); 432 if (count != buffer_->size()) { 433 return false; 434 } 435 return true; 436} 437} // namespace UDMF 438} // namespace OHOS 439