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