cmvr_head/packages/erpc-1.14.0/erpc_c/infra/erpc_client_manager.cpp

229 lines
5.8 KiB
C++
Raw Permalink Normal View History

2025-12-30 15:44:41 +08:00
/*
* Copyright (c) 2014, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* Copyright 2021 ACRIOS Systems s.r.o.
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "erpc_client_manager.h"
using namespace erpc;
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
#if ERPC_NESTED_CALLS_DETECTION
extern bool nestingDetection;
#ifndef _WIN32
#pragma weak nestingDetection
bool nestingDetection = false;
#endif
#endif
RequestContext ClientManager::createRequest(bool isOneway)
{
// Create codec to read and write the request.
Codec *codec = createBufferAndCodec();
return RequestContext(++m_sequence, codec, isOneway);
}
void ClientManager::performRequest(RequestContext &request)
{
bool performRequest;
// Check the codec status
performRequest = request.getCodec()->isStatusOk();
#if ERPC_NESTED_CALLS
if (performRequest)
{
erpc_assert((m_serverThreadId != NULL) && ("server thread id was not set" != NULL));
if (Thread::getCurrentThreadId() == m_serverThreadId)
{
performNestedClientRequest(request);
performRequest = false;
}
}
#endif
if (performRequest)
{
performClientRequest(request);
}
}
void ClientManager::performClientRequest(RequestContext &request)
{
erpc_status_t err;
#if ERPC_NESTED_CALLS_DETECTION
if (!request.isOneway() && nestingDetection)
{
request.getCodec()->updateStatus(kErpcStatus_NestedCallFailure);
}
#endif
#if ERPC_MESSAGE_LOGGING
if (request.getCodec()->isStatusOk() == true)
{
err = logMessage(request.getCodec()->getBuffer());
request.getCodec()->updateStatus(err);
}
#endif
// Send invocation request to server.
if (request.getCodec()->isStatusOk() == true)
{
err = m_transport->send(&request.getCodec()->getBufferRef());
request.getCodec()->updateStatus(err);
}
// If the request is oneway, then there is nothing more to do.
if (!request.isOneway())
{
if (request.getCodec()->isStatusOk() == true)
{
// Receive reply.
err = m_transport->receive(&request.getCodec()->getBufferRef());
request.getCodec()->updateStatus(err);
}
#if ERPC_MESSAGE_LOGGING
if (request.getCodec()->isStatusOk() == true)
{
err = logMessage(request.getCodec()->getBuffer());
request.getCodec()->updateStatus(err);
}
#endif
// Check the reply.
if (request.getCodec()->isStatusOk() == true)
{
verifyReply(request);
}
}
}
#if ERPC_NESTED_CALLS
void ClientManager::performNestedClientRequest(RequestContext &request)
{
erpc_status_t err;
erpc_assert((m_transport != NULL) && ("transport/arbitrator not set" != NULL));
#if ERPC_MESSAGE_LOGGING
if (request.getCodec()->isStatusOk() == true)
{
err = logMessage(request.getCodec()->getBuffer());
request.getCodec()->updateStatus(err);
}
#endif
// Send invocation request to server.
if (request.getCodec()->isStatusOk() == true)
{
err = m_transport->send(&request.getCodec()->getBufferRef());
request.getCodec()->updateStatus(err);
}
// If the request is oneway, then there is nothing more to do.
if (!request.isOneway())
{
// Receive reply.
if (request.getCodec()->isStatusOk() == true)
{
erpc_assert((m_server != NULL) && ("server for nesting calls was not set" != NULL));
err = m_server->run(request);
request.getCodec()->updateStatus(err);
}
#if ERPC_MESSAGE_LOGGING
if (request.getCodec()->isStatusOk() == true)
{
err = logMessage(request.getCodec()->getBuffer());
request.getCodec()->updateStatus(err);
}
#endif
// Check the reply.
if (request.getCodec()->isStatusOk() == true)
{
verifyReply(request);
}
}
}
#endif
void ClientManager::verifyReply(RequestContext &request)
{
message_type_t msgType;
uint32_t service;
uint32_t requestNumber;
uint32_t sequence;
// Some transport layers change the request's message buffer pointer (for things like zero
// copy support), so inCodec must be reset to work with correct buffer.
request.getCodec()->reset(m_transport->reserveHeaderSize());
// Extract the reply header.
request.getCodec()->startReadMessage(msgType, service, requestNumber, sequence);
if (request.getCodec()->isStatusOk() == true)
{
// Verify that this is a reply to the request we just sent.
if ((msgType != message_type_t::kReplyMessage) || (sequence != request.getSequence()))
{
request.getCodec()->updateStatus(kErpcStatus_ExpectedReply);
}
}
}
Codec *ClientManager::createBufferAndCodec(void)
{
Codec *codec = m_codecFactory->create();
MessageBuffer message;
uint8_t reservedMessageSpace = m_transport->reserveHeaderSize();
if (codec != NULL)
{
message = m_messageFactory->create(reservedMessageSpace);
if (NULL != message.get())
{
codec->setBuffer(message, reservedMessageSpace);
}
else
{
// Dispose of buffers and codecs.
m_codecFactory->dispose(codec);
codec = NULL;
}
}
return codec;
}
void ClientManager::releaseRequest(RequestContext &request)
{
if (request.getCodec() != NULL)
{
m_messageFactory->dispose(&request.getCodec()->getBufferRef());
m_codecFactory->dispose(request.getCodec());
}
}
void ClientManager::callErrorHandler(erpc_status_t err, uint32_t functionID)
{
if (m_errorHandler != NULL)
{
m_errorHandler(err, functionID);
}
}