Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2026 BMW AG
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 : #pragma once
12 :
13 : #include <etl/memory.h>
14 : #include <io/IWriter.h>
15 : #include <ip/IPAddress.h>
16 : #include <routing/ErrorHandler.h>
17 : #include <routing/Logger.h>
18 : #include <routing/util.h>
19 : #include <udp/socket/AbstractDatagramSocket.h>
20 :
21 : #include <platform/estdint.h>
22 :
23 : namespace io
24 : {
25 : namespace udp
26 : {
27 : namespace logger = ::util::logger;
28 :
29 : class Receiver : private ::udp::IDataListener
30 : {
31 : public:
32 99 : Receiver(
33 : ::udp::AbstractDatagramSocket& socket,
34 : ::io::IWriter& output,
35 : ::routing::ErrorHandler const errorHandler,
36 : ::etl::span<uint8_t const> const remoteIpAddresses = {})
37 198 : : _socket(socket)
38 99 : , _output(output)
39 99 : , _errorHandler(errorHandler)
40 99 : , _remoteIpAddresses(remoteIpAddresses)
41 99 : , _lastAllocationFailed(false)
42 99 : , _invalidIpAddressPdus()
43 198 : , _failedMemAllocPdus()
44 : {
45 99 : _socket.setDataListener(this);
46 99 : }
47 :
48 96 : virtual ~Receiver() {}
49 :
50 9 : ::routing::StatCounter::Type invalidIpAddressPdus() const { return _invalidIpAddressPdus; }
51 :
52 9 : ::routing::StatCounter::Type failedMemAllocPdus() const { return _failedMemAllocPdus; }
53 :
54 : private:
55 12 : void dataReceived(
56 : ::udp::AbstractDatagramSocket& /* socket */,
57 : ::ip::IPAddress sourceAddress,
58 : uint16_t /* sourcePort */,
59 : ::ip::IPAddress /* destinationAddress */,
60 : uint16_t length) override
61 : {
62 12 : if (!_remoteIpAddresses.empty())
63 : {
64 5 : auto const sourceIpAddress = ::ip::packed(sourceAddress);
65 5 : auto remoteIpAddresses = _remoteIpAddresses;
66 5 : bool isValidAddress = false;
67 35 : while (!remoteIpAddresses.empty())
68 : {
69 : auto const remoteIpAddress
70 34 : = remoteIpAddresses.take<uint8_t const>(sourceIpAddress.size());
71 34 : if (::etl::mem_compare(
72 : sourceIpAddress.begin(), sourceIpAddress.end(), remoteIpAddress.begin())
73 34 : == 0)
74 : {
75 4 : isValidAddress = true;
76 4 : break;
77 : }
78 : }
79 :
80 5 : if (!isValidAddress)
81 : {
82 1 : (void)_socket.read(nullptr, length);
83 :
84 1 : _errorHandler(
85 : ::routing::ErrorHandler::StatusCode::INVALID_REMOTE_IP_ADDRESS, sourceAddress);
86 :
87 1 : ++_invalidIpAddressPdus;
88 :
89 1 : return;
90 : }
91 : }
92 :
93 11 : auto const frame = _output.allocate(length);
94 11 : if (frame.size() != length)
95 : {
96 4 : (void)_socket.read(nullptr, length);
97 :
98 4 : if (!_lastAllocationFailed)
99 : {
100 3 : _errorHandler(::routing::ErrorHandler::StatusCode::MEM_ALLOCATION_FAILURE);
101 3 : _lastAllocationFailed = true;
102 : }
103 :
104 4 : ++_failedMemAllocPdus;
105 :
106 4 : return;
107 : }
108 7 : _lastAllocationFailed = false;
109 :
110 7 : (void)_socket.read(frame.data(), length);
111 :
112 7 : _output.commit();
113 : }
114 :
115 : ::udp::AbstractDatagramSocket& _socket;
116 : ::io::IWriter& _output;
117 : ::routing::ErrorHandler const _errorHandler;
118 : ::etl::span<uint8_t const> const _remoteIpAddresses;
119 : bool _lastAllocationFailed;
120 :
121 : mutable ::routing::StatCounter _invalidIpAddressPdus;
122 : mutable ::routing::StatCounter _failedMemAllocPdus;
123 : };
124 :
125 : } // namespace udp
126 : } // namespace io
|