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