1 /*
2 * Copyright (C) 2021 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 #include "tlv.h"
17
18 using namespace std;
19
20 namespace Hdc {
21
TlvBuf()22 TlvBuf::TlvBuf()
23 {
24 this->Clear();
25 }
26
TlvBuf(std::set<uint32_t> validtags)27 TlvBuf::TlvBuf(std::set<uint32_t> validtags)
28 {
29 this->Clear();
30 this->mValidTags = validtags;
31 }
32
TlvBuf(const uint8_t * tlvs,const uint32_t size)33 TlvBuf::TlvBuf(const uint8_t *tlvs, const uint32_t size)
34 {
35 this->Clear();
36 if (tlvs == nullptr || size == 0) {
37 WRITE_LOG(LOG_WARN, "invalid tlvs or size, size is %u", size);
38 return;
39 }
40 for (uint32_t pos = 0; pos < size;) {
41 if ((size - pos) < TLV_HEAD_SIZE) {
42 WRITE_LOG(LOG_WARN, "invalid tlvs, size is %u, pos is %d", size, pos);
43 this->Clear();
44 return;
45 }
46 uint32_t tag = *reinterpret_cast<const uint32_t*>(tlvs + pos);
47 pos += sizeof(tag);
48 uint32_t len = *reinterpret_cast<const uint32_t*>(tlvs + pos);
49 pos += sizeof(len);
50 const uint8_t *val = tlvs + pos;
51
52 if (len <= 0 || len > (size - pos)) {
53 WRITE_LOG(LOG_WARN, "invalid tlvs, tag %u, len %u, pos %d, size %u", tag, len, pos, size);
54 this->Clear();
55 return;
56 }
57 if (!this->Append(tag, len, val)) {
58 WRITE_LOG(LOG_WARN, "append tlv failed, tag %u, len %u", tag, len);
59 this->Clear();
60 return;
61 }
62 pos += len;
63 }
64 }
65
TlvBuf(const uint8_t * tlvs,const uint32_t size,const std::set<uint32_t> validtags)66 TlvBuf::TlvBuf(const uint8_t *tlvs, const uint32_t size, const std::set<uint32_t> validtags) : TlvBuf(tlvs, size)
67 {
68 this->mValidTags = validtags;
69 }
70
~TlvBuf()71 TlvBuf::~TlvBuf()
72 {
73 this->Clear();
74 }
75
Clear(void)76 void TlvBuf::Clear(void)
77 {
78 if (this->mTlvMap.empty()) {
79 return;
80 }
81
82 for (auto it = this->mTlvMap.begin(); it != this->mTlvMap.end(); ++it) {
83 it->second.clear();
84 }
85 this->mTlvMap.clear();
86 this->mValidTags.clear();
87 }
88
Append(const uint32_t tag,const string & val)89 bool TlvBuf::Append(const uint32_t tag, const string &val)
90 {
91 return this->Append(tag, val.size(), reinterpret_cast<const uint8_t*>(val.data()));
92 }
93
Append(const uint32_t tag,const uint32_t len,const uint8_t * val)94 bool TlvBuf::Append(const uint32_t tag, const uint32_t len, const uint8_t *val)
95 {
96 if (len == 0 || len > TLV_VALUE_MAX_LEN) {
97 WRITE_LOG(LOG_WARN, "the len is invalid: %u", len);
98 return false;
99 }
100 if (val == nullptr) {
101 WRITE_LOG(LOG_WARN, "the val ptr is null");
102 return false;
103 }
104 if (this->mTlvMap.count(tag) > 0) {
105 WRITE_LOG(LOG_WARN, "duplicate tag is %u", tag);
106 return false;
107 }
108 std::vector<uint8_t> v;
109 v.assign(val, val + len);
110 this->mTlvMap[tag] = v;
111 return true;
112 }
113
FindTlv(const uint32_t tag,uint32_t & len,uint8_t * & val) const114 bool TlvBuf::FindTlv(const uint32_t tag, uint32_t &len, uint8_t *&val) const
115 {
116 auto it = this->mTlvMap.find(tag);
117 if (it == this->mTlvMap.end()) {
118 return false;
119 }
120 auto tlv = it->second;
121 len = tlv.size();
122 if (len == 0 || len > TLV_VALUE_MAX_LEN) {
123 WRITE_LOG(LOG_WARN, "invalid size 0 for tag %u len %u", it->first, len);
124 return false;
125 }
126 val = new (std::nothrow) uint8_t[len];
127 if (val == nullptr) {
128 WRITE_LOG(LOG_WARN, "memory not enough %u", len);
129 return false;
130 }
131 if (memcpy_s(val, len, tlv.data(), tlv.size()) != 0) {
132 WRITE_LOG(LOG_WARN, "memcpy failed, len %u", len);
133 delete[] val;
134 val = nullptr;
135 len = 0;
136 return false;
137 }
138 return true;
139 }
140
FindTlv(const uint32_t tag,string & val) const141 bool TlvBuf::FindTlv(const uint32_t tag, string &val) const
142 {
143 auto it = this->mTlvMap.find(tag);
144 if (it == this->mTlvMap.end()) {
145 return false;
146 }
147 auto tlv = it->second;
148 val.clear();
149 val.assign(tlv.begin(), tlv.end());
150
151 return true;
152 }
153
ContainInvalidTag(void) const154 bool TlvBuf::ContainInvalidTag(void) const
155 {
156 if (this->mTlvMap.empty() || this->mValidTags.empty()) {
157 return false;
158 }
159
160 for (auto it = this->mTlvMap.begin(); it != this->mTlvMap.end(); ++it) {
161 if (this->mValidTags.count(it->first) == 0) {
162 WRITE_LOG(LOG_WARN, "contain invalid tag %u len %u", it->first, it->second.size());
163 return true;
164 }
165 }
166 return false;
167 }
168
GetBufSize(void) const169 uint32_t TlvBuf::GetBufSize(void) const
170 {
171 if (this->mTlvMap.empty()) {
172 return 0;
173 }
174
175 uint32_t size = 0;
176 for (auto it = this->mTlvMap.begin(); it != this->mTlvMap.end(); ++it) {
177 size += TLV_HEAD_SIZE;
178 size += it->second.size();
179 }
180 return size;
181 }
182
CopyToBuf(uint8_t * dst,const uint32_t size) const183 bool TlvBuf::CopyToBuf(uint8_t *dst, const uint32_t size) const
184 {
185 uint32_t mysize = this->GetBufSize();
186 if (dst == nullptr || size < mysize) {
187 WRITE_LOG(LOG_WARN, "invalid buf or size, size is %u my size is %u", size, mysize);
188 return false;
189 }
190
191 uint32_t pos = 0;
192 for (auto it = this->mTlvMap.begin(); it != this->mTlvMap.end(); ++it) {
193 auto tlv = it->second;
194 *reinterpret_cast<uint32_t*>(dst + pos) = it->first;
195 pos += sizeof(uint32_t);
196 *reinterpret_cast<uint32_t*>(dst + pos) = tlv.size();
197 pos += sizeof(uint32_t);
198 if (memcpy_s(dst + pos, size - pos, tlv.data(), tlv.size()) != 0) {
199 WRITE_LOG(LOG_WARN, "memcpy failed, len %u", tlv.size());
200 return false;
201 }
202 pos += tlv.size();
203 }
204 return true;
205 }
206
Display(void) const207 void TlvBuf::Display(void) const
208 {
209 if (this->mTlvMap.empty()) {
210 WRITE_LOG(LOG_INFO, "there is no tlv now");
211 return;
212 }
213 for (auto it = this->mTlvMap.begin(); it != this->mTlvMap.end(); ++it) {
214 WRITE_LOG(LOG_INFO, "tag %u len %u", it->first, it->second.size());
215 }
216 }
217
218 } /* namespace Hdc */
219