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