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