* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* ubs-hcom is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "hcom_split.h"
#include "securec.h"
namespace ock {
namespace hcom {
SerResult SyncSpliceMessage(UBSHcomNetResponseContext &ctx, UBSHcomNetEndpoint *ep, int32_t timeout, std::string &acc,
void *&data, uint32_t &dataLen)
{
SerResult result = ep->Receive(timeout, ctx);
if (NN_UNLIKELY(result != SER_OK)) {
NN_LOG_ERROR("Channel sync call receive failed " << result << " ep id " << ep->Id());
return result;
}
switch (ctx.Header().extHeaderType) {
case UBSHcomExtHeaderType::RAW:
data = ctx.Message()->Data();
dataLen = ctx.Message()->DataLen();
return result;
case UBSHcomExtHeaderType::FRAGMENT:
break;
}
while (true) {
const uintptr_t msgAddr = reinterpret_cast<uintptr_t>(ctx.Message()->Data());
const uint32_t msgSize = ctx.Message()->DataLen();
if (msgSize < sizeof(UBSHcomFragmentHeader)) {
NN_LOG_ERROR("SyncSpliceMessage: message size is invalid!");
return SER_ERROR;
}
const UBSHcomFragmentHeader *serviceHeader = reinterpret_cast<UBSHcomFragmentHeader *>(msgAddr);
const void *payload = reinterpret_cast<void *>(msgAddr + sizeof(UBSHcomFragmentHeader));
const uint64_t payloadLen = msgSize - sizeof(UBSHcomFragmentHeader);
const auto msgId = serviceHeader->msgId;
const uint32_t totalLength = serviceHeader->totalLength;
const uint32_t offset = serviceHeader->offset;
NN_LOG_DEBUG("SyncSpliceMessage: id " << msgId << ", totalLength " << totalLength << ", offset " << offset
<< ", size " << payloadLen);
if (totalLength >= SERVICE_MAX_TOTAL_LENGTH) {
NN_LOG_ERROR("SyncSpliceMessage: totalLength (" << totalLength << ") is larger than the maximum ("
<< SERVICE_MAX_TOTAL_LENGTH << ")");
return SER_SPLIT_INVALID_MSG;
}
if (offset == 0) {
acc.resize(totalLength);
}
if (totalLength != static_cast<uint32_t>(acc.size())) {
NN_LOG_ERROR("SyncSpliceMessage: the totalLength does not match with the first fragment. "
<< totalLength << " != " << acc.size());
return SER_SPLIT_INVALID_MSG;
}
if (NN_UNLIKELY(offset > acc.size())) {
NN_LOG_ERROR("SyncSpliceMessage: the fragment is from another msg, or the first fragment is lost. offset = "
<< offset << ", totalLength = " << acc.size());
return SER_SPLIT_INVALID_MSG;
}
if (NN_UNLIKELY(memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(acc.data()) + offset),
acc.size() - offset, payload, payloadLen) != EOK)) {
NN_LOG_ERROR("SyncSpliceMessage: the payload is too large.");
return SER_SPLIT_INVALID_MSG;
}
if (offset + payloadLen == totalLength) {
NN_LOG_DEBUG("SyncSpliceMessage: complete! id " << msgId);
data = const_cast<char *>(acc.data());
dataLen = acc.size();
break;
}
result = ep->Receive(timeout, ctx);
if (NN_UNLIKELY(result != SER_OK)) {
NN_LOG_ERROR("Channel sync call receive failed " << result << " ep id " << ep->Id());
return result;
}
switch (ctx.Header().extHeaderType) {
case UBSHcomExtHeaderType::RAW:
NN_LOG_ERROR(
"SyncSpliceMessage: a RAW type msg is received during SpliceMessage, it will be discarded.");
return SER_ERROR;
case UBSHcomExtHeaderType::FRAGMENT:
break;
}
}
return SER_OK;
}
}
}