• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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