Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2024 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 : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg): Logger/StringWriter API is variadic by design.
12 :
13 : #include "transport/routing/TransportRouterSimple.h"
14 :
15 : #include "busid/BusId.h"
16 : #include "transport/ITransportMessageProcessedListener.h"
17 :
18 : #include <async/Async.h>
19 : #include <transport/TpRouterLogger.h>
20 :
21 : namespace transport
22 : {
23 : using ::util::logger::Logger;
24 : using ::util::logger::TPROUTER;
25 :
26 : namespace
27 : {
28 7 : bool is1ByteDiagAddressBus(uint8_t const busId)
29 : {
30 7 : return (busId != ::busid::ETH_0) && (busId != ::busid::ETH_1);
31 : }
32 : } // namespace
33 :
34 48 : TransportRouterSimple::TransportRouterSimple() : _transportLayers()
35 : {
36 16 : for (uint8_t i = 0U; i < NUM_BUFFERS; i++)
37 : {
38 12 : _locked[i] = false;
39 12 : _message[i].init(_buffer[i], BUFFER_SIZE);
40 : }
41 36 : for (uint8_t i = 0U; i < NUM_FUNCTIONAL_BUFFERS; i++)
42 : {
43 32 : _functionalLocked[i] = false;
44 32 : _functionalMessage[i].init(_functionalBuffer[i], FUNCTIONAL_BUFFER_SIZE);
45 : }
46 4 : _busIdToReply = ::busid::SELFDIAG;
47 4 : }
48 :
49 4 : void TransportRouterSimple::init() { _transportLayers.clear(); }
50 :
51 4 : void TransportRouterSimple::shutdown() { _transportLayers.clear(); }
52 :
53 2 : ITransportMessageProvidingListener::ErrorCode TransportRouterSimple::getTransportMessage(
54 : uint8_t const srcBusId,
55 : uint16_t const sourceAddress,
56 : uint16_t const targetId,
57 : uint16_t const size,
58 : ::etl::span<uint8_t const> const& /* peek */,
59 : TransportMessage*& pTransportMessage)
60 : {
61 2 : Logger::debug(
62 : TPROUTER,
63 : "TransportRouterSimple::getTransportMessage : sourceAddress 0x%x, targetId 0x%x",
64 : sourceAddress,
65 : targetId);
66 2 : pTransportMessage = nullptr;
67 :
68 2 : ::async::LockType const lockGuard;
69 : uint16_t const targetId2Byte
70 2 : = is1ByteDiagAddressBus(srcBusId)
71 2 : ? TransportConfiguration::convert1ByteAddressTo2Byte(targetId)
72 2 : : targetId;
73 :
74 2 : if (TransportConfiguration::isFunctionalAddress(targetId2Byte))
75 : {
76 1 : if (size <= TransportConfiguration::MAX_FUNCTIONAL_MESSAGE_PAYLOAD_SIZE)
77 : {
78 1 : for (uint8_t i = 0U; i < NUM_FUNCTIONAL_BUFFERS; i++)
79 : {
80 1 : if (!_functionalLocked[i])
81 : {
82 1 : _functionalMessage[i].init(_functionalBuffer[i], FUNCTIONAL_BUFFER_SIZE);
83 1 : pTransportMessage = &_functionalMessage[i];
84 1 : _functionalLocked[i] = true;
85 1 : return ErrorCode::TPMSG_OK;
86 : }
87 : }
88 : }
89 : }
90 :
91 1 : if (size > BUFFER_SIZE)
92 : {
93 1 : return ITransportMessageProvider::ErrorCode::TPMSG_SIZE_TOO_LARGE;
94 : }
95 :
96 0 : for (uint8_t i = 0U; i < NUM_BUFFERS; i++)
97 : {
98 0 : if (!_locked[i])
99 : {
100 0 : _message[i].init(_buffer[i], BUFFER_SIZE);
101 0 : pTransportMessage = &_message[i];
102 0 : _locked[i] = true;
103 0 : return ErrorCode::TPMSG_OK;
104 : }
105 : }
106 :
107 0 : return ErrorCode::TPMSG_NO_MSG_AVAILABLE;
108 2 : }
109 :
110 1 : void TransportRouterSimple::releaseTransportMessage(TransportMessage& transportMessage)
111 : {
112 1 : ::async::LockType const lockGuard;
113 4 : for (uint8_t i = 0U; i < NUM_BUFFERS; i++)
114 : {
115 3 : if (&transportMessage == &_message[i])
116 : {
117 0 : _locked[i] = false;
118 0 : return;
119 : }
120 : }
121 1 : for (uint8_t i = 0U; i < NUM_FUNCTIONAL_BUFFERS; i++)
122 : {
123 1 : if (&transportMessage == &_functionalMessage[i])
124 : {
125 1 : _functionalLocked[i] = false;
126 1 : return;
127 : }
128 : }
129 1 : }
130 :
131 3 : ITransportMessageProvidingListener::ReceiveResult TransportRouterSimple::messageReceived(
132 : uint8_t const sourceBusId,
133 : TransportMessage& transportMessage,
134 : ITransportMessageProcessedListener* const pNotificationListener)
135 : {
136 3 : AbstractTransportLayer::ErrorCode result(AbstractTransportLayer::ErrorCode::TP_OK);
137 :
138 3 : if (is1ByteDiagAddressBus(sourceBusId))
139 : {
140 2 : transportMessage.setSourceAddress(
141 2 : TransportConfiguration::convert1ByteAddressTo2Byte(transportMessage.getSourceId()));
142 2 : transportMessage.setTargetAddress(
143 2 : TransportConfiguration::convert1ByteAddressTo2Byte(transportMessage.getTargetId()));
144 : }
145 :
146 3 : if ((sourceBusId == ::busid::CAN_0)
147 : #ifdef PLATFORM_SUPPORT_ETHERNET
148 3 : || (sourceBusId == ::busid::ETH_0)
149 : #endif
150 : )
151 : {
152 1 : _busIdToReply = sourceBusId;
153 1 : forwardMessageToTransportLayer(
154 : transportMessage, ::busid::SELFDIAG, pNotificationListener, result);
155 : }
156 2 : else if (sourceBusId == ::busid::SELFDIAG && _busIdToReply != ::busid::SELFDIAG)
157 : {
158 1 : forwardMessageToTransportLayer(
159 1 : transportMessage, _busIdToReply, pNotificationListener, result);
160 : }
161 : else
162 : {
163 1 : result = AbstractTransportLayer::ErrorCode::TP_SEND_FAIL;
164 : }
165 :
166 3 : if (result != AbstractTransportLayer::ErrorCode::TP_OK)
167 : {
168 1 : return ReceiveResult::RECEIVED_ERROR;
169 : }
170 2 : return ReceiveResult::RECEIVED_NO_ERROR;
171 : }
172 :
173 0 : void TransportRouterSimple::dump() {}
174 :
175 8 : void TransportRouterSimple::addTransportLayer(AbstractTransportLayer& transportLayer)
176 : {
177 8 : TransportLayerList::iterator itr = _transportLayers.begin();
178 8 : TransportLayerList::iterator const e_itr = _transportLayers.end();
179 12 : for (; itr != e_itr; ++itr)
180 : {
181 4 : if (itr->getBusId() == transportLayer.getBusId())
182 : {
183 0 : Logger::error(
184 : TPROUTER,
185 : "TpLayer for bus %s must not be registered multiple times",
186 0 : ::common::busid::BusIdTraits::getName(itr->getBusId()));
187 0 : return;
188 : }
189 : }
190 8 : transportLayer.fProvidingListenerHelper.fpMessageListener = this;
191 8 : transportLayer.fProvidingListenerHelper.fpMessageProvider = this;
192 8 : _transportLayers.push_back(transportLayer);
193 : }
194 :
195 8 : void TransportRouterSimple::removeTransportLayer(AbstractTransportLayer& transportLayer)
196 : {
197 8 : if (!_transportLayers.contains_node(transportLayer))
198 : {
199 0 : return;
200 : }
201 8 : transportLayer.fProvidingListenerHelper.fpMessageListener = nullptr;
202 8 : transportLayer.fProvidingListenerHelper.fpMessageProvider = nullptr;
203 8 : _transportLayers.erase(transportLayer);
204 : }
205 :
206 2 : void TransportRouterSimple::forwardMessageToTransportLayer(
207 : TransportMessage& transportMessage,
208 : uint8_t const destBusId,
209 : ITransportMessageProcessedListener* const pNotificationListener,
210 : AbstractTransportLayer::ErrorCode& result)
211 : {
212 2 : if (is1ByteDiagAddressBus(destBusId))
213 : {
214 1 : transportMessage.setSourceAddress(
215 1 : TransportConfiguration::convert2ByteAddressTo1Byte(transportMessage.getSourceId()));
216 1 : transportMessage.setTargetAddress(
217 1 : TransportConfiguration::convert2ByteAddressTo1Byte(transportMessage.getTargetId()));
218 : }
219 :
220 3 : for (TransportLayerList::iterator itr = _transportLayers.begin(); itr != _transportLayers.end();
221 1 : ++itr)
222 : {
223 3 : if (itr->getBusId() == destBusId)
224 : {
225 2 : result = itr->send(transportMessage, pNotificationListener);
226 2 : break;
227 : }
228 : }
229 2 : }
230 :
231 : } // namespace transport
232 :
233 : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
|