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