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
20 namespace OHOS {
21 namespace UDMF {
TLVObject(std::vector<std::uint8_t> & buffer)22 TLVObject::TLVObject(std::vector<std::uint8_t> &buffer)
23 {
24 total_ += buffer.size();
25 buffer_ = &buffer;
26 cursor_ = 0;
27 file_ = nullptr;
28 }
29
SetFile(std::FILE * file)30 void 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
UpdateSize()46 void TLVObject::UpdateSize()
47 {
48 if (file_ != nullptr) {
49 return;
50 }
51 buffer_->resize(total_);
52 }
53
GetBuffer()54 std::vector<std::uint8_t> TLVObject::GetBuffer()
55 {
56 return *buffer_;
57 }
58
GetTotal()59 size_t TLVObject::GetTotal()
60 {
61 return total_;
62 }
63
GetCursor()64 size_t TLVObject::GetCursor()
65 {
66 return cursor_;
67 }
68
OffsetHead()69 size_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
ResetCursor()81 void 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
Count(const std::string & value)91 size_t TLVObject::Count(const std::string &value)
92 {
93 auto size = sizeof(TLVHead) + value.size();
94 total_ += size;
95 return size;
96 }
97
Count(const std::vector<uint8_t> & value)98 size_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
Count(const OHOS::AAFwk::Want & value)105 size_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
Count(const std::monostate & value)117 size_t TLVObject::Count(const std::monostate &value)
118 {
119 auto size = sizeof(TLVHead);
120 total_ += size;
121 return size;
122 }
123
Count(const void * value)124 size_t TLVObject::Count(const void *value)
125 {
126 auto size = sizeof(TLVHead);
127 total_ += size;
128 return size;
129 }
130
Write(TAG tag,const std::string & value)131 bool 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
Read(std::string & value,const TLVHead & head)153 bool 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
Write(TAG tag,const std::vector<uint8_t> & value)169 bool 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
Read(std::vector<uint8_t> & value,const TLVHead & head)190 bool 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
Write(TAG tag,const OHOS::AAFwk::Want & value)207 bool 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
Read(OHOS::AAFwk::Want & value,const TLVHead & head)235 bool 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
Write(TAG tag,const std::monostate & value)265 bool TLVObject::Write(TAG tag, const std::monostate &value)
266 {
267 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0);
268 }
269
Read(std::monostate & value,const TLVHead & head)270 bool TLVObject::Read(std::monostate &value, const TLVHead &head)
271 {
272 return true;
273 }
274
Write(TAG tag,const void * value)275 bool TLVObject::Write(TAG tag, const void *value)
276 {
277 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0);
278 }
279
280
Read(void * value,const TLVHead & head)281 bool TLVObject::Read(void *value, const TLVHead &head)
282 {
283 value = nullptr;
284 return true;
285 }
286
CountHead()287 size_t TLVObject::CountHead()
288 {
289 total_ += sizeof(TLVHead);
290 return sizeof(TLVHead);
291 }
292
WriteHead(uint16_t tag,uint32_t len)293 bool 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
WriteBackHead(uint16_t tag,size_t tagCursor,uint32_t len)307 bool 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
ReadHead(TLVHead & head)319 bool 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
Skip(TLVHead & head)345 bool 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
HasExpectBuffer(const uint32_t expectLen) const359 bool 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
PrepareBufferForFile(size_t size)371 void TLVObject::PrepareBufferForFile(size_t size)
372 {
373 if (file_ == nullptr) {
374 return;
375 }
376 buffer_->resize(size);
377 }
378
GetStartCursor()379 std::uint8_t *TLVObject::GetStartCursor()
380 {
381 auto startCursor = buffer_->data();
382 if (file_ == nullptr) {
383 startCursor += cursor_;
384 }
385 return startCursor;
386 }
387
SaveBufferToFile()388 bool 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
SaveBufferToFileFront(size_t tagCursor,uint32_t len)401 bool 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
LoadBufferFormFile(size_t size)426 bool 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