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