• 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 #ifndef HC_TLV_PARSER_H
17 #define HC_TLV_PARSER_H
18 
19 #include <hc_parcel.h>
20 #include <hc_vector.h>
21 #include <hc_string.h>
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 #define USE_DEFAULT_TAG 0xFFFF
28 #define TLV_FAIL (-1)
29 #define NO_REVERT 0
30 #define NEED_REVERT 1
31 #define MAX_TOTOL_LEN (100 * 1024 * 1024)
32 
33 typedef struct TlvBaseT {
34     unsigned short tag;
35     unsigned short length;
36     unsigned short checkTag;
37     unsigned short hasValue;
38     int32_t (*parse)(struct TlvBaseT *, HcParcel *, HcBool);
39     int32_t (*getlen)(struct TlvBaseT *);
40     int32_t (*encode)(struct TlvBaseT *, HcParcel *);
41     void (*deinit)(struct TlvBaseT *);
42 } TlvBase;
43 
44 #define DECLARE_TLV_STRUCT(x) \
45     TlvBase base; \
46     unsigned int offsetCount; \
47     unsigned int offset[x];
48 
49 unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag);
50 
51 #define BEGIN_TLV_STRUCT_DEFINE(TlvS, CheckTag) \
52 void Init##TlvS(TlvS *tlv, unsigned short checkTag) \
53 { \
54     typedef TlvS TlvStructType; \
55     unsigned int index = 0; \
56     (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \
57     tlv->base.checkTag = GetTag(checkTag, CheckTag);
58 
59 #define TLV_MEMBER_OPTION(TlvMember, TlvMemberName, CheckTag) \
60     Init##TlvMember(&tlv->TlvMemberName, CheckTag); \
61     tlv->TlvMemberName.base.option = 1; \
62     tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName);
63 
64 #define TLV_MEMBER(TlvMember, TlvMemberName, CheckTag) \
65     Init##TlvMember(&tlv->TlvMemberName, CheckTag); \
66     tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName);
67 
68 #define END_TLV_STRUCT_DEFINE(void) \
69     tlv->offsetCount = index; \
70     tlv->base.parse = ParseTlvStruct; \
71     tlv->base.getlen = GetLenTlvStruct; \
72     tlv->base.encode = EncodeTlvStruct; \
73     tlv->base.deinit = DeinitTlvStruct; \
74 }
75 
76 #define DECLARE_TLV_FIX_LENGTH_TYPE(TlvName, TypeName) \
77 typedef struct \
78 { \
79     TlvBase base; \
80     TypeName data; \
81 } TlvName;
82 
83 DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt32, int)
84 DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt16, short)
85 DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt8, char)
86 DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint32, uint32_t)
87 DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint16, uint16_t)
88 DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint8, uint8_t)
89 DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint64, uint64_t)
90 DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt64, uint64_t)
91 
92 #define DEFINE_TLV_FIX_LENGTH_TYPE(TlvName, Revert) \
93 int32_t ParseTlv##TlvName(TlvBase *tlv, HcParcel *parcel, HcBool strict) \
94 { \
95     (void)strict; \
96     TlvName *realTlv = (TlvName *)(tlv); \
97     HcBool readRet = HC_FALSE; \
98     if (tlv->length != sizeof(realTlv->data)) \
99     { \
100         return TLV_FAIL; \
101     } \
102 \
103     if (Revert) \
104     { \
105         readRet = ParcelReadRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \
106     } else { \
107         readRet = ParcelRead(parcel, &realTlv->data, sizeof(realTlv->data)); \
108     } \
109     if (readRet) \
110     { \
111         return tlv->length; \
112     } else { \
113         return TLV_FAIL; \
114     } \
115 } \
116 \
117 int32_t GetLenTlv##TlvName(TlvBase *tlv) \
118 { \
119     TlvName *realTlv = (TlvName *)(tlv); \
120     return (int32_t)sizeof(realTlv->data); \
121 } \
122 \
123 int32_t EncodeTlv##TlvName(TlvBase *tlv, HcParcel *parcel) \
124 { \
125     HcBool writeRet = HC_FALSE; \
126     TlvName *realTlv = (TlvName *)(tlv); \
127     if (Revert) \
128     { \
129         writeRet = ParcelWriteRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \
130     } else { \
131         writeRet = ParcelWrite(parcel, &realTlv->data, sizeof(realTlv->data)); \
132     } \
133     if (writeRet) \
134     { \
135         return sizeof(realTlv->data); \
136     } else { \
137         return TLV_FAIL; \
138     } \
139 } \
140 \
141 DECLARE_TLV_PARSE_FUNC(TlvName, ParseTlv##TlvName, GetLenTlv##TlvName, EncodeTlv##TlvName);
142 
143 void DeinitTlvFixMember(TlvBase *tlv);
144 
145 #define DECLARE_TLV_PARSE_FUNC(TlvName, TlvParseFunc, TlvGetLenFunc, TlvEncodeFunc) \
146 void Init##TlvName(TlvName *tlv, unsigned short checkTag) \
147 { \
148     (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \
149     tlv->base.parse = TlvParseFunc; \
150     tlv->base.getlen = TlvGetLenFunc; \
151     tlv->base.encode = TlvEncodeFunc; \
152     tlv->base.deinit = DeinitTlvFixMember; \
153     tlv->base.checkTag = checkTag; \
154 }
155 
156 #define TLV_INIT(TlvName, TlvData) Init##TlvName(TlvData, USE_DEFAULT_TAG);
157 
158 #define TLV_DEINIT(TlvData) TlvData.base.deinit((TlvBase *)(&TlvData));
159 typedef struct {
160     TlvBase base;
161     unsigned int offsetCount;
162     unsigned int offset[0];
163 } TlvOffsetExample;
164 
165 HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel);
166 int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict);
167 int32_t GetlenTlvNode(TlvBase *tlv);
168 void DeinitTlvNode(TlvBase *tlv);
169 
170 int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict);
171 int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel);
172 int32_t GetLenTlvStruct(TlvBase *tlv);
173 void DeinitTlvStruct(TlvBase *tlv);
174 int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot);
175 HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict);
176 HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel);
177 
178 typedef struct {
179     TlvBase base;
180     HcParcel data;
181 } TlvBuffer;
182 
183 void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag);
184 int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict);
185 int32_t GetlenTlvBuffer(TlvBase *tlv);
186 int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel);
187 void DeinitTlvBuffer(TlvBase *tlv);
188 
189 typedef struct {
190     TlvBase base;
191     HcString data;
192 } TlvString;
193 
194 void InitTlvString(TlvString *tlv, unsigned short checkTag);
195 int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict);
196 int32_t GetlenTlvString(TlvBase *tlv);
197 int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel);
198 void DeinitTlvString(TlvBase *tlv);
199 
200 #define DECLEAR_INIT_FUNC(TlvStruct) \
201 void Init##TlvStruct(TlvStruct *tlv, unsigned short checkTag);
202 
203 DECLEAR_INIT_FUNC(TlvUint64)
204 DECLEAR_INIT_FUNC(TlvUint32)
205 DECLEAR_INIT_FUNC(TlvUint16)
206 DECLEAR_INIT_FUNC(TlvUint8)
207 DECLEAR_INIT_FUNC(TlvInt64)
208 DECLEAR_INIT_FUNC(TlvInt32)
209 DECLEAR_INIT_FUNC(TlvInt16)
210 DECLEAR_INIT_FUNC(TlvInt8)
211 
212 #define DECLARE_TLV_VECTOR(TlvVecName, TlvVecElement) \
213 DECLARE_HC_VECTOR(Vec##TlvVecName, TlvVecElement) \
214 typedef struct { \
215     TlvBase base; \
216     Vec##TlvVecName data; \
217 } TlvVecName; \
218 void DeinitTlv##TlvVecName(TlvBase *tlv); \
219 void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag);
220 
221 #define IMPLEMENT_TLV_VECTOR(TlvVecName, TlvElementName, VecAllocCount) \
222 IMPLEMENT_HC_VECTOR(Vec##TlvVecName, TlvElementName, VecAllocCount) \
223 int32_t ParseTlv##TlvVecName(TlvBase *tlv, HcParcel *parcel, HcBool strict) \
224 { \
225     TlvVecName *realTlv = (TlvVecName *)(tlv); \
226     uint32_t count = 0; \
227     if (!ParcelReadUint32(parcel, &count)) { \
228         return TLV_FAIL; \
229     } \
230     int32_t totalLen = sizeof(count); \
231     uint32_t index = 0; \
232     for (index = 0; index < count; ++index) { \
233         TlvElementName tlvElement; \
234         TlvElementName *curElement = realTlv->data.pushBack(&realTlv->data, &tlvElement); \
235         if (curElement == NULL) { \
236             return TLV_FAIL; \
237         } \
238         TLV_INIT(TlvElementName, curElement); \
239 \
240         int32_t elementLen = ParseTlvNode((TlvBase *)curElement, parcel, strict); \
241         if (elementLen < 0) { \
242             return TLV_FAIL; \
243         } \
244         totalLen += elementLen; \
245         if (totalLen >= MAX_TOTOL_LEN) { \
246             return TLV_FAIL; \
247         } \
248     } \
249 \
250     return totalLen; \
251 } \
252 \
253 int32_t EncodeTlv##TlvVecName(TlvBase *tlv, HcParcel *parcel) \
254 { \
255     TlvVecName *realTlv = (TlvVecName *)(tlv); \
256     uint32_t index = 0; \
257     TlvElementName *element = NULL; \
258     uint32_t totalLen = 4; \
259     uint32_t count = realTlv->data.size(&realTlv->data); \
260     if (!ParcelWriteUint32(parcel, count)) { \
261         return TLV_FAIL; \
262     } \
263 \
264     FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \
265         if (element != NULL) { \
266             uint32_t len = EncodeTlvNode((TlvBase *)element, parcel, HC_FALSE); \
267             totalLen += len; \
268             if (totalLen >= MAX_TOTOL_LEN) { \
269                 return TLV_FAIL; \
270             } \
271         } \
272     } \
273     return totalLen; \
274 } \
275 int32_t GetLenTlv##TlvVecName(TlvBase *tlv) \
276 { \
277     TlvVecName *realTlv = (TlvVecName *)(tlv); \
278     uint32_t index = 0; \
279     TlvElementName *element = NULL; \
280     uint32_t totalLen = sizeof(uint32_t); \
281     FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \
282         if (element != NULL) { \
283             totalLen += GetlenTlvNode((TlvBase *)element); \
284             if (totalLen >= MAX_TOTOL_LEN) { \
285                 return TLV_FAIL; \
286             } \
287         } else { \
288             return TLV_FAIL; \
289         } \
290     } \
291     return totalLen; \
292 } \
293 \
294 void DeinitTlv##TlvVecName(TlvBase *tlv) \
295 { \
296     TlvVecName *realTlv = (TlvVecName *)(tlv); \
297     uint32_t index = 0; \
298     TlvElementName *element = NULL; \
299     FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \
300         if (element != NULL) { \
301             TLV_DEINIT((*element)); \
302         } \
303     } \
304     DESTROY_HC_VECTOR(Vec##TlvVecName, &((TlvVecName *)tlv)->data); \
305 } \
306 \
307 void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag) \
308 { \
309     (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \
310     tlv->base.parse = ParseTlv##TlvVecName; \
311     tlv->base.encode = EncodeTlv##TlvVecName; \
312     tlv->base.getlen = GetLenTlv##TlvVecName; \
313     tlv->base.deinit = DeinitTlv##TlvVecName; \
314     tlv->base.checkTag = checkTag; \
315     tlv->data = CREATE_HC_VECTOR(Vec##TlvVecName); \
316 }
317 
318 #ifdef __cplusplus
319 }
320 #endif
321 #endif
322