229 lines
5.8 KiB
C++
229 lines
5.8 KiB
C++
/*
|
|
* 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);
|
|
}
|
|
}
|