• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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