LCOV - code coverage report
Current view: top level - libs/bsw/cpp2someip/src - RpcHandler.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.4 % 384 255
Test Date: 2026-09-11 12:05:06 Functions: 85.7 % 21 18

            Line data    Source code
       1              : /********************************************************************************
       2              :  * Copyright (c) 2026 Accenture
       3              :  *
       4              :  * This program and the accompanying materials are made available under the
       5              :  * terms of the Apache License Version 2.0 which is available at
       6              :  * https://www.apache.org/licenses/LICENSE-2.0
       7              :  *
       8              :  * SPDX-License-Identifier: Apache-2.0
       9              :  ********************************************************************************/
      10              : 
      11              : #include "someip/RpcHandler.h"
      12              : 
      13              : #include "someip/IEventReceiver.h"
      14              : #include "someip/INetwork.h"
      15              : #include "someip/IServiceRegistry.h"
      16              : #include "someip/ISomeIpSerializable.h"
      17              : #include "someip/NetworkChannel.h"
      18              : #include "someip/QueryManager.h"
      19              : #include "someip/ServiceHandler.h"
      20              : #include "someip/SomeIpConstants.h"
      21              : #include "someip/SomeIpParser.h"
      22              : #include "someip/SomeIpSerializer.h"
      23              : #include "someip/Statistics.h"
      24              : #include "someip/TpTransceiver.h"
      25              : #include "someip/logger.h"
      26              : 
      27              : #include <ip/to_str.h>
      28              : 
      29              : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
      30              : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
      31              : 
      32              : namespace
      33              : {
      34              : class RequestContextCleanup final
      35              : {
      36              : public:
      37              :     using RpcCallback = ::someip::ServiceHandler::RpcCallback;
      38              : 
      39            2 :     explicit RequestContextCleanup(::someip::RequestContext& context) : _context(context) {}
      40              : 
      41            2 :     ~RequestContextCleanup()
      42              :     {
      43            2 :         _context.pService->releaseCallback(*static_cast<RpcCallback*>(_context.callback));
      44            2 :         _context.pResponse = nullptr;
      45            2 :         _context.pRequest  = nullptr;
      46            2 :     }
      47              : 
      48              : private:
      49              :     ::someip::RequestContext& _context;
      50              : };
      51              : 
      52              : } // anonymous namespace
      53              : 
      54              : namespace someip
      55              : {
      56              : using ::ip::IPAddress;
      57              : using ::ip::IPEndpoint;
      58              : using ::util::logger::SOMEIP;
      59              : 
      60           44 : RpcHandler::RpcHandler(
      61              :     INetwork& network,
      62              :     ::async::ContextType const ethernetContext,
      63              :     ITpTransceiver& tpTransceiver,
      64              :     ServiceManager& serviceManager,
      65           44 :     IServiceRegistry& serviceRegistry)
      66           44 : : _network(network)
      67           44 : , _ethernetContext(ethernetContext)
      68           44 : , _tpTransceiver(tpTransceiver)
      69           44 : , _serviceManager(serviceManager)
      70           44 : , _serviceRegistry(serviceRegistry)
      71           44 : , _pEventReceiver(nullptr)
      72           44 : {}
      73              : 
      74            3 : void RpcHandler::setEventReceiver(IEventReceiver& eventReceiver)
      75              : {
      76            3 :     _pEventReceiver = &eventReceiver;
      77            3 : }
      78              : 
      79            2 : void RpcHandler::removeEventReceiver() { _pEventReceiver = nullptr; }
      80              : 
      81            9 : RpcHandler::ErrorCode RpcHandler::handleRequest(
      82              :     SomeIpMessage const& message,
      83              :     IPEndpoint const& sourceAddress,
      84              :     port::type localPort,
      85              :     proto::type proto)
      86              : {
      87            9 :     RpcHandler::ErrorCode result     = ErrorCode::RPC_HANDLER_ERROR;
      88            9 :     service_id::type const serviceId = message.getServiceId();
      89            9 :     uint16_t const methodId          = message.getMethodId();
      90            9 :     uint8_t const interfaceVersion   = message.getInterfaceVersion();
      91              : 
      92            9 :     auto service         = ::someip::make<ServiceDescription>();
      93            9 :     service.serviceId    = serviceId;
      94            9 :     service.majorVersion = interfaceVersion;
      95            9 :     service.port         = localPort;
      96            9 :     service.proto        = proto;
      97            9 :     ServiceManager::FindServiceResult smResult
      98              :         = ServiceManager::FindServiceResult::FIND_SERVICE_UNKNOWN;
      99              : 
     100            9 :     ServiceHandler* const handler = _serviceManager.getHandler(service, smResult);
     101              : 
     102            9 :     switch (smResult)
     103              :     {
     104            7 :         case ServiceManager::FindServiceResult::FIND_SERVICE_OK:
     105              :         {
     106            7 :             if (handler == nullptr)
     107              :             {
     108            0 :                 WARN_LOG(
     109              :                     SOMEIP,
     110              :                     "RpcHandler::handleRequest() no service handler (serviceId %d, port %d, proto "
     111              :                     "%s)",
     112              :                     serviceId,
     113              :                     localPort,
     114              :                     proto == proto::SD_L4_PROTO_UDP ? "UDP" : "TCP");
     115            0 :                 result = RpcHandler::ErrorCode::RPC_HANDLER_ERROR;
     116              :             }
     117            7 :             else if (handler->getMethodDetail(methodId) == nullptr)
     118              :             {
     119            1 :                 WARN_LOG(
     120              :                     SOMEIP,
     121              :                     "RpcHandler::handleRequest(): unknown method (serviceId %d, "
     122              :                     "interfaceVersion %d, port %d, proto %s, methodId %d)",
     123              :                     serviceId,
     124              :                     interfaceVersion,
     125              :                     localPort,
     126              :                     proto == proto::SD_L4_PROTO_UDP ? "UDP" : "TCP",
     127              :                     methodId);
     128            1 :                 Statistics::incCounter(Statistics::Counter::RPC_UNKNOWN_METHOD_RX);
     129            1 :                 result = ErrorCode::RPC_HANDLER_UNKNOWN_METHOD;
     130              :             }
     131            6 :             else if (
     132            6 :                 static_cast<uint8_t>(handler->getMethodDetail(methodId)->callSemantic)
     133            6 :                 != static_cast<uint8_t>(message.getMessageType()) + 1U)
     134              :             {
     135            2 :                 switch (handler->getMethodDetail(methodId)->callSemantic)
     136              :                 {
     137            1 :                     case SomeIpCallSemantic::SEMANTIC_REQUEST_RESPONSE:
     138              :                     {
     139            1 :                         return ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_REQUEST_RESPONSE;
     140              :                     }
     141            1 :                     case SomeIpCallSemantic::SEMANTIC_FIRE_AND_FORGET:
     142              :                     {
     143            1 :                         return ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_FIRE_AND_FORGET;
     144              :                     }
     145            0 :                     case SomeIpCallSemantic::SEMANTIC_UNKNOWN:
     146              :                     {
     147            0 :                         Statistics::incCounter(Statistics::Counter::RPC_MALFORMED_MESSAGE_RX);
     148            0 :                         return ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE;
     149              :                     }
     150              :                 }
     151              :             }
     152            4 :             else if (!handler->hasAvailableCallback())
     153              :             {
     154            1 :                 WARN_LOG(
     155              :                     SOMEIP,
     156              :                     "RpcHandler::handleRequest() number of parallel callbacks exhausted (serviceId "
     157              :                     "%d, "
     158              :                     "port %d, proto %s)",
     159              :                     serviceId,
     160              :                     localPort,
     161              :                     proto == proto::SD_L4_PROTO_UDP ? "UDP" : "TCP");
     162            1 :                 result = RpcHandler::ErrorCode::RPC_HANDLER_ERROR;
     163              :             }
     164              :             else
     165              :             {
     166            3 :                 ServiceHandler::RpcCallback& callback = handler->getCallback();
     167            3 :                 RequestContext context;
     168              : 
     169            3 :                 SomeIpParser parser(message.getBufferPayload());
     170              : 
     171            3 :                 context.pRequest           = handler->createRequest(methodId, parser);
     172            3 :                 context.pResponse          = handler->getResponse(methodId);
     173            3 :                 context.pService           = handler;
     174            3 :                 context.remoteIp           = sourceAddress;
     175            3 :                 context.localPort          = localPort;
     176            3 :                 context.proto              = proto;
     177            3 :                 context.requestId          = message.getRequestId(); // client-id && session-id
     178            3 :                 context.serviceId          = serviceId;
     179            3 :                 context.methodId           = methodId;
     180            3 :                 context.interfaceVersion   = interfaceVersion;
     181            3 :                 context.callback           = static_cast<void*>(&callback);
     182            3 :                 context.requestMessageType = message.getMessageType();
     183              : 
     184              :                 callback
     185            6 :                     = ServiceHandler::RpcCallback::fromObject<RpcHandler, &RpcHandler::requestDone>(
     186            3 :                         *this, context);
     187              : 
     188            3 :                 handler->dispatchMethod(methodId, context.pRequest, context.pResponse, callback);
     189            3 :                 result = RpcHandler::ErrorCode::RPC_HANDLER_OK;
     190              :             }
     191            5 :             break;
     192              :         }
     193            0 :         case ServiceManager::FindServiceResult::FIND_SERVICE_WRONG_MAJOR_VERSION:
     194              :         {
     195            0 :             WARN_LOG(
     196              :                 SOMEIP,
     197              :                 "RpcHandler::handleRequest(): wrong interface version (serviceId %d, "
     198              :                 "interfaceVersion "
     199              :                 "%d, port %d, proto %s)",
     200              :                 serviceId,
     201              :                 interfaceVersion,
     202              :                 localPort,
     203              :                 proto == proto::SD_L4_PROTO_UDP ? "UDP" : "TCP");
     204            0 :             Statistics::incCounter(Statistics::Counter::RPC_WRONG_INTERFACE_VERSION_RX);
     205            0 :             result = RpcHandler::ErrorCode::RPC_HANDLER_WRONG_INTERFACE_VERSION;
     206            0 :             break;
     207              :         }
     208            2 :         case ServiceManager::FindServiceResult::FIND_SERVICE_UNKNOWN:
     209              :         default:
     210              :         {
     211            2 :             WARN_LOG(
     212              :                 SOMEIP,
     213              :                 "RpcHandler::handleRequest(): no service provided (serviceId %d, port %d, proto "
     214              :                 "%s)",
     215              :                 serviceId,
     216              :                 localPort,
     217              :                 proto == proto::SD_L4_PROTO_UDP ? "UDP" : "TCP");
     218            2 :             Statistics::incCounter(Statistics::Counter::RPC_UNKNOWN_SERVICE_RX);
     219            2 :             result = ErrorCode::RPC_HANDLER_UNKNOWN_SERVICE;
     220            2 :             break;
     221              :         }
     222              :     }
     223            7 :     return result;
     224              : }
     225              : 
     226              : IRpcHandler::ErrorCode
     227            2 : RpcHandler::handleMessage(NetworkChannel const& channel, SomeIpMessage const& message)
     228              : {
     229            2 :     IRpcHandler::ErrorCode errorCode = IRpcHandler::ErrorCode::RPC_HANDLER_OK;
     230              : 
     231            2 :     service_id::type const serviceId       = message.getServiceId();
     232            2 :     major_version::type const majorVersion = message.getInterfaceVersion();
     233            2 :     uint16_t const methodId                = message.getMethodId();
     234            2 :     instance_id::type instanceId           = instance_id::ANY;
     235              : 
     236            2 :     if (message.getMessageType() == SomeIpMessage::MessageType::REQUEST
     237            2 :         || message.getMessageType() == SomeIpMessage::MessageType::REQUEST_NO_RETURN)
     238              :     {
     239              :         // Local provider
     240            2 :         auto const portResult = channel.getLocalPort();
     241            2 :         if (!portResult.has_value())
     242              :         {
     243            0 :             WARN_LOG(SOMEIP, "RpcHandler: unable to get local port");
     244            0 :             return ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE;
     245              :         }
     246              : 
     247            2 :         instanceId = _serviceRegistry.getInstanceId(
     248            2 :             message.getServiceId(),
     249            2 :             message.getInterfaceVersion(),
     250            2 :             _network.getLocalIp(),
     251            2 :             portResult.value(),
     252              :             false); // false means local provider
     253              :     }
     254              :     else
     255              :     {
     256              :         // Remote provider
     257            0 :         instanceId = _serviceRegistry.getInstanceId(
     258            0 :             message.getServiceId(),
     259            0 :             message.getInterfaceVersion(),
     260            0 :             channel.getRemoteEndpoint().getAddress(),
     261            0 :             channel.getRemoteEndpoint().getPort());
     262              :     }
     263            2 :     DEBUG_LOG(
     264              :         SOMEIP,
     265              :         "RpcHandler::handleMessage(serviceId %d, methodId %d, instanceId %d, majorVersion "
     266              :         "%d)",
     267              :         serviceId,
     268              :         methodId,
     269              :         instanceId,
     270              :         majorVersion);
     271              : 
     272            2 :     bool const queryManagerCheck = _serviceRegistry.getQueryManager() != nullptr;
     273              :     bool const notificationCheck
     274            2 :         = message.getMessageType() != SomeIpMessage::MessageType::NOTIFICATION;
     275              : 
     276            2 :     if (queryManagerCheck && notificationCheck)
     277              :     {
     278              :         ServiceQuery const* const query
     279            0 :             = _serviceRegistry.getQueryManager()->getQuery(serviceId, instanceId);
     280              : 
     281            0 :         bool const nullptrCheck = (query != nullptr) && (query->listener != nullptr);
     282              : 
     283              :         bool const msgTypeCheck
     284              :             = nullptrCheck
     285            0 :               && (static_cast<uint8_t>(query->listener->getMethodDetail(methodId)->callSemantic)
     286            0 :                   != static_cast<uint8_t>(message.getMessageType()) + 1U);
     287              : 
     288            0 :         if (msgTypeCheck)
     289              :         {
     290            0 :             switch (query->listener->getMethodDetail(methodId)->callSemantic)
     291              :             {
     292            0 :                 case SomeIpCallSemantic::SEMANTIC_REQUEST_RESPONSE:
     293              :                 {
     294            0 :                     errorCode = ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_REQUEST_RESPONSE;
     295            0 :                     break;
     296              :                 }
     297            0 :                 case SomeIpCallSemantic::SEMANTIC_FIRE_AND_FORGET:
     298              :                 {
     299            0 :                     errorCode = ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_FIRE_AND_FORGET;
     300            0 :                     break;
     301              :                 }
     302            0 :                 case SomeIpCallSemantic::SEMANTIC_UNKNOWN:
     303              :                 {
     304            0 :                     errorCode = ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE;
     305            0 :                     break;
     306              :                 }
     307              :             }
     308              :         }
     309              :     }
     310              : 
     311            2 :     auto const localPortResult = channel.getLocalPort();
     312            2 :     if (!localPortResult.has_value())
     313              :     {
     314            0 :         WARN_LOG(SOMEIP, "RpcHandler::handleMessage() no local port available");
     315            0 :         return ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE;
     316              :     }
     317            2 :     auto const localPort = localPortResult.value();
     318              : 
     319            2 :     switch (message.getMessageType())
     320              :     {
     321            2 :         case SomeIpMessage::MessageType::REQUEST:
     322              :         case SomeIpMessage::MessageType::REQUEST_NO_RETURN:
     323              :         {
     324            2 :             errorCode = handleRequest(
     325            2 :                 message, channel.getRemoteEndpoint(), localPort, channel.getProto());
     326            2 :             break;
     327              :         }
     328            0 :         case SomeIpMessage::MessageType::RESPONSE:
     329              :         {
     330            0 :             errorCode = handleResponse(message, channel.getRemoteEndpoint(), localPort);
     331            0 :             break;
     332              :         }
     333            0 :         case SomeIpMessage::MessageType::NOTIFICATION:
     334              :         {
     335            0 :             if (message.getMessageId() != SD_MESSAGE_ID)
     336              :             {
     337            0 :                 handleNotification(message, channel.getRemoteEndpoint(), localPort);
     338              :             }
     339              :             else
     340              :             {
     341            0 :                 WARN_LOG(SOMEIP, "RpcHandler::handleMessage(): dropping SD message");
     342              :             }
     343            0 :             break;
     344              :         }
     345            0 :         case SomeIpMessage::MessageType::EXCEPTION:
     346              :         {
     347            0 :             (void)handleError(message, channel.getRemoteEndpoint());
     348            0 :             errorCode = IRpcHandler::ErrorCode::RPC_HANDLER_OK; // ignore errors
     349            0 :             break;
     350              :         }
     351            0 :         default:
     352              :         {
     353            0 :             WARN_LOG(
     354              :                 SOMEIP,
     355              :                 "RpcHandler::handleMessage(): dropping message (serviceId 0x%x, messageType 0x%x)",
     356              :                 message.getServiceId(),
     357              :                 message.getMessageType());
     358            0 :             errorCode = IRpcHandler::ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE;
     359            0 :             break;
     360              :         }
     361              :     }
     362              : 
     363            2 :     return errorCode;
     364              : }
     365              : 
     366            9 : RpcHandler::ErrorCode RpcHandler::handleResponse(
     367              :     SomeIpMessage const& message, IPEndpoint const& sourceAddress, port::type const localPort)
     368              : {
     369            9 :     RpcHandler::ErrorCode result     = RpcHandler::ErrorCode::RPC_HANDLER_ERROR;
     370            9 :     service_id::type const serviceId = message.getServiceId();
     371            9 :     uint16_t const clientId          = static_cast<uint16_t>(message.getClientId());
     372            9 :     uint16_t const methodId          = message.getMethodId();
     373            9 :     uint32_t const payloadLength     = message.getPayloadLength();
     374            9 :     INFO_LOG(
     375              :         SOMEIP,
     376              :         "RpcHandler::handleResponse(serviceId %d, clientId %d, methodId %d, %d bytes)",
     377              :         serviceId,
     378              :         clientId,
     379              :         methodId,
     380              :         payloadLength);
     381              : 
     382              :     IRpcChannel* const pChannel
     383            9 :         = findChannel(serviceId, clientId, sourceAddress, message.getSessionId());
     384            9 :     if (pChannel == nullptr)
     385              :     {
     386            4 :         WARN_LOG(SOMEIP, "RpcHandler::handleResponse(): no channel waiting");
     387            4 :         result = RpcHandler::ErrorCode::RPC_HANDLER_NOT_RESPONSIBLE;
     388              :     }
     389            5 :     else if (pChannel->getLocalPort() != localPort)
     390              :     {
     391            1 :         WARN_LOG(SOMEIP, "RpcHandler::handleResponse(): wrong local port");
     392            1 :         result = RpcHandler::ErrorCode::RPC_HANDLER_ERROR;
     393              :     }
     394              :     else
     395              :     {
     396            4 :         unregisterChannel(*pChannel);
     397            4 :         pChannel->cancelTimeout();
     398            4 :         ISomeIpSerializable* const pResponse = pChannel->getResponse();
     399            4 :         if (pResponse != nullptr)
     400              :         {
     401              :             SomeIpParser parser(
     402            0 :                 ::etl::span<uint8_t const>(message.getPayload(), message.getPayloadLength()));
     403            0 :             pResponse->parseFromArray(parser);
     404            0 :             if (parser.isGood() == false)
     405              :             {
     406            0 :                 WARN_LOG(SOMEIP, "RpcHandler::handleResponse(): invalid payload");
     407            0 :                 pChannel->responseReceived(::someip::RPC_INVALID_PAYLOAD);
     408              :             }
     409              :         }
     410              : 
     411            4 :         pChannel->responseReceived(getRpcErrorCode(
     412              :             static_cast<typename SomeIpMessage::ReturnCode>(message.getReturnCode())));
     413              : 
     414            4 :         result = RpcHandler::ErrorCode::RPC_HANDLER_OK;
     415              :     }
     416              : 
     417            9 :     return result;
     418              : }
     419              : 
     420            3 : void RpcHandler::handleNotification(
     421              :     SomeIpMessage const& message, IPEndpoint const& sourceAddress, port::type const localPort)
     422              : {
     423            3 :     uint32_t const messageId = message.getMessageId();
     424            3 :     if (messageId != SD_MESSAGE_ID)
     425              :     {
     426            3 :         service_id::type const serviceId       = message.getServiceId();
     427            3 :         major_version::type const majorVersion = message.getInterfaceVersion();
     428            3 :         uint16_t const eventId                 = message.getMethodId();
     429            3 :         instance_id::type instanceId           = _serviceRegistry.getInstanceId(
     430            3 :             serviceId, majorVersion, sourceAddress.getAddress(), sourceAddress.getPort());
     431              : 
     432            3 :         DEBUG_LOG(
     433              :             SOMEIP,
     434              :             "RpcHandler::handleNotification(serviceId %d, eventId %d, instanceId %d, majorVersion "
     435              :             "%d)",
     436              :             serviceId,
     437              :             eventId,
     438              :             instanceId,
     439              :             majorVersion);
     440              : 
     441            3 :         if (instanceId == instance_id::ANY)
     442              :         {
     443              :             char addressStr[::ip::MAX_ENDPOINT_STRING_LENGTH];
     444            0 :             char* const addressStrPtr = ::ip::to_str(sourceAddress, addressStr).data();
     445            0 :             WARN_LOG(
     446              :                 SOMEIP,
     447              :                 "Invalid InstanceId for serviceId: %d majorVersion: %d address: %s",
     448              :                 serviceId,
     449              :                 majorVersion,
     450              :                 addressStrPtr);
     451            0 :             return;
     452              :         }
     453              : 
     454            3 :         if (!_serviceRegistry.isEventgroupPort(serviceId, instanceId, majorVersion, localPort))
     455              :         {
     456            1 :             WARN_LOG(SOMEIP, "RpcHandler::handleNotification(): invalid local port");
     457            1 :             return;
     458              :         }
     459              : 
     460            2 :         if (_pEventReceiver != nullptr)
     461              :         {
     462              :             SomeIpParser parser(
     463            1 :                 ::etl::span<uint8_t const>(message.getPayload(), message.getPayloadLength()));
     464            1 :             _pEventReceiver->eventReceived(serviceId, eventId, instanceId, majorVersion, parser);
     465              :         }
     466              :         else
     467              :         {
     468            1 :             WARN_LOG(SOMEIP, "RpcHandler::handleNotification(): no event receiver registered");
     469              :         }
     470            2 :         return;
     471              :     }
     472              : 
     473            0 :     WARN_LOG(SOMEIP, "RpcHandler::handleNotification(): invalid messageId: 0x%x", messageId);
     474              : }
     475              : 
     476              : RpcHandler::ErrorCode
     477            5 : RpcHandler::handleError(SomeIpMessage const& message, IPEndpoint const& sourceAddress)
     478              : {
     479            5 :     service_id::type const serviceId           = message.getServiceId();
     480            5 :     uint16_t const clientId                    = static_cast<uint16_t>(message.getClientId());
     481            5 :     uint16_t const methodId                    = message.getMethodId();
     482            5 :     SomeIpMessage::ReturnCode const returnCode = message.getReturnCode();
     483              : 
     484            5 :     INFO_LOG(
     485              :         SOMEIP,
     486              :         "RpcHandler::handleError(serviceId %d, clientId %d, methodId %d, error 0x%x)",
     487              :         serviceId,
     488              :         clientId,
     489              :         methodId,
     490              :         returnCode);
     491              : 
     492              :     IRpcChannel* const pChannel
     493            5 :         = findChannel(serviceId, clientId, sourceAddress, message.getSessionId());
     494            5 :     if (pChannel != nullptr)
     495              :     {
     496            4 :         unregisterChannel(*pChannel);
     497            4 :         pChannel->cancelTimeout();
     498            4 :         pChannel->responseReceived(getRpcErrorCode(returnCode));
     499            4 :         return RpcHandler::ErrorCode::RPC_HANDLER_OK;
     500              :     }
     501              : 
     502            1 :     WARN_LOG(SOMEIP, "RpcHandler::handleError(): no channel waiting");
     503            1 :     return RpcHandler::ErrorCode::RPC_HANDLER_ERROR;
     504              : }
     505              : 
     506            8 : ServiceResultCode RpcHandler::getRpcErrorCode(SomeIpMessage::ReturnCode const error)
     507              : {
     508            8 :     switch (error)
     509              :     {
     510            4 :         case SomeIpMessage::ReturnCode::SOMEIP_E_OK:
     511              :         {
     512            4 :             return ::someip::RPC_POSITIVE_RESPONSE;
     513              :         }
     514            1 :         case SomeIpMessage::ReturnCode::SOMEIP_E_NOT_OK:
     515              :         {
     516            1 :             return ::someip::RPC_UNDEFINED_ERROR;
     517              :         }
     518            0 :         case SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_SERVICE:
     519              :         {
     520            0 :             return ::someip::RPC_SERVICE_NOT_AVAILABLE;
     521              :         }
     522            0 :         case SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_METHOD:
     523              :         {
     524            0 :             return ::someip::RPC_METHOD_NOT_AVAILABLE;
     525              :         }
     526            1 :         case SomeIpMessage::ReturnCode::SOMEIP_E_WRONG_PROTOCOL_VERSION:
     527              :         {
     528            1 :             return ::someip::RPC_WRONG_PROTOCOL_VERSION;
     529              :         }
     530            1 :         case SomeIpMessage::ReturnCode::SOMEIP_E_WRONG_INTERFACE_VERSION:
     531              :         {
     532            1 :             return ::someip::RPC_WRONG_INTERFACE_VERSION;
     533              :         }
     534            0 :         case SomeIpMessage::ReturnCode::SOMEIP_E_MALFORMED_MESSAGE:
     535              :         {
     536            0 :             return ::someip::RPC_INVALID_PAYLOAD;
     537              :         }
     538            1 :         default:
     539              :         {
     540            1 :             return ::someip::RPC_UNDEFINED_ERROR;
     541              :         }
     542              :     }
     543              : }
     544              : 
     545            0 : SomeIpMessage::ReturnCode RpcHandler::getSomeipErrorCode(ServiceResultCode const error)
     546              : {
     547            0 :     switch (error)
     548              :     {
     549            0 :         case ::someip::RPC_SERVICE_NOT_AVAILABLE:
     550              :         {
     551            0 :             return SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_SERVICE;
     552              :         }
     553            0 :         case ::someip::RPC_METHOD_NOT_AVAILABLE:
     554              :         {
     555            0 :             return SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_METHOD;
     556              :         }
     557            0 :         case ::someip::RPC_INVALID_PAYLOAD:
     558              :         {
     559            0 :             return SomeIpMessage::ReturnCode::SOMEIP_E_MALFORMED_MESSAGE;
     560              :         }
     561            0 :         default:
     562              :         {
     563            0 :             return SomeIpMessage::ReturnCode::SOMEIP_E_NOT_OK;
     564              :         }
     565              :     }
     566              : }
     567              : 
     568           11 : ServiceResultCode RpcHandler::sendRequest(
     569              :     ISomeIpSerializable const* pRequest,
     570              :     service_id::type const serviceId,
     571              :     uint16_t const methodId,
     572              :     uint8_t const interfaceVersion,
     573              :     bool const isResponseExpected,
     574              :     IRpcChannel& channel,
     575              :     uint32_t timeout)
     576              : {
     577           11 :     auto const localPortResult = channel.getLocalPort();
     578           11 :     if (!localPortResult.has_value())
     579              :     {
     580            0 :         WARN_LOG(SOMEIP, "RpcHandler::sendRequest() no local port available");
     581            0 :         return COULD_NOT_DELIVER;
     582              :     }
     583              : 
     584           11 :     auto const localPort = localPortResult.value();
     585           11 :     auto const remoteIp  = channel.getRemoteIp();
     586           11 :     auto const proto     = channel.getProto();
     587           11 :     auto networkChannel  = _network.getRpcChannel(localPort, remoteIp, proto);
     588           11 :     auto const sessionId = channel.getSessionId();
     589           11 :     auto const clientId  = channel.getClientId();
     590              : 
     591           11 :     if (!networkChannel.has_value())
     592              :     {
     593            0 :         WARN_LOG(SOMEIP, "RpcHandler::sendRequest() no channel");
     594            0 :         return COULD_NOT_DELIVER;
     595              :     }
     596              : 
     597           11 :     auto const output = networkChannel->getOutputBuffer();
     598              : 
     599           11 :     if (SomeIpMessage::OFFSET_PAYLOAD > output.size())
     600              :     {
     601            0 :         ERROR_LOG(SOMEIP, "RpcHandler::sendRequest(): buffer too small for message header");
     602            0 :         return COULD_NOT_DELIVER;
     603              :     }
     604              : 
     605           11 :     SomeIpMessage message(output);
     606           11 :     message.setServiceId(serviceId);
     607           11 :     message.setMethodId(methodId);
     608           11 :     message.setClientId(clientId);
     609           11 :     message.setSessionId(sessionId);
     610           11 :     message.setPayloadLength(0U);
     611           11 :     message.setProtocolVersion(::someip::configuration::PROTOCOL_VERSION);
     612           11 :     message.setInterfaceVersion(interfaceVersion);
     613           11 :     message.setReturnCode(SomeIpMessage::ReturnCode::SOMEIP_E_OK);
     614              : 
     615           11 :     if (pRequest != nullptr)
     616              :     {
     617              :         SomeIpSerializer serializer(
     618            7 :             ::etl::span<uint8_t>(message.getPayload(), message.getMaximumPayloadLength()));
     619            7 :         pRequest->serializeToArray(serializer);
     620            7 :         if (serializer.isGood() == false)
     621              :         {
     622            2 :             WARN_LOG(SOMEIP, "RpcHandler::sendRequest(): invalid payload");
     623            2 :             return COULD_NOT_DELIVER;
     624              :         }
     625            5 :         message.setPayloadLength(static_cast<uint32_t>(serializer.getCurrentPosition()));
     626              :     }
     627            9 :     if (isResponseExpected)
     628              :     {
     629            9 :         message.setMessageType(SomeIpMessage::MessageType::REQUEST);
     630              : 
     631            9 :         registerChannel(channel);
     632            9 :         channel.setTimeout(_ethernetContext, timeout);
     633              :     }
     634              :     else
     635              :     {
     636            0 :         message.setMessageType(SomeIpMessage::MessageType::REQUEST_NO_RETURN);
     637              :     }
     638              : 
     639            9 :     bool result                    = false;
     640            9 :     auto const networkChannelProto = networkChannel->getProto();
     641            9 :     auto const messageTotalLength  = message.getTotalLength();
     642            9 :     if (ITpTransceiver::isOutgoingTpMessage(networkChannelProto, messageTotalLength))
     643              :     {
     644            0 :         result = _tpTransceiver.sendTpMessage(*networkChannel, message);
     645              :     }
     646              :     else
     647              :     {
     648            9 :         result = networkChannel->send(messageTotalLength);
     649              :     }
     650              : 
     651            9 :     if (!result)
     652              :     {
     653            1 :         WARN_LOG(SOMEIP, "RpcHandler::sendRequest() send failed");
     654            1 :         if (isResponseExpected)
     655              :         {
     656            1 :             unregisterChannel(channel);
     657            1 :             channel.cancelTimeout();
     658              :         }
     659              : 
     660            1 :         return COULD_NOT_DELIVER;
     661              :     }
     662              : 
     663            8 :     Statistics::incCounter(Statistics::Counter::PDU_TX);
     664            8 :     return RPC_SENT_SUCCESSFULLY;
     665           11 : }
     666              : 
     667            0 : void RpcHandler::requestExpired(IRpcChannel& channel) { unregisterChannel(channel); }
     668              : 
     669            2 : ServiceResultCode RpcHandler::requestDone(RequestContext& context, ServiceResultCode const result)
     670              : {
     671              :     // make sure we cleanup after ourselves when we are done
     672            2 :     RequestContextCleanup const cleanup(context);
     673              : 
     674            2 :     if ((result != ::someip::RPC_POSITIVE_RESPONSE)
     675            0 :         && (context.requestMessageType != SomeIpMessage::MessageType::REQUEST_NO_RETURN))
     676              :     {
     677            0 :         return sendError(
     678              :             context.requestId,
     679            0 :             context.serviceId,
     680            0 :             context.methodId,
     681            0 :             context.interfaceVersion,
     682            0 :             static_cast<uint8_t>(getSomeipErrorCode(result)),
     683            0 :             context.localPort,
     684            0 :             context.proto,
     685            0 :             context.remoteIp);
     686              :     }
     687              : 
     688            2 :     if (SomeIpMessage::MessageType::REQUEST == context.requestMessageType)
     689              :     {
     690            2 :         auto channel = _network.getRpcChannel(context.localPort, context.remoteIp, context.proto);
     691              : 
     692            2 :         if (!channel.has_value())
     693              :         {
     694            0 :             WARN_LOG(SOMEIP, "RpcHandler::requestDone() no channel");
     695            0 :             return COULD_NOT_DELIVER;
     696              :         }
     697              : 
     698            2 :         auto const output = channel->getOutputBuffer();
     699              : 
     700            2 :         SomeIpMessage message(output);
     701            2 :         message.setRequestId(context.requestId);
     702            2 :         message.setServiceId(context.serviceId);
     703            2 :         message.setMethodId(context.methodId);
     704            2 :         message.setMessageType(SomeIpMessage::MessageType::RESPONSE);
     705            2 :         message.setProtocolVersion(::someip::configuration::PROTOCOL_VERSION);
     706            2 :         message.setInterfaceVersion(context.interfaceVersion);
     707            2 :         message.setReturnCode(static_cast<SomeIpMessage::ReturnCode>(context.operationResult));
     708              : 
     709            2 :         ISomeIpSerializable* const pResponse = context.pResponse;
     710            2 :         if (pResponse != nullptr)
     711              :         {
     712              :             SomeIpSerializer serializer(
     713            0 :                 ::etl::span<uint8_t>(message.getPayload(), message.getMaximumPayloadLength()));
     714            0 :             pResponse->serializeToArray(serializer);
     715            0 :             if (serializer.isGood() == false)
     716              :             {
     717            0 :                 WARN_LOG(SOMEIP, "RpcHandler::requestDone() invalid payload");
     718            0 :                 return COULD_NOT_DELIVER;
     719              :             }
     720            0 :             message.setPayloadLength(static_cast<uint32_t>(serializer.getCurrentPosition()));
     721              :         }
     722              :         else
     723              :         {
     724            2 :             message.setPayloadLength(0U);
     725              :         }
     726              : 
     727            2 :         uint32_t const length = message.getTotalLength();
     728              : 
     729              :         bool tpMessageSent;
     730            2 :         if (ITpTransceiver::isOutgoingTpMessage(channel->getProto(), length))
     731              :         {
     732            0 :             tpMessageSent = _tpTransceiver.sendTpMessage(*channel, message);
     733              :         }
     734              :         else
     735              :         {
     736            2 :             tpMessageSent = channel->send(length);
     737              :         }
     738              : 
     739            2 :         if (!tpMessageSent)
     740              :         {
     741            2 :             WARN_LOG(SOMEIP, "RpcHandler::requestDone() send failed");
     742            2 :             return COULD_NOT_DELIVER;
     743              :         }
     744              : 
     745            0 :         Statistics::incCounter(Statistics::Counter::PDU_TX);
     746            2 :     }
     747              : 
     748            0 :     return RPC_SENT_SUCCESSFULLY;
     749            2 : }
     750              : 
     751            0 : ServiceResultCode RpcHandler::sendError(
     752              :     uint32_t const requestId,
     753              :     service_id::type const serviceId,
     754              :     uint16_t const methodId,
     755              :     uint8_t const interfaceVersion,
     756              :     uint8_t const returnCode,
     757              :     port::type const localPort,
     758              :     proto::type const proto,
     759              :     IPEndpoint const& remoteIp) const
     760              : {
     761            0 :     auto channel = _network.getRpcChannel(localPort, remoteIp, proto);
     762              : 
     763            0 :     if (!channel.has_value())
     764              :     {
     765            0 :         WARN_LOG(SOMEIP, "RpcHandler::sendError() no channel");
     766            0 :         return COULD_NOT_DELIVER;
     767              :     }
     768              : 
     769            0 :     auto const output = channel->getOutputBuffer();
     770              : 
     771            0 :     SomeIpMessage message(output);
     772            0 :     message.setMessageType(SomeIpMessage::MessageType::EXCEPTION);
     773            0 :     message.setRequestId(requestId);
     774            0 :     message.setServiceId(serviceId);
     775            0 :     message.setMethodId(methodId);
     776            0 :     message.setPayloadLength(0U);
     777            0 :     message.setProtocolVersion(::someip::configuration::PROTOCOL_VERSION);
     778            0 :     message.setInterfaceVersion(interfaceVersion);
     779            0 :     message.setReturnCode(static_cast<SomeIpMessage::ReturnCode>(returnCode));
     780              : 
     781            0 :     uint32_t const length = message.getTotalLength();
     782            0 :     if (length > output.size())
     783              :     {
     784            0 :         ERROR_LOG(
     785              :             SOMEIP,
     786              :             "RpcHandler::sendError() length %d exceeds max of %d bytes",
     787              :             length,
     788              :             output.size());
     789            0 :         return COULD_NOT_DELIVER;
     790              :     }
     791              : 
     792            0 :     bool const result = channel->send(length);
     793              : 
     794            0 :     if (!result)
     795              :     {
     796            0 :         WARN_LOG(SOMEIP, "RpcHandler::sendError() send failed");
     797              :     }
     798              : 
     799            0 :     return result ? RPC_SENT_SUCCESSFULLY : COULD_NOT_DELIVER;
     800            0 : }
     801              : 
     802            6 : size_t RpcHandler::getNumRegisteredChannels() const { return _rpcChannelList.size(); }
     803              : 
     804            9 : void RpcHandler::registerChannel(IRpcChannel& channel)
     805              : {
     806            9 :     if (!_rpcChannelList.contains_node(channel))
     807              :     {
     808            9 :         _rpcChannelList.push_front(channel);
     809              :     }
     810              :     else
     811              :     {
     812            0 :         WARN_LOG(SOMEIP, "RpcHandler::registerChannel() channel already registered!");
     813              :     }
     814            9 : }
     815              : 
     816              : // private
     817            9 : void RpcHandler::unregisterChannel(IRpcChannel& channel)
     818              : {
     819            9 :     if (_rpcChannelList.contains_node(channel))
     820              :     {
     821           18 :         _rpcChannelList.remove_if([&channel](IRpcChannel const& ch) { return &ch == &channel; });
     822              :     }
     823            9 : }
     824              : 
     825              : // private
     826           14 : IRpcChannel* RpcHandler::findChannel(
     827              :     service_id::type const serviceId,
     828              :     uint16_t const clientId,
     829              :     IPEndpoint const& remoteIp,
     830              :     uint16_t const sessionId)
     831              : {
     832           17 :     for (auto& itr : _rpcChannelList)
     833              :     {
     834           23 :         if ((itr.getServiceId() == serviceId) && (itr.getClientId() == clientId)
     835           23 :             && (itr.getRemoteIp() == remoteIp) && (itr.getSessionId() == sessionId))
     836              :         {
     837            9 :             return &itr;
     838              :         }
     839              :     }
     840              : 
     841            5 :     return nullptr;
     842              : }
     843              : 
     844              : } // namespace someip
     845              : 
     846              : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
        

Generated by: LCOV version 2.0-1