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