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