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
24extern "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
33typedef 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
49unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag);
50
51#define BEGIN_TLV_STRUCT_DEFINE(TlvS, CheckTag) \
52void 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) \
77typedef struct \
78{ \
79    TlvBase base; \
80    TypeName data; \
81} TlvName;
82
83DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt32, int)
84DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt16, short)
85DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt8, char)
86DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint32, uint32_t)
87DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint16, uint16_t)
88DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint8, uint8_t)
89DECLARE_TLV_FIX_LENGTH_TYPE(TlvUint64, uint64_t)
90DECLARE_TLV_FIX_LENGTH_TYPE(TlvInt64, uint64_t)
91
92#define DEFINE_TLV_FIX_LENGTH_TYPE(TlvName, Revert) \
93int32_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\
117int32_t GetLenTlv##TlvName(TlvBase *tlv) \
118{ \
119    TlvName *realTlv = (TlvName *)(tlv); \
120    return (int32_t)sizeof(realTlv->data); \
121} \
122\
123int32_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\
141DECLARE_TLV_PARSE_FUNC(TlvName, ParseTlv##TlvName, GetLenTlv##TlvName, EncodeTlv##TlvName);
142
143void DeinitTlvFixMember(TlvBase *tlv);
144
145#define DECLARE_TLV_PARSE_FUNC(TlvName, TlvParseFunc, TlvGetLenFunc, TlvEncodeFunc) \
146void 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));
159typedef struct {
160    TlvBase base;
161    unsigned int offsetCount;
162    unsigned int offset[0];
163} TlvOffsetExample;
164
165HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel);
166int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict);
167int32_t GetlenTlvNode(TlvBase *tlv);
168void DeinitTlvNode(TlvBase *tlv);
169
170int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict);
171int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel);
172int32_t GetLenTlvStruct(TlvBase *tlv);
173void DeinitTlvStruct(TlvBase *tlv);
174int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot);
175HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict);
176HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel);
177
178typedef struct {
179    TlvBase base;
180    HcParcel data;
181} TlvBuffer;
182
183void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag);
184int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict);
185int32_t GetlenTlvBuffer(TlvBase *tlv);
186int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel);
187void DeinitTlvBuffer(TlvBase *tlv);
188
189typedef struct {
190    TlvBase base;
191    HcString data;
192} TlvString;
193
194void InitTlvString(TlvString *tlv, unsigned short checkTag);
195int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict);
196int32_t GetlenTlvString(TlvBase *tlv);
197int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel);
198void DeinitTlvString(TlvBase *tlv);
199
200#define DECLEAR_INIT_FUNC(TlvStruct) \
201void Init##TlvStruct(TlvStruct *tlv, unsigned short checkTag);
202
203DECLEAR_INIT_FUNC(TlvUint64)
204DECLEAR_INIT_FUNC(TlvUint32)
205DECLEAR_INIT_FUNC(TlvUint16)
206DECLEAR_INIT_FUNC(TlvUint8)
207DECLEAR_INIT_FUNC(TlvInt64)
208DECLEAR_INIT_FUNC(TlvInt32)
209DECLEAR_INIT_FUNC(TlvInt16)
210DECLEAR_INIT_FUNC(TlvInt8)
211
212#define DECLARE_TLV_VECTOR(TlvVecName, TlvVecElement) \
213DECLARE_HC_VECTOR(Vec##TlvVecName, TlvVecElement) \
214typedef struct { \
215    TlvBase base; \
216    Vec##TlvVecName data; \
217} TlvVecName; \
218void DeinitTlv##TlvVecName(TlvBase *tlv); \
219void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag);
220
221#define IMPLEMENT_TLV_VECTOR(TlvVecName, TlvElementName, VecAllocCount) \
222IMPLEMENT_HC_VECTOR(Vec##TlvVecName, TlvElementName, VecAllocCount) \
223int32_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\
253int32_t EncodeTlv##TlvVecName(TlvBase *tlv, HcParcel *parcel) \
254{ \
255    TlvVecName *realTlv = (TlvVecName *)(tlv); \
256    uint32_t index = 0; \
257    TlvElementName *element = NULL; \
258    int32_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            int32_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} \
275int32_t GetLenTlv##TlvVecName(TlvBase *tlv) \
276{ \
277    TlvVecName *realTlv = (TlvVecName *)(tlv); \
278    uint32_t index = 0; \
279    TlvElementName *element = NULL; \
280    int32_t totalLen = sizeof(int32_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\
294void 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\
307void 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