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)
|