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