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