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