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 "session_data_header.h"
17 #include "dtbcollabmgr_log.h"
18 #include <optional>
19 #include "securec.h"
20
21 namespace OHOS {
22 namespace DistributedCollab {
23 namespace {
24 static constexpr uint32_t DSCHED_SHIFT_8 = 8;
25 static constexpr uint16_t UINT16_SHIFT_MASK_0 = 0x00ff;
26 static const std::string TAG = "DSchedCollabSessionDataHeader";
27 const std::map<uint16_t, uint32_t> HEADER_LEN_VERSION_MAP = {
28 { SessionDataHeader::PROTOCOL_VERSION, SessionDataHeader::HEADER_LEN }
29 };
30 }
31
Serialize()32 std::unique_ptr<AVTransDataBuffer> SessionDataHeader::Serialize()
33 {
34 std::unique_ptr<AVTransDataBuffer> buffer = std::make_unique<AVTransDataBuffer>(HEADER_LEN);
35
36 uint8_t* header = buffer->Data();
37 uint32_t bufLen = HEADER_LEN;
38 uint32_t itemCapacity = 0;
39
40 itemCapacity = WriteVersion(header, bufLen);
41 header += itemCapacity;
42 bufLen -= itemCapacity;
43
44 itemCapacity = WriteFragFlag(header, bufLen);
45 header += itemCapacity;
46 bufLen -= itemCapacity;
47
48 itemCapacity = WriteDataType(header, bufLen);
49 header += itemCapacity;
50 bufLen -= itemCapacity;
51
52 itemCapacity = WriteSeqNum(header, bufLen);
53 header += itemCapacity;
54 bufLen -= itemCapacity;
55
56 itemCapacity = WriteTotalLen(header, bufLen);
57 header += itemCapacity;
58 bufLen -= itemCapacity;
59
60 itemCapacity = WritePacketLen(header, bufLen);
61 header += itemCapacity;
62 bufLen -= itemCapacity;
63
64 itemCapacity = WritePayloadLen(header, bufLen);
65 header += itemCapacity;
66 bufLen -= itemCapacity;
67
68 itemCapacity = WriteSubSeq(header, bufLen);
69 return buffer;
70 }
71
WriteVersion(uint8_t * header,const uint32_t bufLen)72 inline uint32_t SessionDataHeader::WriteVersion(uint8_t* header, const uint32_t bufLen)
73 {
74 TlvItem item = { TLV_TYPE::TLV_TYPE_VERSION, sizeof(version_), version_ };
75 WriteTlvItemToBuffer(item, header, bufLen);
76 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(version_);
77 }
78
WriteFragFlag(uint8_t * header,const uint32_t bufLen)79 inline uint32_t SessionDataHeader::WriteFragFlag(uint8_t* header, const uint32_t bufLen)
80 {
81 TlvItem item = { TLV_TYPE::TLV_TYPE_FRAG_FLAG, sizeof(fragFlag_), static_cast<uint8_t>(fragFlag_) };
82 WriteTlvItemToBuffer(item, header, bufLen);
83 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(fragFlag_);
84 }
85
WriteDataType(uint8_t * header,const uint32_t bufLen)86 inline uint32_t SessionDataHeader::WriteDataType(uint8_t* header, const uint32_t bufLen)
87 {
88 TlvItem item = { TLV_TYPE::TLV_TYPE_DATA_TYPE, sizeof(dataType_), dataType_ };
89 WriteTlvItemToBuffer(item, header, bufLen);
90 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(dataType_);
91 }
92
WriteSeqNum(uint8_t * header,const uint32_t bufLen)93 inline uint32_t SessionDataHeader::WriteSeqNum(uint8_t* header, const uint32_t bufLen)
94 {
95 TlvItem item = { TLV_TYPE::TLV_TYPE_SEQ_NUM, sizeof(seqNum_), seqNum_ };
96 WriteTlvItemToBuffer(item, header, bufLen);
97 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(seqNum_);
98 }
99
WriteTotalLen(uint8_t * header,const uint32_t bufLen)100 inline uint32_t SessionDataHeader::WriteTotalLen(uint8_t* header, const uint32_t bufLen)
101 {
102 TlvItem item = { TLV_TYPE::TLV_TYPE_TOTAL_LEN, sizeof(totalLen_), totalLen_ };
103 WriteTlvItemToBuffer(item, header, bufLen);
104 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(totalLen_);
105 }
106
WriteSubSeq(uint8_t * header,const uint32_t bufLen)107 inline uint32_t SessionDataHeader::WriteSubSeq(uint8_t* header, const uint32_t bufLen)
108 {
109 TlvItem item = { TLV_TYPE::TLV_TYPE_SUB_SEQ, sizeof(subSeq_), subSeq_ };
110 WriteTlvItemToBuffer(item, header, bufLen);
111 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(subSeq_);
112 }
113
WritePayloadLen(uint8_t * header,const uint32_t bufLen)114 inline uint32_t SessionDataHeader::WritePayloadLen(uint8_t* header, const uint32_t bufLen)
115 {
116 TlvItem item = { TLV_TYPE::TLV_TYPE_PAYLOAD_LEN, sizeof(payloadLen_), payloadLen_ };
117 WriteTlvItemToBuffer(item, header, bufLen);
118 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(payloadLen_);
119 }
120
WritePacketLen(uint8_t * header,const uint32_t bufLen)121 inline uint32_t SessionDataHeader::WritePacketLen(uint8_t* header, const uint32_t bufLen)
122 {
123 TlvItem item = { TLV_TYPE::TLV_TYPE_PACKET_LEN, sizeof(packetLen_), packetLen_ };
124 WriteTlvItemToBuffer(item, header, bufLen);
125 return TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + sizeof(packetLen_);
126 }
127
WriteTlvItemToBuffer(const TlvItem & tlvItem,uint8_t * header,const uint32_t bufLen)128 int32_t SessionDataHeader::WriteTlvItemToBuffer(const TlvItem& tlvItem,
129 uint8_t* header, const uint32_t bufLen)
130 {
131 uint8_t* current = header;
132 uint16_t typeInt = static_cast<uint16_t>(tlvItem.type);
133 *current++ = typeInt >> DSCHED_SHIFT_8;
134 *current++ = typeInt & UINT16_SHIFT_MASK_0;
135 *current++ = tlvItem.len >> DSCHED_SHIFT_8;
136 *current++ = tlvItem.len & UINT16_SHIFT_MASK_0;
137
138 int32_t ret = memcpy_s(current,
139 bufLen - (current - header),
140 &tlvItem.value, tlvItem.len);
141 if (ret != EOK) {
142 HILOGE("copy tlv value failed!, ret %{public}d", ret);
143 return WRITE_TLV_ITEM_TO_BUFFER_FAILED;
144 }
145 return ERR_OK;
146 }
147
Deserialize(const uint8_t * buffer,const size_t bufLen)148 std::optional<SessionDataHeader> SessionDataHeader::Deserialize(const uint8_t* buffer, const size_t bufLen)
149 {
150 if (buffer == nullptr || bufLen < HEADER_LEN) {
151 HILOGE("invalid buffer to deserialize");
152 return std::nullopt;
153 }
154 SessionDataHeader sessionHeader;
155 uint8_t* header = const_cast<uint8_t*>(buffer);
156 uint8_t* current = header;
157 uint8_t* end = header + BASE_HEADER_LEN;
158 // move pointer to read each tlv item by base session header
159 TlvItem item;
160 while (current + TlvItem::HEADER_LEN_BYTES + TlvItem::HEADER_TYPE_BYTES < end) {
161 if (sessionHeader.ReadTlvItemFromBuffer(item, sessionHeader, current, end) != ERR_OK) {
162 HILOGE("read tlv item failed");
163 return std::nullopt;
164 }
165 // move pointer by each item
166 current += (TlvItem::HEADER_LEN_BYTES + TlvItem::HEADER_TYPE_BYTES);
167 current += item.len;
168 }
169 if (sessionHeader.payloadLen_ > SessionDataHeader::BINARY_PAYLOAD_MAX_LEN
170 || sessionHeader.packetLen_ > SessionDataHeader::BINARY_DATA_MAX_TOTAL_LEN) {
171 HILOGE("invalid param");
172 return std::nullopt;
173 }
174 if (sessionHeader.totalLen_ < sessionHeader.packetLen_) {
175 HILOGE("totalLen too small");
176 return std::nullopt;
177 }
178 // verify header, maybe higher version
179 uint32_t headerLen = 0;
180 auto versionIt = HEADER_LEN_VERSION_MAP.find(sessionHeader.version_);
181 if (versionIt == HEADER_LEN_VERSION_MAP.end()) {
182 HILOGW("recv data version higher, %{public}d", sessionHeader.version_);
183 // Get header len with max version
184 auto maxIt = HEADER_LEN_VERSION_MAP.rbegin();
185 headerLen = maxIt->second;
186 } else {
187 headerLen = versionIt->second;
188 }
189 if (sessionHeader.packetLen_ < sessionHeader.payloadLen_ + headerLen) {
190 HILOGE("invalid header, no match version");
191 return std::nullopt;
192 }
193 // deserialize other variables with matching version
194 return sessionHeader;
195 }
196
ReadTlvItemFromBuffer(TlvItem & tlvItem,SessionDataHeader & sessionHeader,const uint8_t * header,const uint8_t * end)197 int32_t SessionDataHeader::ReadTlvItemFromBuffer(TlvItem& tlvItem, SessionDataHeader& sessionHeader,
198 const uint8_t* header, const uint8_t* end)
199 {
200 // assign item format
201 uint8_t* current = const_cast<uint8_t*>(header);
202 tlvItem.type = static_cast<TLV_TYPE>(ReadUint16(current));
203 current += TlvItem::HEADER_TYPE_BYTES;
204 tlvItem.len = ReadUint16(current);
205 current += TlvItem::HEADER_LEN_BYTES;
206
207 if (current + tlvItem.len > end) {
208 HILOGE("reserverd bytes not sufficient");
209 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
210 }
211
212 // assign session current by len
213 int32_t ret = ERR_OK;
214 switch (tlvItem.type) {
215 case TLV_TYPE::TLV_TYPE_VERSION:
216 ret = ReadVersionFromBuffer(sessionHeader, current, tlvItem.len);
217 break;
218
219 case TLV_TYPE::TLV_TYPE_FRAG_FLAG:
220 ret = ReadFragFlagFromBuffer(sessionHeader, current, tlvItem.len);
221 break;
222
223 case TLV_TYPE::TLV_TYPE_DATA_TYPE:
224 ret = ReadDataTypeFromBuffer(sessionHeader, current, tlvItem.len);
225 break;
226
227 case TLV_TYPE::TLV_TYPE_SEQ_NUM:
228 ret = ReadSeqNumFromBuffer(sessionHeader, current, tlvItem.len);
229 break;
230
231 case TLV_TYPE::TLV_TYPE_TOTAL_LEN:
232 ret = ReadTotalLenFromBuffer(sessionHeader, current, tlvItem.len);
233 break;
234
235 case TLV_TYPE::TLV_TYPE_SUB_SEQ:
236 ret = ReadSubSeqFromBuffer(sessionHeader, current, tlvItem.len);
237 break;
238
239 case TLV_TYPE::TLV_TYPE_PAYLOAD_LEN:
240 ret = ReadPayloadLenFromBuffer(sessionHeader, current, tlvItem.len);
241 break;
242
243 case TLV_TYPE::TLV_TYPE_PACKET_LEN:
244 ret = ReadPacketLenFromBuffer(sessionHeader, current, tlvItem.len);
245 break;
246
247 default:
248 HILOGE("invalid data type: %{public}d", static_cast<uint16_t>(tlvItem.type));
249 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
250 }
251
252 return ret;
253 }
254
ReadUint16(const uint8_t * header)255 inline uint16_t SessionDataHeader::ReadUint16(const uint8_t* header)
256 {
257 return (header[0] << DSCHED_SHIFT_8) | header[1];
258 }
259
ReadVersionFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)260 inline int32_t SessionDataHeader::ReadVersionFromBuffer(SessionDataHeader& sessionHeader,
261 const uint8_t* header, const uint32_t len)
262 {
263 int32_t ret = memcpy_s(&sessionHeader.version_, sizeof(sessionHeader.version_), header, len);
264 if (ret != EOK) {
265 HILOGE("Set Version failed");
266 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
267 }
268 return ERR_OK;
269 }
270
ReadFragFlagFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)271 inline int32_t SessionDataHeader::ReadFragFlagFromBuffer(SessionDataHeader& sessionHeader,
272 const uint8_t* header, const uint32_t len)
273 {
274 int32_t ret = memcpy_s(&sessionHeader.fragFlag_, sizeof(sessionHeader.fragFlag_), header, len);
275 if (ret != EOK) {
276 HILOGE("Set FragFlag failed");
277 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
278 }
279 return ERR_OK;
280 }
281
ReadDataTypeFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)282 inline int32_t SessionDataHeader::ReadDataTypeFromBuffer(SessionDataHeader& sessionHeader,
283 const uint8_t* header, const uint32_t len)
284 {
285 int32_t ret = memcpy_s(&sessionHeader.dataType_, sizeof(sessionHeader.dataType_), header, len);
286 if (ret != EOK) {
287 HILOGE("Set DataType failed");
288 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
289 }
290 return ERR_OK;
291 }
292
ReadSeqNumFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)293 inline int32_t SessionDataHeader::ReadSeqNumFromBuffer(SessionDataHeader& sessionHeader,
294 const uint8_t* header, const uint32_t len)
295 {
296 int32_t ret = memcpy_s(&sessionHeader.seqNum_, sizeof(sessionHeader.seqNum_), header, len);
297 if (ret != EOK) {
298 HILOGE("Set SeqNum failed");
299 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
300 }
301 return ERR_OK;
302 }
303
ReadTotalLenFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)304 inline int32_t SessionDataHeader::ReadTotalLenFromBuffer(SessionDataHeader& sessionHeader,
305 const uint8_t* header, const uint32_t len)
306 {
307 int32_t ret = memcpy_s(&sessionHeader.totalLen_, sizeof(sessionHeader.totalLen_), header, len);
308 if (ret != EOK) {
309 HILOGE("Set TotalLen failed");
310 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
311 }
312 return ERR_OK;
313 }
314
ReadSubSeqFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)315 inline int32_t SessionDataHeader::ReadSubSeqFromBuffer(SessionDataHeader& sessionHeader,
316 const uint8_t* header, const uint32_t len)
317 {
318 int32_t ret = memcpy_s(&sessionHeader.subSeq_, sizeof(sessionHeader.subSeq_), header, len);
319 if (ret != EOK) {
320 HILOGE("Set SubSeq failed");
321 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
322 }
323 return ERR_OK;
324 }
325
ReadPayloadLenFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)326 inline int32_t SessionDataHeader::ReadPayloadLenFromBuffer(SessionDataHeader& sessionHeader,
327 const uint8_t* header, const uint32_t len)
328 {
329 int32_t ret = memcpy_s(&sessionHeader.payloadLen_, sizeof(sessionHeader.payloadLen_), header, len);
330 if (ret != EOK) {
331 HILOGE("Set DataLen failed");
332 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
333 }
334 return ERR_OK;
335 }
336
ReadPacketLenFromBuffer(SessionDataHeader & sessionHeader,const uint8_t * header,const uint32_t len)337 inline int32_t SessionDataHeader::ReadPacketLenFromBuffer(SessionDataHeader& sessionHeader,
338 const uint8_t* header, const uint32_t len)
339 {
340 int32_t ret = memcpy_s(&sessionHeader.packetLen_, sizeof(sessionHeader.packetLen_), header, len);
341 if (ret != EOK) {
342 HILOGE("Set DataLen failed");
343 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
344 }
345 return ERR_OK;
346 }
347 } // namespace DistributedCollab
348 } // namespace OHOS