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's size=%{public}zu", tag,
135 value.size());
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's size=%{public}zu", tag,
145 value.size());
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 delete want;
263 return true;
264 }
265
Write(TAG tag,const std::monostate & value)266 bool TLVObject::Write(TAG tag, const std::monostate &value)
267 {
268 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0);
269 }
270
Read(std::monostate & value,const TLVHead & head)271 bool TLVObject::Read(std::monostate &value, const TLVHead &head)
272 {
273 return true;
274 }
275
Write(TAG tag,const void * value)276 bool TLVObject::Write(TAG tag, const void *value)
277 {
278 return WriteHead(static_cast<uint16_t>(tag), (uint32_t)0);
279 }
280
281
Read(void * value,const TLVHead & head)282 bool TLVObject::Read(void *value, const TLVHead &head)
283 {
284 value = nullptr;
285 return true;
286 }
287
CountHead()288 size_t TLVObject::CountHead()
289 {
290 total_ += sizeof(TLVHead);
291 return sizeof(TLVHead);
292 }
293
WriteHead(uint16_t tag,uint32_t len)294 bool TLVObject::WriteHead(uint16_t tag, uint32_t len)
295 {
296 if (!HasExpectBuffer(sizeof(TLVHead))) {
297 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write head. tag=%{public}hu", tag);
298 return false;
299 }
300 PrepareBufferForFile(sizeof(TLVHead));
301 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor());
302 tlvHead->tag = HostToNet(tag);
303 tlvHead->len = HostToNet(len);
304 cursor_ += sizeof(TLVHead);
305 return SaveBufferToFile();
306 }
307
WriteBackHead(uint16_t tag,size_t tagCursor,uint32_t len)308 bool TLVObject::WriteBackHead(uint16_t tag, size_t tagCursor, uint32_t len)
309 {
310 auto startCursor = buffer_->data();
311 if (file_ == nullptr) {
312 startCursor += tagCursor;
313 }
314 auto tlvHead = reinterpret_cast<TLVHead *>(startCursor);
315 tlvHead->tag = HostToNet(tag);
316 tlvHead->len = HostToNet(len);
317 return SaveBufferToFileFront(tagCursor, sizeof(TLVHead));
318 }
319
ReadHead(TLVHead & head)320 bool TLVObject::ReadHead(TLVHead &head)
321 {
322 if (!HasExpectBuffer(sizeof(TLVHead))) {
323 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read head. tag=%{public}hu", head.tag);
324 return false;
325 }
326 if (!LoadBufferFormFile(sizeof(TLVHead))) {
327 LOG_ERROR(UDMF_FRAMEWORK, "LoadBufferFormFile error in tlv read head. tag=%{public}hu", head.tag);
328 return false;
329 }
330 auto startCursor = GetStartCursor();
331 const auto *pHead = reinterpret_cast<const TLVHead *>(startCursor);
332 auto len = NetToHost(pHead->len);
333 if (file_ == nullptr) {
334 if (!HasExpectBuffer(len + sizeof(TLVHead))) {
335 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv read head and len. tag=%{public}hu", head.tag);
336 return false;
337 }
338 }
339
340 head.tag = NetToHost(pHead->tag);
341 head.len = len;
342 cursor_ += sizeof(TLVHead);
343 return true;
344 }
345
Skip(TLVHead & head)346 bool TLVObject::Skip(TLVHead &head)
347 {
348 if (file_ != nullptr) {
349 cursor_ += head.len;
350 return fseek(file_, head.len * sizeof(uint8_t), SEEK_CUR) == 0;
351 }
352 if (total_ < head.len || total_ - head.len < cursor_) {
353 LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv skip. tag=%{public}hu", head.tag);
354 return false;
355 }
356 cursor_ += head.len;
357 return true;
358 }
359
HasExpectBuffer(const uint32_t expectLen) const360 bool TLVObject::HasExpectBuffer(const uint32_t expectLen) const
361 {
362 if (buffer_ == nullptr) {
363 return false;
364 }
365 if (file_ != nullptr) {
366 buffer_->resize(expectLen);
367 return true;
368 }
369 return buffer_->size() >= cursor_ && buffer_->size() - cursor_ >= expectLen;
370 }
371
PrepareBufferForFile(size_t size)372 void TLVObject::PrepareBufferForFile(size_t size)
373 {
374 if (file_ == nullptr) {
375 return;
376 }
377 buffer_->resize(size);
378 }
379
GetStartCursor()380 std::uint8_t *TLVObject::GetStartCursor()
381 {
382 auto startCursor = buffer_->data();
383 if (file_ == nullptr) {
384 startCursor += cursor_;
385 }
386 return startCursor;
387 }
388
SaveBufferToFile()389 bool TLVObject::SaveBufferToFile()
390 {
391 if (file_ == nullptr) {
392 return true;
393 }
394 auto count = fwrite(buffer_->data(), sizeof(uint8_t), buffer_->size(), file_);
395 if (count != buffer_->size()) {
396 LOG_ERROR(UDMF_FRAMEWORK, "fwrite error!");
397 return false;
398 }
399 return true;
400 }
401
SaveBufferToFileFront(size_t tagCursor,uint32_t len)402 bool TLVObject::SaveBufferToFileFront(size_t tagCursor, uint32_t len)
403 {
404 if (file_ == nullptr) {
405 return true;
406 }
407 int32_t leftOffset =
408 -((static_cast<int32_t>(cursor_) - static_cast<int32_t>(tagCursor))) * static_cast<int32_t>(sizeof(uint8_t));
409 if (fseek(file_, leftOffset * sizeof(uint8_t), SEEK_CUR) != 0) {
410 LOG_ERROR(UDMF_FRAMEWORK, "file fseek left error!");
411 return false;
412 }
413 auto count = fwrite(buffer_->data(), sizeof(uint8_t), sizeof(TLVHead), file_);
414 if (count != sizeof(TLVHead)) {
415 LOG_ERROR(UDMF_FRAMEWORK, "file write error!");
416 return false;
417 }
418 int32_t rightOffset =
419 static_cast<int32_t>(cursor_) - static_cast<int32_t>(tagCursor) - static_cast<int32_t>(sizeof(TLVHead));
420 if (fseek(file_, rightOffset * sizeof(uint8_t), SEEK_CUR) != 0) {
421 LOG_ERROR(UDMF_FRAMEWORK, "file fseek right error!");
422 return false;
423 }
424 return true;
425 }
426
LoadBufferFormFile(size_t size)427 bool TLVObject::LoadBufferFormFile(size_t size)
428 {
429 if (file_ == nullptr) {
430 return true;
431 }
432 auto count = fread(buffer_->data(), sizeof(uint8_t), buffer_->size(), file_);
433 if (count != buffer_->size()) {
434 return false;
435 }
436 return true;
437 }
438 } // namespace UDMF
439 } // namespace OHOS
440