• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 STREAM_PACKET_HEADER_H
17 #define STREAM_PACKET_HEADER_H
18 
19 #include <arpa/inet.h>
20 #include <chrono>
21 #include <cstdint>
22 #include <memory>
23 #include <sys/types.h>
24 #include <utility>
25 #include <vector>
26 
27 #include "i_stream.h"
28 #include "securec.h"
29 #include "stream_common.h"
30 #include "trans_log.h"
31 
32 using ::std::chrono::duration_cast;
33 using ::std::chrono::milliseconds;
34 using ::std::chrono::system_clock;
35 
36 namespace Communication {
37 namespace SoftBus {
38 static constexpr int SHIFT = 2;
39 // Align x up to the nearest integer multiple of 2*shift
Align(int x,int shift)40 inline static int Align(int x, int shift)
41 {
42     auto tmpValue = static_cast<unsigned int>(x);
43     auto tmpShift = static_cast<unsigned int>(shift);
44     return static_cast<int>((tmpValue + ((1 << tmpShift) - 1)) & ~((1 << tmpShift) - 1));
45 }
46 
AlignTo4Bytes(int x)47 inline static int AlignTo4Bytes(int x)
48 {
49     return Align(x, SHIFT);
50 }
51 
52 struct CommonHeader {
53     uint8_t version : 2;
54     uint8_t subVersion : 1;
55     uint8_t extFlag : 1;
56     uint8_t streamType : 4;
57     uint8_t marker : 1;
58     uint8_t flag : 1;
59     uint8_t level : 4;
60     uint8_t pad : 2;
61     uint16_t streamId;
62     uint32_t timestamp;
63     uint32_t dataLen;
64     uint16_t seqNum;
65     uint16_t subSeqNum;
66 };
67 
68 struct TypeLength {
69     uint16_t type = 0;
70     uint32_t length = 0;
71 };
72 
73 class TwoLevelsTlv {
74 public:
75     static constexpr int HEADER_LEN = 2;
76     static constexpr int NUMS_LEN = 2;
77     static constexpr int CHECK_SUM_LEN = 4;
78 
TwoLevelsTlv()79     TwoLevelsTlv()
80     {
81         SetTlvVersion(0);
82     }
TwoLevelsTlv(std::unique_ptr<char[]> extBuf,ssize_t extSize)83     TwoLevelsTlv(std::unique_ptr<char[]> extBuf, ssize_t extSize)
84     {
85         SetTlvVersion(0);
86         ext_ = std::move(extBuf);
87         extLen_ = extSize;
88     }
89 
90     virtual ~TwoLevelsTlv() = default;
91 
SetTlvVersion(uint16_t version)92     void SetTlvVersion(uint16_t version)
93     {
94         firstLevelHeader.type |= (static_cast<uint16_t>(version << TopOffset::VERSION_OFFSET) & TopMask::VERSION_MASK);
95     }
96 
GetVersion()97     uint16_t GetVersion() const
98     {
99         return (firstLevelHeader.type & TopMask::VERSION_MASK) >> TopOffset::VERSION_OFFSET;
100     }
101 
Packetize(char * start,ssize_t size,ssize_t offset)102     int Packetize(char *start, ssize_t size, ssize_t offset)
103     {
104         char *pos = new (start + offset) char[size];
105         if (ext_ != nullptr) {
106             auto extTlvAlignSize = HEADER_LEN + NUMS_LEN + AlignTo4Bytes(extLen_);
107             if (AddFrameExtData(pos + HEADER_LEN + NUMS_LEN) != 0) {
108                 return -1;
109             }
110             checkSum_ += static_cast<uint32_t>(extTlvAlignSize);
111         } else {
112             return 0; // 目前假设只有ext,其他option后面添加
113         }
114 
115         checkSum_ += HEADER_LEN + NUMS_LEN;
116 
117         auto tmp = reinterpret_cast<uint16_t *>(pos);
118         *(tmp++) = htons(firstLevelHeader.type);
119         *(tmp++) = htons(firstLevelHeader.length);
120 
121         // size is always bigger than CHECK_SUM_LEN
122         auto checkSumTmp = reinterpret_cast<uint32_t *>(pos + (size - CHECK_SUM_LEN));
123         *checkSumTmp = htonl(checkSum_);
124         return 0;
125     }
126 
Depacketize(char * data,uint32_t size)127     void Depacketize(char *data, uint32_t size)
128     {
129         if (size < sizeof(uint16_t) + sizeof(uint16_t)) {
130             return;
131         }
132         auto tmp = reinterpret_cast<uint16_t *>(data);
133         firstLevelHeader.type = ntohs(*tmp++);
134         firstLevelHeader.length = ntohs(*tmp++);
135 
136         if (firstLevelHeader.type & TopMask::EXT_BUF_MASK) {
137             constexpr uint32_t extFiledNum = 4;
138             if (size < sizeof(uint16_t) * extFiledNum) {
139                 return;
140             }
141             TypeLength tl;
142             tl.type = ntohs(*tmp++);
143             tl.length = ntohs(*tmp++);
144 
145             if (tl.length == 0 ||
146                 sizeof(uint16_t) * extFiledNum + AlignTo4Bytes(tl.length) + sizeof(checkSum_) > size) {
147                 return;
148             }
149             ext_ = std::make_unique<char[]>(tl.length);
150             int ret = memcpy_s(ext_.get(), tl.length, reinterpret_cast<void *>(tmp), tl.length);
151             if (ret == 0) {
152                 extLen_ = static_cast<ssize_t>(tl.length);
153             }
154             checkSum_ = ntohl(*reinterpret_cast<uint32_t *>((reinterpret_cast<char *>(tmp) + AlignTo4Bytes(extLen_))));
155             if (checkSum_ > sizeof(uint16_t) * extFiledNum + AlignTo4Bytes(tl.length)) {
156                 TRANS_LOGE(TRANS_STREAM, "checkSum=%{public}u, length=%{public}u", checkSum_, tl.length);
157                 checkSum_ = 0;
158             }
159         }
160     }
161 
GetTlvNums()162     uint16_t GetTlvNums() const
163     {
164         return firstLevelHeader.length;
165     }
166 
GetExtLen()167     ssize_t GetExtLen() const
168     {
169         return extLen_;
170     }
171 
GetCheckSum()172     uint32_t GetCheckSum() const
173     {
174         return checkSum_;
175     }
176 
GetExtBuffer()177     std::unique_ptr<char[]> GetExtBuffer()
178     {
179         return std::move(ext_);
180     }
181 
182 private:
183     enum TopMask {
184         VERSION_MASK = 0xC000,
185         EXT_BUF_MASK = 0x0001,
186         OPTION_MASK = 0x0002,
187     };
188 
189     enum TopOffset {
190         VERSION_OFFSET = 14,
191         EXT_BUF_OFFSET = 0,
192         OPTION_OFFSET = 1,
193     };
194 
195     enum BottomMask {
196         LEN_MASK = 0x8000,
197         EXT_MASK = 0x0001,
198     };
199 
200     enum BottomOffset {
201         EXT_OFFSET = 0,
202     };
203 
AddFrameExtData(char * start)204     int AddFrameExtData(char *start)
205     {
206         firstLevelHeader.type |= ((1 << TopOffset::EXT_BUF_OFFSET) & TopMask::EXT_BUF_MASK);
207         firstLevelHeader.length++;
208 
209         TypeLength extTlv {};
210         extTlv.type = 0;
211         extTlv.length = static_cast<uint16_t>(extLen_);
212 
213         auto pos = reinterpret_cast<uint16_t *>(start);
214         *(pos++) = htons(extTlv.type);
215         *(pos++) = htons(extTlv.length);
216 
217         char *extPos = reinterpret_cast<char *>(pos);
218         int ret = memcpy_s(extPos, AlignTo4Bytes(extLen_), ext_.get(), extLen_);
219         if (ret != 0) {
220             return -1;
221         }
222         return 0;
223     }
224 
225     uint32_t checkSum_ = 0;
226     TypeLength firstLevelHeader {};
227     std::vector<TypeLength> tlvList_ {};
228     std::unique_ptr<char[]> ext_ = nullptr;
229     ssize_t extLen_ = 0;
230 };
231 
232 class StreamPacketHeader {
233 public:
234     static constexpr int STREAM_HEADER_SIZE = 16;
235     static constexpr int VERSION = 0;
236     static constexpr int SUB_VERSION = 1;
237 
238     static constexpr uint32_t VERSION_OFFSET = 30;
239     static constexpr uint32_t SUB_VERSION_OFFSET = 29;
240     static constexpr uint32_t EXT_FLAG_OFFSET = 28;
241     static constexpr uint32_t STREAM_TYPE_OFFSET = 24;
242     static constexpr uint32_t MAKER_OFFSET = 23;
243     static constexpr uint32_t FLAG_OFFSET = 22;
244     static constexpr uint32_t LEVEL_OFFSET = 18;
245     static constexpr uint32_t SEQ_NUM_OFFSET = 0;
246 
247     static constexpr uint32_t WORD_SIZE = 16;
248 
StreamPacketHeader()249     StreamPacketHeader() {}
StreamPacketHeader(uint8_t streamType,bool extended,uint32_t dataLen,const Communication::SoftBus::StreamFrameInfo * streamFrameInfo)250     StreamPacketHeader(uint8_t streamType, bool extended, uint32_t dataLen,
251         const Communication::SoftBus::StreamFrameInfo* streamFrameInfo)
252     {
253         uint32_t ts = 0;
254         if (streamFrameInfo->timeStamp == 0) {
255             const auto now = system_clock::now();
256             const auto ms = duration_cast<milliseconds>(now.time_since_epoch()).count();
257             ts = static_cast<uint32_t>(ms);
258         } else {
259             ts = streamFrameInfo->timeStamp;
260         }
261 
262         SetVersion(VERSION, SUB_VERSION);
263         commonHeader_.extFlag = extended ? 1 : 0;
264         commonHeader_.streamType = streamType;
265         commonHeader_.marker = 0;
266         commonHeader_.flag = 0;
267         commonHeader_.level = streamFrameInfo->level;
268         commonHeader_.pad = 0;
269         commonHeader_.streamId = streamFrameInfo->streamId;
270         commonHeader_.timestamp = ts;
271         commonHeader_.dataLen = dataLen;
272         commonHeader_.seqNum = streamFrameInfo->seqNum;
273         commonHeader_.subSeqNum = streamFrameInfo->seqSubNum;
274     }
275 
276     virtual ~StreamPacketHeader() = default;
277 
Packetize(char * pos,ssize_t size,ssize_t offset)278     void Packetize(char *pos, ssize_t size, ssize_t offset) const
279     {
280         auto start = reinterpret_cast<uint32_t *>(new (pos + offset) char[size]);
281 
282         uint32_t common = 0;
283         common |= commonHeader_.version << VERSION_OFFSET;
284         common |= commonHeader_.subVersion << SUB_VERSION_OFFSET;
285         common |= commonHeader_.extFlag << EXT_FLAG_OFFSET;
286         common |= commonHeader_.streamType << STREAM_TYPE_OFFSET;
287         common |= commonHeader_.marker << MAKER_OFFSET;
288         common |= commonHeader_.flag << FLAG_OFFSET;
289         common |= commonHeader_.level << LEVEL_OFFSET;
290         common |= static_cast<uint16_t>(commonHeader_.streamId << SEQ_NUM_OFFSET);
291 
292         *start++ = htonl(common);
293         *start++ = htonl(commonHeader_.timestamp);
294         *start++ = htonl(commonHeader_.dataLen);
295         common = 0;
296         common |= commonHeader_.seqNum << WORD_SIZE;
297         common |= commonHeader_.subSeqNum;
298         *start++ = htonl(common);
299     }
300 
Depacketize(const char * header)301     void Depacketize(const char *header)
302     {
303         auto start = reinterpret_cast<const uint32_t *>(header);
304         uint32_t common = ntohl(*start++);
305         commonHeader_.timestamp = ntohl(*start++);
306         commonHeader_.dataLen = ntohl(*start++);
307         uint32_t seq = ntohl(*start);
308         commonHeader_.seqNum = seq >> WORD_SIZE;
309         commonHeader_.subSeqNum = seq & 0xff;
310 
311         commonHeader_.version = common >> VERSION_OFFSET;
312         commonHeader_.subVersion = common >> SUB_VERSION_OFFSET;
313         commonHeader_.extFlag = common >> EXT_FLAG_OFFSET;
314         commonHeader_.streamType = common >> STREAM_TYPE_OFFSET;
315         commonHeader_.marker = common >> MAKER_OFFSET;
316         commonHeader_.flag = common >> FLAG_OFFSET;
317         commonHeader_.level = common >> LEVEL_OFFSET;
318         commonHeader_.streamId = common >> SEQ_NUM_OFFSET;
319     }
320 
SetVersion(uint8_t version,uint8_t subVersion)321     void SetVersion(uint8_t version, uint8_t subVersion)
322     {
323         commonHeader_.version = version;
324         commonHeader_.subVersion = subVersion;
325     }
GetVersion()326     uint8_t GetVersion() const
327     {
328         return commonHeader_.version;
329     }
330 
GetSubVersion()331     uint8_t GetSubVersion() const
332     {
333         return commonHeader_.subVersion;
334     }
335 
GetExtFlag()336     uint8_t GetExtFlag() const
337     {
338         return commonHeader_.extFlag;
339     }
340 
GetStreamType()341     uint8_t GetStreamType() const
342     {
343         return commonHeader_.streamType;
344     }
345 
SetMarker(uint8_t marker)346     void SetMarker(uint8_t marker)
347     {
348         commonHeader_.marker = marker;
349     }
GetMarker()350     uint8_t GetMarker() const
351     {
352         return commonHeader_.marker;
353     }
354 
GetFlag()355     uint8_t GetFlag() const
356     {
357         return commonHeader_.flag;
358     }
359 
GetSeqNum()360     uint16_t GetSeqNum() const
361     {
362         return commonHeader_.seqNum;
363     }
364 
GetTimestamp()365     uint32_t GetTimestamp() const
366     {
367         return commonHeader_.timestamp;
368     }
369 
GetDataLen()370     uint32_t GetDataLen() const
371     {
372         return commonHeader_.dataLen;
373     }
374 
GetStreamId()375     uint16_t GetStreamId() const
376     {
377         return commonHeader_.streamId;
378     }
GetSubSeqNum()379     uint16_t GetSubSeqNum() const
380     {
381         return commonHeader_.subSeqNum;
382     }
GetLevel()383     uint8_t GetLevel() const
384     {
385         return commonHeader_.level;
386     }
387 
388 private:
389     CommonHeader commonHeader_ {};
390 };
391 } // namespace SoftBus
392 } // namespace Communication
393 
394 #endif
395