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/TpTransceiver.h"
12 :
13 : #include "bsp/timer/SystemTimer.h"
14 : #include "someip/logger.h"
15 :
16 : #include <util/timeout/ITimeoutManager2.h>
17 :
18 : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
19 : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
20 :
21 : namespace someip
22 : {
23 : using ::common::ITimeoutManager2;
24 : using ::util::logger::SOMEIP;
25 :
26 15 : TpTransceiver::TpTransceiver(
27 : ::async::ContextType const ethernetContext,
28 : ::etl::span<TpSender*>& senders,
29 15 : ::etl::span<TpReceiver*>& receivers)
30 15 : : _ethernetContext(ethernetContext)
31 15 : , _cyclicFunction(::async::Function::CallType::create<TpTransceiver, &TpTransceiver::cyclic>(*this))
32 : , _cyclicTimeout()
33 15 : , _senders(senders)
34 15 : , _receivers(receivers)
35 15 : , _busy(false)
36 15 : {}
37 :
38 2 : void TpTransceiver::stop()
39 : {
40 2 : if (_busy)
41 : {
42 1 : _cyclicTimeout.cancel();
43 1 : _busy = false;
44 : }
45 :
46 3 : for (TpReceiver* const receiver : _receivers)
47 : {
48 1 : if ((receiver != nullptr) && (receiver->isActive()))
49 : {
50 1 : receiver->stop();
51 : }
52 : }
53 2 : }
54 :
55 : // virtual
56 3 : bool TpTransceiver::sendTpMessage(NetworkChannel& channel, SomeIpMessage const& message) const
57 : {
58 3 : if (_senders.size() == 0U)
59 : {
60 0 : ERROR_LOG(SOMEIP, "TpTransceiver::sendTpMessage(): no sender available!");
61 0 : return false;
62 : }
63 :
64 3 : TpSender::TpResult const result = _senders.at(0U)->send(channel, message); // sync !
65 :
66 3 : return (TpSender::TpResult::TP_OK == result);
67 : }
68 :
69 : // virtual
70 11 : void TpTransceiver::receiveTpMessage(
71 : NetworkChannel& channel, SomeIpMessage const& message, ITpListener& listener)
72 : {
73 11 : TpReceiver* receiver = nullptr;
74 11 : TpReceiver* idle = nullptr;
75 :
76 18 : for (TpReceiver* const item : _receivers)
77 : {
78 11 : if (item != nullptr)
79 : {
80 11 : if (item->isMatching(channel, message))
81 : {
82 4 : receiver = item;
83 4 : break;
84 : }
85 7 : if ((idle == nullptr) && (!item->isActive()))
86 : {
87 6 : idle = item;
88 : }
89 : }
90 : }
91 :
92 11 : if ((receiver == nullptr) && (idle != nullptr))
93 : {
94 6 : receiver = idle;
95 : }
96 :
97 11 : if (receiver == nullptr)
98 : {
99 1 : ERROR_LOG(SOMEIP, "TpTransceiver::receiveTpMessage(): no receiver available!");
100 1 : return;
101 : }
102 :
103 10 : if (!receiver->isActive())
104 : {
105 6 : receiver->start(channel, message, listener);
106 : }
107 :
108 10 : uint32_t const time = static_cast<uint32_t>(getSystemTimeMs32Bit());
109 :
110 10 : TpReceiver::TpResult const result = receiver->receive(channel, message, time); // async !
111 :
112 10 : if (TpReceiver::TpResult::TP_PENDING == result)
113 : {
114 5 : if (!_busy)
115 : {
116 5 : async::schedule(
117 5 : _ethernetContext,
118 : _cyclicFunction,
119 5 : _cyclicTimeout,
120 : TP_UPDATE_CYCLE,
121 : ::async::TimeUnit::MILLISECONDS);
122 :
123 5 : _busy = true;
124 : }
125 : }
126 : else
127 : {
128 5 : receiver->stop();
129 :
130 5 : if (_busy)
131 : {
132 4 : bool busy = false;
133 :
134 8 : for (TpReceiver* const item : _receivers)
135 : {
136 4 : if ((item != nullptr) && (item->isActive()))
137 : {
138 0 : busy = true;
139 0 : break;
140 : }
141 : }
142 :
143 4 : if (!busy)
144 : {
145 4 : _cyclicTimeout.cancel();
146 4 : _busy = false;
147 : }
148 : }
149 : }
150 : }
151 :
152 0 : void TpTransceiver::cyclic()
153 : {
154 0 : uint32_t const time = static_cast<uint32_t>(getSystemTimeMs32Bit());
155 :
156 0 : bool busy = false;
157 :
158 0 : for (TpReceiver* const receiver : _receivers)
159 : {
160 0 : if (receiver != nullptr)
161 : {
162 0 : if (receiver->isExpired(time))
163 : {
164 0 : WARN_LOG(SOMEIP, "TpTransceiver::expired(): tp-receiver[%p] timeout!", receiver);
165 :
166 0 : receiver->stop();
167 : }
168 0 : else if (receiver->isActive())
169 : {
170 0 : busy = true;
171 : }
172 : else
173 : {
174 : // nothing to do
175 : }
176 : }
177 : }
178 :
179 0 : _busy = busy;
180 :
181 0 : if (_busy)
182 : {
183 0 : async::schedule(
184 0 : _ethernetContext,
185 : _cyclicFunction,
186 0 : _cyclicTimeout,
187 : TP_UPDATE_CYCLE,
188 : ::async::TimeUnit::MILLISECONDS);
189 : }
190 0 : }
191 :
192 : } // namespace someip
193 :
194 : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
|