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/RpcReceiver.h"
12 :
13 : #include "someip/INetwork.h"
14 : #include "someip/IServiceRegistry.h"
15 : #include "someip/SomeIpConstants.h"
16 : #include "someip/SomeIpMessage.h"
17 : #include "someip/Statistics.h"
18 : #include "someip/logger.h"
19 :
20 : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
21 : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
22 :
23 : namespace someip
24 : {
25 : using ::util::logger::SOMEIP;
26 :
27 : using ::ip::IPAddress;
28 : using ::ip::IPEndpoint;
29 :
30 21 : RpcReceiver::RpcReceiver(
31 : INetwork& network,
32 : ITpTransceiver& tpTransceiver,
33 : IEventReceiver& eventReceiver,
34 : IServiceRegistry& serviceRegistry,
35 : IRpcHandler& rpcHandler,
36 : MulticastReceptionList& multicastReceptionList,
37 21 : IDiagnosticListener* const diagnosticListener)
38 21 : : _network(network)
39 21 : , _tpTransceiver(tpTransceiver)
40 21 : , _eventReceiver(eventReceiver)
41 21 : , _pDiagnosticListener(diagnosticListener)
42 21 : , _serviceRegistry(serviceRegistry)
43 21 : , _rpcHandler(rpcHandler)
44 21 : , _pPriorityRpcHandler(nullptr)
45 21 : , _multicastReceptions(multicastReceptionList)
46 : {
47 : (void)_serviceRegistry;
48 21 : _network.setRpcListener(*this);
49 21 : }
50 :
51 2 : void RpcReceiver::init() { _rpcHandler.setEventReceiver(_eventReceiver); }
52 :
53 2 : void RpcReceiver::shutdown() { _rpcHandler.removeEventReceiver(); }
54 :
55 : // virtual
56 14 : void RpcReceiver::received(NetworkChannel& channel, uint32_t const length)
57 : {
58 14 : Statistics::incCounter(Statistics::Counter::FRAME_RX);
59 :
60 14 : ::etl::span<uint8_t> const input = channel.getInputBuffer();
61 :
62 14 : uint32_t offset = 0U;
63 23 : while (offset < length)
64 : {
65 16 : uint32_t const bytesLeft = length - offset;
66 16 : if (bytesLeft < SomeIpMessage::OFFSET_PAYLOAD)
67 : {
68 3 : ERROR_LOG(
69 : SOMEIP,
70 : "RpcReceiver::dataReceived(): %d bytes left, but no valid header",
71 : bytesLeft);
72 3 : Statistics::incCounter(Statistics::Counter::RPC_MALFORMED_MESSAGE_RX);
73 7 : return;
74 : }
75 :
76 13 : Statistics::incCounter(Statistics::Counter::PDU_RX);
77 :
78 13 : SomeIpMessage const message(input.subspan(offset, bytesLeft));
79 :
80 13 : uint32_t const payloadLength = message.getPayloadLength();
81 13 : if (payloadLength <= bytesLeft - SomeIpMessage::OFFSET_PAYLOAD)
82 : {
83 10 : offset += (payloadLength + SomeIpMessage::OFFSET_PAYLOAD);
84 : }
85 : else
86 : {
87 3 : ERROR_LOG(
88 : SOMEIP,
89 : "RpcReceiver::dataReceived(): %d bytes left, but expected is %d",
90 : bytesLeft,
91 : payloadLength + SomeIpMessage::OFFSET_PAYLOAD);
92 3 : Statistics::incCounter(Statistics::Counter::RPC_MALFORMED_MESSAGE_RX);
93 3 : if ((message.getMessageType() != SomeIpMessage::MessageType::REQUEST_NO_RETURN)
94 3 : && (message.getMessageType() != SomeIpMessage::MessageType::NOTIFICATION))
95 : {
96 1 : sendError(channel, message, SomeIpMessage::ReturnCode::SOMEIP_E_MALFORMED_MESSAGE);
97 : }
98 3 : return;
99 : }
100 :
101 10 : if ((message.getReturnCode() != SomeIpMessage::ReturnCode::SOMEIP_E_OK)
102 10 : && (message.getMessageType() != SomeIpMessage::MessageType::EXCEPTION))
103 : {
104 1 : WARN_LOG(
105 : SOMEIP,
106 : "RpcReceiver::dataReceived(): invalid return code: %d",
107 : message.getReturnCode());
108 1 : return; // drop incoming SOME/IP error message
109 : }
110 :
111 9 : if (message.getProtocolVersion() != configuration::PROTOCOL_VERSION)
112 : {
113 3 : WARN_LOG(
114 : SOMEIP,
115 : "RpcReceiver::dataReceived(): invalid protocol version %d",
116 : message.getProtocolVersion());
117 3 : Statistics::incCounter(Statistics::Counter::RPC_WRONG_PROTOCOL_VERSION_RX);
118 3 : if ((message.getMessageType() != SomeIpMessage::MessageType::REQUEST_NO_RETURN)
119 3 : && (message.getMessageType() != SomeIpMessage::MessageType::NOTIFICATION))
120 : {
121 1 : sendError(
122 : channel, message, SomeIpMessage::ReturnCode::SOMEIP_E_WRONG_PROTOCOL_VERSION);
123 : }
124 5 : continue; // drop message
125 : }
126 :
127 6 : if (isMagicCookie(message))
128 : {
129 2 : DEBUG_LOG(
130 : SOMEIP,
131 : "RpcReceiver::dataReceived(): ignore magic-cookie (0x%X)",
132 : message.getMessageId());
133 2 : continue; // NYI: ignore message
134 : }
135 :
136 4 : if (ITpTransceiver::isIncomingTpMessage(channel.getProto(), message.getMessageType()))
137 : {
138 0 : _tpTransceiver.receiveTpMessage(channel, message, *this);
139 : }
140 : else
141 : {
142 4 : handleMessage(channel, message);
143 : }
144 : }
145 : }
146 :
147 : // virtual
148 1 : void RpcReceiver::receivedTpMessage(NetworkChannel& channel, SomeIpMessage const& message)
149 : {
150 1 : if ((message.getReturnCode() != SomeIpMessage::ReturnCode::SOMEIP_E_OK)
151 1 : && (message.getMessageType() != SomeIpMessage::MessageType::EXCEPTION))
152 : {
153 0 : WARN_LOG(
154 : SOMEIP,
155 : "RpcReceiver::receivedTpMessage(): invalid return code: %d",
156 : message.getReturnCode());
157 0 : return; // drop incoming SOME/IP error message
158 : }
159 :
160 1 : handleMessage(channel, message);
161 : }
162 :
163 : // virtual
164 4 : void RpcReceiver::setPriorityRpcHandler(IRpcHandler& priorityRpcHandler)
165 : {
166 4 : _pPriorityRpcHandler = &priorityRpcHandler;
167 4 : }
168 :
169 : // virtual
170 1 : void RpcReceiver::removePriorityRpcHandler() { _pPriorityRpcHandler = nullptr; }
171 :
172 : // virtual
173 5 : bool RpcReceiver::requestMulticastReception(IPEndpoint const& multicastEndpoint)
174 : {
175 5 : uint8_t const ip0 = multicastEndpoint.getAddress().raw[0];
176 5 : uint8_t const ip1 = multicastEndpoint.getAddress().raw[1];
177 5 : uint8_t const ip2 = multicastEndpoint.getAddress().raw[2];
178 5 : uint8_t const ip3 = multicastEndpoint.getAddress().raw[3];
179 5 : uint16_t const port = multicastEndpoint.getPort();
180 :
181 5 : if (_multicastReceptions.full())
182 : {
183 1 : WARN_LOG(
184 : SOMEIP,
185 : "RpcReceiver::requestMulticastReception() multicast pool empty. Unable to add "
186 : "(%d,%d,%d,%d), Port: %d.",
187 : ip0,
188 : ip1,
189 : ip2,
190 : ip3,
191 : port);
192 1 : return true;
193 : }
194 :
195 : // Check if already exists
196 : internal::FindNetworkChannelCondition const condition(
197 4 : multicastEndpoint.getAddress(), multicastEndpoint.getPort());
198 4 : if (::etl::find_if(_multicastReceptions.begin(), _multicastReceptions.end(), condition)
199 8 : != _multicastReceptions.end())
200 : {
201 1 : INFO_LOG(
202 : SOMEIP,
203 : "RpcReceiver::requestMulticastReception() channel already present for (%d,%d,%d,%d), "
204 : "Port: %d.",
205 : ip0,
206 : ip1,
207 : ip2,
208 : ip3,
209 : port);
210 1 : return true;
211 : }
212 :
213 : // Open a new channel
214 3 : auto const channel = _network.openUdpChannel(multicastEndpoint.getPort(), multicastEndpoint);
215 :
216 3 : if (!channel.has_value())
217 : {
218 1 : ERROR_LOG(
219 : SOMEIP,
220 : "RpcReceiver::requestMulticastReception() no channel. Unable to add (%d,%d,%d,%d), "
221 : "Port: %d.",
222 : ip0,
223 : ip1,
224 : ip2,
225 : ip3,
226 : port);
227 1 : return false;
228 : }
229 :
230 : // Insert the new channel
231 2 : auto insertResult = _multicastReceptions.insert(channel);
232 2 : if (!insertResult.second)
233 : {
234 0 : WARN_LOG(
235 : SOMEIP,
236 : "RpcReceiver::requestMulticastReception() not able to add channel for "
237 : "(%d,%d,%d,%d), Port: %d.",
238 : ip0,
239 : ip1,
240 : ip2,
241 : ip3,
242 : port);
243 0 : return false;
244 : }
245 :
246 2 : INFO_LOG(
247 : SOMEIP,
248 : "RpcReceiver::requestMulticastReception() channel added for (%d,%d,%d,%d), "
249 : "Port: %d.",
250 : ip0,
251 : ip1,
252 : ip2,
253 : ip3,
254 : port);
255 2 : return true;
256 3 : }
257 :
258 : // virtual
259 1 : void RpcReceiver::cancelMulticastReception(IPEndpoint const& multicastEndpoint)
260 : {
261 1 : auto channel = _network.getRpcChannel(
262 1 : multicastEndpoint.getPort(), multicastEndpoint, proto::SD_L4_PROTO_UDP);
263 :
264 1 : if (!channel.has_value())
265 : {
266 0 : WARN_LOG(SOMEIP, "RpcReceiver::cancelMulticastReception() no channel");
267 : }
268 : else
269 : {
270 1 : channel->close();
271 : internal::FindNetworkChannelCondition const condition(
272 1 : multicastEndpoint.getAddress(), multicastEndpoint.getPort());
273 1 : auto it = _multicastReceptions.begin();
274 1 : while (it != _multicastReceptions.end())
275 : {
276 1 : if (condition(*it))
277 : {
278 1 : _multicastReceptions.erase(it);
279 1 : break; // Found and removed the matching channel
280 : }
281 :
282 0 : ++it;
283 : }
284 : }
285 1 : }
286 :
287 : // private
288 : // static
289 6 : bool RpcReceiver::isMagicCookie(SomeIpMessage const& message)
290 : {
291 6 : uint32_t const messageId = message.getMessageId();
292 6 : uint32_t const requestId = message.getRequestId();
293 :
294 : return ((MAGIC_COOKIE_CLIENT_MESSAGE_ID == messageId)
295 5 : || (MAGIC_COOKIE_SERVER_MESSAGE_ID == messageId))
296 11 : && (MAGIC_COOKIE_REQUEST_ID == requestId);
297 : }
298 :
299 : // private
300 5 : void RpcReceiver::handleMessage(NetworkChannel& channel, SomeIpMessage const& message)
301 : {
302 5 : IRpcHandler::ErrorCode errorCode = IRpcHandler::ErrorCode::RPC_HANDLER_NOT_RESPONSIBLE;
303 :
304 5 : if (_pPriorityRpcHandler != nullptr)
305 : {
306 3 : errorCode = _pPriorityRpcHandler->handleMessage(channel, message);
307 : }
308 :
309 5 : if (errorCode == IRpcHandler::ErrorCode::RPC_HANDLER_NOT_RESPONSIBLE)
310 : {
311 2 : errorCode = _rpcHandler.handleMessage(channel, message);
312 : }
313 :
314 5 : if ((errorCode != IRpcHandler::ErrorCode::RPC_HANDLER_OK)
315 2 : && (errorCode != IRpcHandler::ErrorCode::RPC_HANDLER_NOT_RESPONSIBLE))
316 : {
317 2 : if ((message.getMessageType() != SomeIpMessage::MessageType::REQUEST_NO_RETURN)
318 1 : && ((message.getMessageType() != SomeIpMessage::MessageType::NOTIFICATION)
319 0 : || (errorCode
320 : != IRpcHandler::ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_REQUEST_RESPONSE))
321 3 : && (errorCode
322 : != IRpcHandler::ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE_FIRE_AND_FORGET))
323 : {
324 1 : sendError(channel, message, getSomeipErrorCode(errorCode));
325 : }
326 : }
327 5 : }
328 :
329 : // private
330 3 : void RpcReceiver::sendError(
331 : NetworkChannel& channel,
332 : SomeIpMessage const& message,
333 : SomeIpMessage::ReturnCode const returnCode)
334 : {
335 3 : DEBUG_LOG(SOMEIP, "RpcReceiver::sendError(0x%x)", returnCode);
336 :
337 3 : SomeIpMessage error(channel.getOutputBuffer());
338 3 : error.setMessageType(SomeIpMessage::MessageType::EXCEPTION);
339 3 : error.setRequestId(message.getRequestId());
340 3 : error.setServiceId(message.getServiceId());
341 3 : error.setMethodId(message.getMethodId());
342 3 : error.setPayloadLength(0U);
343 3 : error.setProtocolVersion(::someip::configuration::PROTOCOL_VERSION);
344 3 : error.setInterfaceVersion(message.getInterfaceVersion());
345 3 : error.setReturnCode(returnCode);
346 :
347 3 : uint16_t const length = static_cast<uint16_t>(error.getTotalLength());
348 3 : if (!channel.send(length))
349 : {
350 3 : WARN_LOG(SOMEIP, "SomeIpSdTransceiver: send failed");
351 : }
352 :
353 3 : if (_pDiagnosticListener != nullptr)
354 : {
355 3 : _pDiagnosticListener->onError(
356 : channel.getRemoteEndpoint(),
357 : message,
358 : static_cast<SomeIpMessage::ReturnCode>(returnCode));
359 : }
360 3 : }
361 :
362 : // static
363 1 : SomeIpMessage::ReturnCode RpcReceiver::getSomeipErrorCode(IRpcHandler::ErrorCode const error)
364 : {
365 1 : switch (error)
366 : {
367 0 : case IRpcHandler::ErrorCode::RPC_HANDLER_OK:
368 : {
369 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_OK;
370 : }
371 1 : case IRpcHandler::ErrorCode::RPC_HANDLER_UNKNOWN_SERVICE:
372 : {
373 1 : return SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_SERVICE;
374 : }
375 0 : case IRpcHandler::ErrorCode::RPC_HANDLER_UNKNOWN_METHOD:
376 : {
377 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_UNKNOWN_METHOD;
378 : }
379 0 : case IRpcHandler::ErrorCode::RPC_HANDLER_WRONG_INTERFACE_VERSION:
380 : {
381 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_WRONG_INTERFACE_VERSION;
382 : }
383 0 : case IRpcHandler::ErrorCode::RPC_HANDLER_MALFORMED_MESSAGE:
384 : {
385 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_MALFORMED_MESSAGE;
386 : }
387 0 : case IRpcHandler::ErrorCode::RPC_HANDLER_WRONG_MESSAGE_TYPE:
388 : {
389 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_WRONG_MESSAGE_TYPE;
390 : }
391 0 : default:
392 : {
393 0 : return SomeIpMessage::ReturnCode::SOMEIP_E_NOT_OK;
394 : }
395 : }
396 : }
397 :
398 : namespace internal
399 : {
400 :
401 1 : bool NetworkChannelComparator::operator()(
402 : ::etl::optional<NetworkChannel> const& lhs, ::etl::optional<NetworkChannel> const& rhs) const
403 : {
404 : // Handle empty optionals (though they shouldn't be inserted)
405 1 : if (!lhs.has_value() && !rhs.has_value())
406 : {
407 0 : return false;
408 : }
409 1 : if (!lhs.has_value())
410 : {
411 0 : return true; // Empty sorts before non-empty
412 : }
413 1 : if (!rhs.has_value())
414 : {
415 0 : return false; // Non-empty sorts after empty
416 : }
417 :
418 : // Lexicographic comparison for strict weak ordering
419 1 : auto const& lhs_addr = lhs.value().getRemoteEndpoint().getAddress();
420 1 : auto const& rhs_addr = rhs.value().getRemoteEndpoint().getAddress();
421 :
422 : #ifdef PLATFORM_SUPPORT_IPV6
423 : // IPv6-mapped IPv4 addresses: compare bytes 12-15
424 : for (size_t i = 12; i < 16; ++i)
425 : #else
426 : // Pure IPv4: compare bytes 0-3
427 4 : for (size_t i = 0; i < 4; ++i)
428 : #endif
429 : {
430 4 : if (lhs_addr.raw[i] != rhs_addr.raw[i])
431 : {
432 1 : return lhs_addr.raw[i] < rhs_addr.raw[i];
433 : }
434 : }
435 :
436 0 : auto const lhs_port = lhs.value().getLocalPort();
437 0 : auto const rhs_port = rhs.value().getLocalPort();
438 :
439 0 : if (!lhs_port.has_value() || !rhs_port.has_value())
440 : {
441 0 : return false;
442 : }
443 :
444 0 : return lhs_port.value() < rhs_port.value();
445 : }
446 :
447 5 : FindNetworkChannelCondition::FindNetworkChannelCondition(
448 5 : ::ip::IPAddress const& ipAddr, uint16_t const port)
449 5 : : _ip(ipAddr), _port(port)
450 5 : {}
451 :
452 4 : bool FindNetworkChannelCondition::operator()(::etl::optional<NetworkChannel> const& channel) const
453 : {
454 4 : if (!channel.has_value())
455 : {
456 0 : return false;
457 : }
458 4 : auto const address = channel->getRemoteEndpoint().getAddress();
459 4 : auto const port = channel->getRemoteEndpoint().getPort();
460 4 : return ((_ip == address) && (_port == port));
461 : }
462 :
463 : } // namespace internal
464 :
465 : } // namespace someip
466 :
467 : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
|