1 /*
2  * Copyright (c) 2024 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 #include "dsched_softbus_session.h"
17 
18 #include <chrono>
19 
20 #include "distributed_sched_adapter.h"
21 #include "distributed_sched_utils.h"
22 #include "dsched_transport_softbus_adapter.h"
23 #include "dtbschedmgr_log.h"
24 #include "session.h"
25 
26 namespace OHOS {
27 namespace DistributedSchedule {
28 namespace {
29 const std::string TAG = "DSchedSoftbusSession";
30 }
31 
DSchedSoftbusSession()32 DSchedSoftbusSession::DSchedSoftbusSession()
33 {
34     sessionId_ = 0;
35     refCount_ = COUNT_INIT_NUM;
36     isServer_ = false;
37     maxSendBytesSize_ = 0;
38     maxQos_ = 0;
39     ResetAssembleFrag();
40 }
41 
DSchedSoftbusSession(SessionInfo & info)42 DSchedSoftbusSession::DSchedSoftbusSession(SessionInfo &info)
43 {
44     sessionId_ = info.sessionId;
45     myDeviceId_ = info.myDeviceId;
46     peerDeviceId_ = info.peerDeviceId;
47     sessionName_ = info.sessionName;
48     isServer_ = info.isServer;
49     refCount_ = COUNT_INIT_NUM;
50     maxSendBytesSize_ = 0;
51     maxQos_ = 0;
52     ResetAssembleFrag();
53 }
54 
~DSchedSoftbusSession()55 DSchedSoftbusSession::~DSchedSoftbusSession()
56 {
57 }
58 
OnConnect()59 void DSchedSoftbusSession::OnConnect()
60 {
61     refCount_++;
62     HILOGI("session %{public}d current ref cnt: %{public}d", sessionId_, refCount_.load());
63 }
64 
OnDisconnect()65 bool DSchedSoftbusSession::OnDisconnect()
66 {
67     refCount_--;
68     HILOGI("session %{public}d current ref cnt: %{public}d", sessionId_, refCount_.load());
69     if (refCount_ <= 0) {
70         HILOGI("session: %{public}d not in use, clear resource", sessionId_);
71         return true;
72     }
73     return false;
74 }
75 
OnBytesReceived(std::shared_ptr<DSchedDataBuffer> buffer)76 int32_t DSchedSoftbusSession::OnBytesReceived(std::shared_ptr<DSchedDataBuffer> buffer)
77 {
78     HILOGD("called");
79     if (buffer == nullptr) {
80         HILOGE("buffer is null");
81         return INVALID_PARAMETERS_ERR;
82     }
83     PackRecvData(buffer);
84     return ERR_OK;
85 }
86 
SendData(std::shared_ptr<DSchedDataBuffer> buffer,int32_t dataType)87 int32_t DSchedSoftbusSession::SendData(std::shared_ptr<DSchedDataBuffer> buffer, int32_t dataType)
88 {
89     HILOGD("called");
90     if (buffer == nullptr) {
91         HILOGE("buffer is null");
92         return INVALID_PARAMETERS_ERR;
93     }
94     UnPackSendData(buffer, dataType);
95     return ERR_OK;
96 }
97 
GetPeerDeviceId()98 std::string DSchedSoftbusSession::GetPeerDeviceId()
99 {
100     return peerDeviceId_;
101 }
102 
PackRecvData(std::shared_ptr<DSchedDataBuffer> buffer)103 void DSchedSoftbusSession::PackRecvData(std::shared_ptr<DSchedDataBuffer> buffer)
104 {
105     uint64_t bufferSize;
106     if (buffer->Size() < BINARY_HEADER_FRAG_LEN) {
107         bufferSize = static_cast<uint64_t>(buffer->Size());
108         HILOGE("pack recv data error, size: %" PRIu64", session id: %{public}d", bufferSize, sessionId_);
109         return;
110     }
111     uint8_t *ptrPacket = buffer->Data();
112     SessionDataHeader headerPara;
113     int32_t ret = GetFragDataHeader(ptrPacket, headerPara);
114     if (ret != ERR_OK) {
115         HILOGE("get frag data header failed, ret %{public}d", ret);
116         return;
117     }
118     if (buffer->Size() != (headerPara.dataLen + BINARY_HEADER_FRAG_LEN) || headerPara.dataLen > headerPara.totalLen ||
119         headerPara.dataLen > BINARY_DATA_MAX_LEN || headerPara.totalLen > BINARY_DATA_MAX_TOTAL_LEN) {
120         bufferSize = static_cast<uint64_t>(buffer->Size());
121         HILOGE("pack recv data failed, size: %" PRIu64", dataLen: %{public}d, totalLen: %{public}d session id:"
122             " %{public}d", bufferSize, headerPara.dataLen, headerPara.totalLen, sessionId_);
123         return;
124     }
125     bufferSize = static_cast<uint64_t>(buffer->Size());
126     HILOGD("pack recv data Assemble, size: %" PRIu64", dataLen: %{public}d, totalLen: %{public}d, nowTime: "
127         "%" PRId64" start", bufferSize, headerPara.dataLen, headerPara.totalLen, GetNowTimeStampUs());
128     if (headerPara.fragFlag == FRAG_START_END) {
129         AssembleNoFrag(buffer, headerPara);
130     } else {
131         AssembleFrag(buffer, headerPara);
132     }
133     bufferSize = static_cast<uint64_t>(buffer->Size());
134     HILOGD("pack recv data Assemble, size: %" PRIu64", dataLen: %{public}d, totalLen: %{public}d, nowTime: "
135         "%" PRId64" end", bufferSize, headerPara.dataLen, headerPara.totalLen, GetNowTimeStampUs());
136 }
137 
GetFragDataHeader(uint8_t * ptrPacket,SessionDataHeader & headerPara)138 int32_t DSchedSoftbusSession::GetFragDataHeader(uint8_t *ptrPacket, SessionDataHeader& headerPara)
139 {
140     uint32_t i = 0;
141     int32_t ret = ERR_OK;
142     while (i < BINARY_HEADER_FRAG_LEN) {
143         uint16_t index = 0;
144         uint16_t byteLeft = BINARY_HEADER_FRAG_LEN - i;
145         if (ptrPacket == nullptr) {
146             ret = ERR_NULL_OBJECT;
147             break;
148         }
149         ret = ReadTlvToHeader(ptrPacket + i, headerPara, index, byteLeft);
150         if (ret != ERR_OK) {
151             break;
152         }
153         i += index;
154     }
155     return ret;
156 }
157 
ReadTlvToHeader(uint8_t * ptrPacket,SessionDataHeader & headerPara,uint16_t & index,uint16_t byteLeft)158 int32_t DSchedSoftbusSession::ReadTlvToHeader(uint8_t *ptrPacket, SessionDataHeader& headerPara, uint16_t& index,
159     uint16_t byteLeft)
160 {
161     uint8_t *ptr = ptrPacket;
162     if (ptr == nullptr || byteLeft < HEADER_UINT16_NUM) { return INVALID_PARAMETERS_ERR; }
163     uint16_t type = U16Get(ptr);
164     ptr += sizeof(type);
165     byteLeft -= HEADER_UINT16_NUM;
166 
167     if (ptr == nullptr || byteLeft < HEADER_UINT16_NUM) { return INVALID_PARAMETERS_ERR; }
168     uint16_t len = U16Get(ptr);
169     ptr += sizeof(len);
170     byteLeft -= HEADER_UINT16_NUM;
171 
172     if (ptr == nullptr || byteLeft < len) { return INVALID_PARAMETERS_ERR; }
173     index = sizeof(type) + sizeof(len) + len;
174 
175     int32_t ret = INVALID_PARAMETERS_ERR;
176     switch (type) {
177         case TLV_TYPE_VERSION:
178             ret = memcpy_s(&headerPara.version, sizeof(headerPara.version), ptr, len);
179             break;
180         case TLV_TYPE_FRAG_FLAG:
181             ret = memcpy_s(&headerPara.fragFlag, sizeof(headerPara.fragFlag), ptr, len);
182             break;
183         case TLV_TYPE_DATA_TYPE:
184             ret = memcpy_s(&headerPara.dataType, sizeof(headerPara.dataType), ptr, len);
185             break;
186         case TLV_TYPE_SEQ_NUM:
187             ret = memcpy_s(&headerPara.seqNum, sizeof(headerPara.seqNum), ptr, len);
188             break;
189         case TLV_TYPE_TOTAL_LEN:
190             ret = memcpy_s(&headerPara.totalLen, sizeof(headerPara.totalLen), ptr, len);
191             break;
192         case TLV_TYPE_SUB_SEQ:
193             ret = memcpy_s(&headerPara.subSeq, sizeof(headerPara.subSeq), ptr, len);
194             break;
195         case TLV_TYPE_DATA_LEN:
196             ret = memcpy_s(&headerPara.dataLen, sizeof(headerPara.dataLen), ptr, len);
197             break;
198         default:
199             HILOGE("invalid type: %{public}d!", type);
200             break;
201     }
202     return ret;
203 }
204 
U16Get(const uint8_t * ptr)205 uint16_t DSchedSoftbusSession::U16Get(const uint8_t *ptr)
206 {
207     return (ptr[0] << DSCHED_SHIFT_8) | ptr[1];
208 }
209 
AssembleNoFrag(std::shared_ptr<DSchedDataBuffer> buffer,SessionDataHeader & headerPara)210 void DSchedSoftbusSession::AssembleNoFrag(std::shared_ptr<DSchedDataBuffer> buffer, SessionDataHeader& headerPara)
211 {
212     if (headerPara.dataLen != headerPara.totalLen) {
213         HILOGE("header lenth error, dataLen: %{public}d, totalLen: %{public}d, sessionId: %{public}d, peerNetworkId: "
214             "%{public}s.", headerPara.dataLen, headerPara.totalLen, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
215         return;
216     }
217     std::shared_ptr<DSchedDataBuffer> postData = std::make_shared<DSchedDataBuffer>(headerPara.dataLen);
218     int32_t ret = memcpy_s(postData->Data(), postData->Size(), buffer->Data() + BINARY_HEADER_FRAG_LEN,
219         buffer->Size() - BINARY_HEADER_FRAG_LEN);
220     if (ret != ERR_OK) {
221         HILOGE("memcpy failed, ret: %{public}d, sessionId: %{public}d, peerNetworkId: %{public}s.",
222             ret, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
223         return;
224     }
225     DSchedTransportSoftbusAdapter::GetInstance().OnDataReady(sessionId_, postData, headerPara.dataType);
226 }
227 
AssembleFrag(std::shared_ptr<DSchedDataBuffer> buffer,SessionDataHeader & headerPara)228 void DSchedSoftbusSession::AssembleFrag(std::shared_ptr<DSchedDataBuffer> buffer, SessionDataHeader& headerPara)
229 {
230     if (headerPara.fragFlag == FRAG_START) {
231         isWaiting_ = true;
232         nowSeq_ = headerPara.seqNum;
233         nowSubSeq_ = headerPara.subSeq;
234         offset_ = 0;
235         totalLen_ = headerPara.totalLen;
236         packBuffer_ = std::make_shared<DSchedDataBuffer>(headerPara.totalLen);
237         int32_t ret = memcpy_s(packBuffer_->Data(), packBuffer_->Size(), buffer->Data() + BINARY_HEADER_FRAG_LEN,
238             buffer->Size() - BINARY_HEADER_FRAG_LEN);
239         if (ret != ERR_OK) {
240             HILOGE("FRAG_START memcpy fail, ret: %{public}d, sessionId: %{public}d peerNetworkId: %{public}s.",
241                 ret, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
242             ResetAssembleFrag();
243             return;
244         }
245         offset_ += headerPara.dataLen;
246     }
247 
248     if (headerPara.fragFlag == FRAG_MID || headerPara.fragFlag == FRAG_END) {
249         int32_t ret = CheckUnPackBuffer(headerPara);
250         if (ret != ERR_OK) {
251             ResetAssembleFrag();
252             return;
253         }
254 
255         nowSubSeq_ = headerPara.subSeq;
256         ret = memcpy_s(packBuffer_->Data() + offset_, packBuffer_->Size() - offset_,
257             buffer->Data() + BINARY_HEADER_FRAG_LEN, buffer->Size() - BINARY_HEADER_FRAG_LEN);
258         if (ret != ERR_OK) {
259             HILOGE("memcpy_s failed, ret: %{public}d, sessionId: %{public}d, peerNetworkId: %{public}s.",
260                 ret, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
261             ResetAssembleFrag();
262             return;
263         }
264         offset_ += headerPara.dataLen;
265     }
266 
267     if (headerPara.fragFlag == FRAG_END) {
268         DSchedTransportSoftbusAdapter::GetInstance().OnDataReady(sessionId_, packBuffer_, headerPara.dataType);
269         ResetAssembleFrag();
270     }
271 }
272 
CheckUnPackBuffer(SessionDataHeader & headerPara)273 int32_t DSchedSoftbusSession::CheckUnPackBuffer(SessionDataHeader& headerPara)
274 {
275     if (!isWaiting_) {
276         HILOGE("failed, not waiting, sessionId: %{public}d peerNetworkId: %{public}s.",
277             sessionId_, GetAnonymStr(peerDeviceId_).c_str());
278         return INVALID_PARAMETERS_ERR;
279     }
280 
281     if (nowSeq_ != headerPara.seqNum) {
282         HILOGE("seq error, nowSeq: %{public}d, actualSeq: %{public}d, sessionId: %{public}d, peerNetworkId: "
283             "%{public}s.", nowSeq_, headerPara.seqNum, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
284         return INVALID_PARAMETERS_ERR;
285     }
286 
287     if (nowSubSeq_ + 1 != headerPara.subSeq) {
288         HILOGE("subSeq error, nowSeq: %{public}d, actualSeq: %{public}d, sessionId: %{public}d, peerNetworkId: "
289             "%{public}s.", nowSubSeq_, headerPara.subSeq, sessionId_, GetAnonymStr(peerDeviceId_).c_str());
290         return INVALID_PARAMETERS_ERR;
291     }
292 
293     if (totalLen_ < headerPara.dataLen + offset_) {
294         HILOGE("data len error cap: %{public}d, size: %{public}d, dataLen: %{public}d, sessionId: %{public}d,"
295             " peerNetworkId: %{public}s.", totalLen_, offset_, headerPara.dataLen, sessionId_,
296             GetAnonymStr(peerDeviceId_).c_str());
297         return INVALID_PARAMETERS_ERR;
298     }
299     return ERR_OK;
300 }
301 
ResetAssembleFrag()302 void DSchedSoftbusSession::ResetAssembleFrag()
303 {
304     isWaiting_ = false;
305     nowSeq_ = 0;
306     nowSubSeq_ = 0;
307     offset_ = 0;
308     totalLen_ = 0;
309     packBuffer_ = nullptr;
310 }
311 
UnPackSendData(std::shared_ptr<DSchedDataBuffer> buffer,int32_t dataType)312 int32_t DSchedSoftbusSession::UnPackSendData(std::shared_ptr<DSchedDataBuffer> buffer, int32_t dataType)
313 {
314     uint32_t maxSendSize = 0;
315     int32_t ret = GetSessionOption(sessionId_, SESSION_OPTION_MAX_SENDBYTES_SIZE, &maxSendSize, sizeof(maxSendSize));
316     if (ret != ERR_OK) {
317         HILOGE("GetSessionOption get max SendBytes size failed, ret: %{public}d, session: %{public}d",
318             ret, sessionId_);
319         return ret;
320     }
321     HILOGD("GetSessionOption get max SendBytes size: %{public}u, session: %{public}d", maxSendSize, sessionId_);
322 
323     if (buffer->Size() <= maxSendSize) {
324         return UnPackStartEndData(buffer, dataType);
325     }
326 
327     uint16_t subSeq = 0;
328     uint32_t totalLen = buffer->Size();
329     uint32_t offset = 0;
330     uint64_t bufferSize = 0;
331     SessionDataHeader headPara = { PROTOCOL_VERSION, FRAG_START, dataType, 0, totalLen, subSeq };
332 
333     while (totalLen > offset) {
334         SetHeadParaDataLen(headPara, totalLen, offset, maxSendSize);
335         bufferSize = static_cast<uint64_t>(buffer->Size());
336         HILOGD("size: %" PRIu64", dataLen: %{public}d, totalLen: %{public}d, nowTime: %" PRId64" start:",
337             bufferSize, headPara.dataLen, headPara.totalLen, GetNowTimeStampUs());
338 
339         auto unpackData = std::make_shared<DSchedDataBuffer>(headPara.dataLen + BINARY_HEADER_FRAG_LEN);
340         MakeFragDataHeader(headPara, unpackData->Data(), BINARY_HEADER_FRAG_LEN);
341         int32_t ret = memcpy_s(unpackData->Data() + BINARY_HEADER_FRAG_LEN,
342             unpackData->Size() - BINARY_HEADER_FRAG_LEN, buffer->Data() + offset, headPara.dataLen);
343         if (ret != ERR_OK) {
344             HILOGE("memcpy_s failed, ret: %{public}d, session: %{public}d", ret, sessionId_);
345             return ret;
346         }
347 
348         ret = DSchedTransportSoftbusAdapter::GetInstance().SendBytesBySoftbus(sessionId_, unpackData);
349         if (ret != ERR_OK) {
350             HILOGE("sendData failed, ret: %{public}d, session: %{public}d", ret, sessionId_);
351             return ret;
352         }
353         HILOGD("size: %" PRIu64", dataLen: %{public}d, totalLen: %{public}d, nowTime: %" PRId64" end:",
354             bufferSize, headPara.dataLen, headPara.totalLen, GetNowTimeStampUs());
355 
356         headPara.subSeq++;
357         headPara.fragFlag = FRAG_MID;
358         offset += headPara.dataLen;
359 
360         ret = GetSessionOption(sessionId_, SESSION_OPTION_MAX_SENDBYTES_SIZE, &maxSendSize, sizeof(maxSendSize));
361         if (ret != ERR_OK) {
362             HILOGE("GetSessionOption get max SendBytes size failed, ret: %{public}d, session: %{public}d",
363                 ret, sessionId_);
364             return ret;
365         }
366         HILOGD("GetSessionOption get next SendBytes size: %{public}u, session: %{public}d", maxSendSize, sessionId_);
367     }
368     return ERR_OK;
369 }
370 
UnPackStartEndData(std::shared_ptr<DSchedDataBuffer> buffer,int32_t dataType)371 int32_t DSchedSoftbusSession::UnPackStartEndData(std::shared_ptr<DSchedDataBuffer> buffer, int32_t dataType)
372 {
373     SessionDataHeader headPara = { PROTOCOL_VERSION, FRAG_START_END, dataType, 0, buffer->Size(), 0 };
374 
375     uint32_t maxSendSize = 0;
376     int32_t ret = GetSessionOption(sessionId_, SESSION_OPTION_MAX_SENDBYTES_SIZE, &maxSendSize, sizeof(maxSendSize));
377     if (ret != ERR_OK) {
378         HILOGE("GetSessionOption get max SendBytes size failed, ret: %{public}d, session: %{public}d",
379             ret, sessionId_);
380         return ret;
381     }
382     HILOGD("GetSessionOption get max SendBytes size: %{public}u, session: %{public}d", maxSendSize, sessionId_);
383 
384     headPara.dataLen = buffer->Size();
385     auto unpackData = std::make_shared<DSchedDataBuffer>(buffer->Size() + BINARY_HEADER_FRAG_LEN);
386     MakeFragDataHeader(headPara, unpackData->Data(), BINARY_HEADER_FRAG_LEN);
387     ret = memcpy_s(unpackData->Data() + BINARY_HEADER_FRAG_LEN, unpackData->Size() - BINARY_HEADER_FRAG_LEN,
388         buffer->Data(), buffer->Size());
389     if (ret != ERR_OK) {
390         HILOGE("START_END memcpy_s failed, ret: %{public}d, session: %{public}d", ret, sessionId_);
391         return ret;
392     }
393     return DSchedTransportSoftbusAdapter::GetInstance().SendBytesBySoftbus(sessionId_, unpackData);
394 }
395 
SetHeadParaDataLen(SessionDataHeader & headPara,const uint32_t totalLen,const uint32_t offset,const uint32_t maxSendSize)396 void DSchedSoftbusSession::SetHeadParaDataLen(SessionDataHeader& headPara, const uint32_t totalLen,
397     const uint32_t offset, const uint32_t maxSendSize)
398 {
399     if (totalLen - offset > maxSendSize) {
400         headPara.dataLen = maxSendSize - BINARY_DATA_PACKET_RESERVED_BUFFER;
401     } else {
402         headPara.fragFlag = FRAG_END;
403         headPara.dataLen = totalLen - offset;
404     }
405 }
406 
GetNowTimeStampUs()407 int64_t DSchedSoftbusSession::GetNowTimeStampUs()
408 {
409     std::chrono::microseconds nowUs = std::chrono::duration_cast<std::chrono::microseconds>(
410         std::chrono::system_clock::now().time_since_epoch());
411     return nowUs.count();
412 }
413 
MakeFragDataHeader(const SessionDataHeader & headPara,uint8_t * header,uint32_t len)414 void DSchedSoftbusSession::MakeFragDataHeader(const SessionDataHeader& headPara, uint8_t *header, uint32_t len)
415 {
416     uint32_t headerLen = (sizeof(uint16_t) + sizeof(uint16_t)) * HEADER_TLV_NUM  +
417         sizeof(uint8_t) * HEADER_UINT8_NUM + sizeof(uint16_t) * HEADER_UINT16_NUM +
418         sizeof(uint32_t) * HEADER_UINT32_NUM;
419     if (headerLen > len) {
420         HILOGE("MakeFragDataHeader %{public}d over len %{public}d", headerLen, len);
421         return;
422     }
423 
424     uint32_t i = 0;
425     uint32_t capacity = len;
426     uint32_t offset = TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES;
427     TlvItem version = { TLV_TYPE_VERSION, sizeof(uint16_t), headPara.version };
428     WriteTlvToBuffer(version, &header[i], capacity);
429     capacity -= offset + sizeof(uint16_t);
430     i += offset + sizeof(uint16_t);
431 
432     TlvItem fragFlag = { TLV_TYPE_FRAG_FLAG, sizeof(uint8_t), headPara.fragFlag };
433     WriteTlvToBuffer(fragFlag, &header[i], capacity);
434     capacity -= offset + sizeof(uint8_t);
435     i += offset + sizeof(uint8_t);
436 
437     TlvItem dataType = { TLV_TYPE_DATA_TYPE, sizeof(uint32_t), headPara.dataType };
438     WriteTlvToBuffer(dataType, &header[i], capacity);
439     capacity -= offset + sizeof(uint32_t);
440     i += offset + sizeof(uint32_t);
441 
442     TlvItem seqNum = { TLV_TYPE_SEQ_NUM, sizeof(uint32_t), headPara.seqNum };
443     WriteTlvToBuffer(seqNum, &header[i], capacity);
444     capacity -= offset + sizeof(uint32_t);
445     i += offset + sizeof(uint32_t);
446 
447     TlvItem totalLen = { TLV_TYPE_TOTAL_LEN, sizeof(uint32_t), headPara.totalLen };
448     WriteTlvToBuffer(totalLen, &header[i], capacity);
449     capacity -= offset + sizeof(uint32_t);
450     i += offset + sizeof(uint32_t);
451 
452     TlvItem subSeq = { TLV_TYPE_SUB_SEQ, sizeof(uint16_t), headPara.subSeq };
453     WriteTlvToBuffer(subSeq, &header[i], capacity);
454     capacity -= offset + sizeof(uint16_t);
455     i += offset + sizeof(uint16_t);
456 
457     TlvItem dataLen = { TLV_TYPE_DATA_LEN, sizeof(uint32_t), headPara.dataLen };
458     WriteTlvToBuffer(dataLen, &header[i], capacity);
459 }
460 
WriteTlvToBuffer(const TlvItem & tlvItem,uint8_t * buffer,uint32_t bufLen)461 void DSchedSoftbusSession::WriteTlvToBuffer(const TlvItem& tlvItem, uint8_t *buffer,  uint32_t bufLen)
462 {
463     uint32_t tlvLen = TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES + tlvItem.len;
464     if (bufLen < tlvLen) {
465         HILOGE("tlv len %{public}d over buffer len %{public}d", tlvLen, bufLen);
466         return;
467     }
468     uint32_t i = 0;
469     buffer[i++] = tlvItem.type >> DSCHED_SHIFT_8;
470     buffer[i++] = tlvItem.type & UINT16_SHIFT_MASK_0;
471     buffer[i++] = tlvItem.len >> DSCHED_SHIFT_8;
472     buffer[i++] = tlvItem.len & UINT16_SHIFT_MASK_0;
473     int32_t ret = memcpy_s(&buffer[i], bufLen - TlvItem::HEADER_TYPE_BYTES + TlvItem::HEADER_LEN_BYTES,
474         &tlvItem.value, tlvItem.len);
475     if (ret != ERR_OK) {
476         HILOGE("copy tlv value failed!, ret %{public}d", ret);
477     }
478     return;
479 }
480 }  // namespace DistributedSchedule
481 }  // namespace OHOS
482