1 /*
2 * Copyright (c) 2024 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 #include "tlv_utils.h"
17
18 #include "securec.h"
19 #include "netstack_log.h"
20
21 namespace OHOS::NetStack {
22
23 #define DFX_MSG_FIELD_NUM 30
24 #define BUFFER_MAX_SIZE (1 * 256 * 1024)
25
26 #define TLV_TAG_LEN sizeof(uint32_t)
27 #define TLV_LENGTH_LEN sizeof(uint32_t)
28 #define TLV_TLV_HEAD_LEN (TLV_TAG_LEN + TLV_LENGTH_LEN)
29
GetNextTlv(const uint8_t * buffer)30 uint8_t *TlvUtils::GetNextTlv(const uint8_t *buffer)
31 {
32 return const_cast<uint8_t *>(buffer) + (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ +
33 TLV_TLV_HEAD_LEN;
34 }
35
ParseTlv(const uint8_t * buffer,TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)36 uint8_t *TlvUtils::ParseTlv(const uint8_t *buffer, TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
37 {
38 if (buffer + TLV_TLV_HEAD_LEN > boundary) {
39 *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
40 return nullptr;
41 }
42 if (GetNextTlv(buffer) > boundary) {
43 *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
44 return nullptr;
45 }
46 tlv->tag_ = (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->tag_;
47 tlv->len_ = (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_;
48 tlv->value_ = const_cast<uint8_t *>(buffer) + TLV_TLV_HEAD_LEN;
49 *retCode = TLV_OK;
50 return GetNextTlv(buffer);
51 }
52
AppendTlv(uint8_t * buffer,const TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)53 uint8_t *TlvUtils::AppendTlv(uint8_t *buffer, const TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
54 {
55 if (buffer > boundary) {
56 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
57 return nullptr;
58 }
59 if (buffer + (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ + TLV_TLV_HEAD_LEN > boundary) {
60 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
61 return nullptr;
62 }
63 (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->tag_ = tlv->tag_;
64 (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ = tlv->len_;
65 if (tlv->len_ != 0 && tlv->value_ != nullptr) {
66 if (memcpy_s(buffer + TLV_TLV_HEAD_LEN, boundary - buffer - TLV_TLV_HEAD_LEN, tlv->value_, tlv->len_) !=
67 EOK) {
68 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
69 return nullptr;
70 }
71 }
72 *retCode = TLV_OK;
73 return GetNextTlv(buffer);
74 }
75
Serialize(const TlvCommon * tlv,uint32_t tlvCount,uint8_t * buff,uint32_t maxBuffSize,uint32_t * buffSize)76 uint32_t TlvUtils::Serialize(const TlvCommon *tlv, uint32_t tlvCount, uint8_t *buff, uint32_t maxBuffSize,
77 uint32_t *buffSize)
78 {
79 if (tlv == nullptr || buff == nullptr || buffSize == nullptr) {
80 return TLV_ERR_INVALID_PARA;
81 }
82 uint8_t *curr = buff;
83 uint8_t *boundary = buff + maxBuffSize;
84
85 uint32_t retCode = TLV_OK;
86 for (uint32_t index = 0; index < tlvCount; index++) {
87 curr = AppendTlv(curr, &tlv[index], boundary, &retCode);
88 if (curr == nullptr || retCode != TLV_OK) {
89 return retCode;
90 }
91 }
92 *buffSize = curr - buff;
93 return TLV_OK;
94 }
95
Deserialize(const uint8_t * buff,uint32_t buffSize,TlvCommon * tlv,uint32_t maxTlvCount,uint32_t * tlvCount)96 uint32_t TlvUtils::Deserialize(const uint8_t *buff, uint32_t buffSize, TlvCommon *tlv, uint32_t maxTlvCount,
97 uint32_t *tlvCount)
98 {
99 if (tlv == nullptr || buff == nullptr || tlvCount == nullptr) {
100 return TLV_ERR_INVALID_PARA;
101 }
102
103 auto *msg = const_cast<uint8_t *>(buff);
104 const uint8_t *boundary = buff + buffSize;
105 uint32_t index = 0;
106
107 while (msg != nullptr) {
108 if (index >= maxTlvCount) {
109 return TLV_ERR_BUFF_NO_ENOUGH;
110 }
111 uint32_t retCode = TLV_OK;
112 msg = ParseTlv(msg, &tlv[index], boundary, &retCode);
113 if (msg == nullptr || retCode != TLV_OK) {
114 break;
115 }
116 index++;
117 }
118 *tlvCount = index;
119 return TLV_OK;
120 }
121
GenerateTlv(DfxMessage & msg,TlvCommon * tlvs,uint32_t * tlvCount)122 uint32_t TlvUtils::GenerateTlv(DfxMessage &msg, TlvCommon *tlvs, uint32_t *tlvCount)
123 {
124 uint32_t index = 0;
125 tlvs[index++] = TlvCommon{U64, sizeof(msg.requestBeginTime_), &msg.requestBeginTime_};
126 tlvs[index++] = TlvCommon{U64, sizeof(msg.dnsEndTime_), &msg.dnsEndTime_};
127 tlvs[index++] = TlvCommon{U64, sizeof(msg.tcpConnectEndTime_), &msg.tcpConnectEndTime_};
128 tlvs[index++] = TlvCommon{U64, sizeof(msg.tlsHandshakeEndTime_), &msg.tlsHandshakeEndTime_};
129 tlvs[index++] = TlvCommon{U64, sizeof(msg.firstSendTime_), &msg.firstSendTime_};
130 tlvs[index++] = TlvCommon{U64, sizeof(msg.firstRecvTime_), &msg.firstRecvTime_};
131 tlvs[index++] = TlvCommon{U64, sizeof(msg.requestEndTime_), &msg.requestEndTime_};
132 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestId_.size()),
133 const_cast<char *>(msg.requestId_.data())};
134 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestUrl_.size()),
135 const_cast<char *>(msg.requestUrl_.data())};
136 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestMethod_.size()),
137 const_cast<char *>(msg.requestMethod_.data())};
138 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestHeader_.size()),
139 const_cast<char *>(msg.requestHeader_.data())};
140 tlvs[index++] = TlvCommon{U32, sizeof(msg.responseStatusCode_), &msg.responseStatusCode_};
141 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseHeader_.size()),
142 const_cast<char *>(msg.responseHeader_.data())};
143 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseEffectiveUrl_.size()),
144 const_cast<char *>(msg.responseEffectiveUrl_.data())};
145 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseIpAddress_.size()),
146 const_cast<char *>(msg.responseIpAddress_.data())};
147 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseHttpVersion_.size()),
148 const_cast<char *>(msg.responseHttpVersion_.data())};
149 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseReasonPhrase_.size()),
150 const_cast<char *>(msg.responseReasonPhrase_.data())};
151 tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseBody_.size()),
152 const_cast<char *>(msg.responseBody_.data())};
153 *tlvCount = index;
154 return TLV_OK;
155 }
156
Parse(DfxMessage & msg,TlvCommon * tlvs,uint32_t tlvCount)157 uint32_t TlvUtils::Parse(DfxMessage &msg, TlvCommon *tlvs, uint32_t tlvCount)
158 {
159 uint32_t index = 0;
160 msg.requestBeginTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
161 msg.dnsEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
162 msg.tcpConnectEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
163 msg.tlsHandshakeEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
164 msg.firstSendTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
165 msg.firstRecvTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
166 msg.requestEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
167 msg.requestId_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
168 index++;
169 msg.requestUrl_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
170 index++;
171 msg.requestMethod_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
172 index++;
173 msg.requestHeader_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
174 index++;
175 msg.responseStatusCode_ = *(static_cast<uint32_t *>(tlvs[index].value_));
176 index++;
177 msg.responseHeader_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
178 index++;
179 msg.responseEffectiveUrl_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
180 index++;
181 msg.responseIpAddress_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
182 index++;
183 msg.responseHttpVersion_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
184 index++;
185 msg.responseReasonPhrase_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
186 index++;
187 msg.responseBody_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
188 index++;
189 if (index != tlvCount) {
190 return TLV_ERR_PARSE_PAYLOAD_ERR;
191 }
192 return TLV_OK;
193 }
194
Encode(DfxMessage & msg,void * data,uint32_t & dataSize)195 uint32_t TlvUtils::Encode(DfxMessage &msg, void *data, uint32_t &dataSize)
196 {
197 void *tlvsTemp = malloc(sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
198 if (tlvsTemp == nullptr) {
199 NETSTACK_LOGE("tlv encode malloc tlvList failed");
200 return TLV_ERR;
201 }
202 auto *tlvs = static_cast<TlvCommon *>(tlvsTemp);
203 (void) memset_s(&tlvs[0], sizeof(TlvCommon) * DFX_MSG_FIELD_NUM, 0,
204 sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
205 uint32_t fieldCount = 0;
206 GenerateTlv(msg, tlvs, &fieldCount);
207
208 if (data == nullptr) {
209 data = malloc(BUFFER_MAX_SIZE);
210 if (data == nullptr) {
211 NETSTACK_LOGE("tlv encode malloc data failed");
212 free(tlvsTemp);
213 return TLV_ERR;
214 }
215 }
216 (void) memset_s(data, BUFFER_MAX_SIZE, 0, BUFFER_MAX_SIZE);
217 uint32_t ret = Serialize(tlvs, fieldCount, static_cast<uint8_t *>(data), BUFFER_MAX_SIZE,
218 &dataSize);
219 free(tlvsTemp);
220 NETSTACK_LOGI("tlv encode finished. code=%{public}u", ret);
221 return ret;
222 }
223
Decode(DfxMessage & msg,void * data,uint32_t dataSize)224 uint32_t TlvUtils::Decode(DfxMessage &msg, void *data, uint32_t dataSize)
225 {
226 if (data == nullptr || dataSize == 0) {
227 NETSTACK_LOGE("tlv decode invalid params");
228 return TLV_ERR_INVALID_PARA;
229 }
230 void *tlvsTemp = malloc(sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
231 if (tlvsTemp == nullptr) {
232 NETSTACK_LOGE("tlv decode malloc tlvList failed");
233 return TLV_ERR;
234 }
235 auto *tlvs = static_cast<TlvCommon *>(tlvsTemp);
236 (void) memset_s(&tlvs[0], sizeof(TlvCommon) * DFX_MSG_FIELD_NUM, 0,
237 sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
238 uint32_t fieldCount = 0;
239 auto ret = Deserialize(static_cast<uint8_t *>(data), dataSize, tlvs, DFX_MSG_FIELD_NUM, &fieldCount);
240 Parse(msg, tlvs, fieldCount);
241 free(tlvsTemp);
242 NETSTACK_LOGI("tlv decode finished. code=%{public}u", ret);
243 return ret;
244 }
245 }