libdoip  0.1.0
DoIP (Diagnostics over Internet Protocol) ISO 13400 C++17 Library
DoIPDefaultConnection.h
Go to the documentation of this file.
1 #ifndef DOIPDEFAULTCONNECTION_H
2 #define DOIPDEFAULTCONNECTION_H
3 
4 #include "DoIPConfig.h"
5 #include "DoIPServerModel.h"
6 
8 #include "DoIPTimes.h"
9 #include "IConnectionContext.h"
10 #include "TimerManager.h"
11 #include <optional>
12 
13 namespace doip {
14 
15 using namespace std::chrono_literals;
16 
17 // Timer IDsD& config
18 enum class ConnectionTimers : uint8_t {
19  InitialInactivity, // T_TCP_Initial_Inactivity (default: 2s)
20  GeneralInactivity, // T_TCP_General_Inactivity (default: 5min)
21  AliveCheck, // T_TCP_Alive_Check (default: 500ms)
22  DownstreamResponse, // Server timeout when waiting for a response of the subnet device ("downstream") - not standardized by ISO 13400
23  UserDefined // Placeholder for user-defined timers ()
24 };
25 
26 inline std::ostream &operator<<(std::ostream &os, ConnectionTimers tid) {
27  switch (tid) {
29  return os << "Initial Inactivity";
31  return os << "General Inactivity";
33  return os << "Alive Check";
35  return os << "Downstream Response";
37  return os << "User Defined";
38  default:
39  return os << "Unknown(" << static_cast<int>(tid) << ")";
40  }
41 }
42 
43 using StateChangeHandler = std::function<void()>;
44 using MessageHandler = std::function<void(std::optional<DoIPMessage>)>;
45 using TimeOutHandler = std::function<void(ConnectionTimers)>;
46 
47 /**
48  * @brief Default implementation of IConnectionContext
49  *
50  * This class provides a default implementation of the IConnectionContext
51  * interface, including the state machine and server model. It excludes
52  * TCP socket support, making it suitable for non-TCP-based connections.
53  */
55 
56  /**
57  * @brief Descriptor for a state in the state machine
58  *
59  * Contains state, timer, transitions, handlers and timeout duration.
60  */
61  struct StateDescriptor {
62  /**
63  * @brief Constructor for StateDescriptor
64  * @param state_ The state represented
65  * @param timer_ The timer associated with this state
66  * @param stateAfterTimeout_ State to transition to after timeout
67  * @param handler_ Message handler for this state
68  * @param enterState_ Handler called when entering this state
69  * @param timeoutHandler_ Handler called on timeout
70  * @param timeoutDurationUser_ Custom timeout duration
71  */
72  StateDescriptor(DoIPServerState state_,
73  DoIPServerState stateAfterTimeout_,
74  MessageHandler handler_,
76  StateChangeHandler enterState_ = nullptr,
77  TimeOutHandler timeoutHandler_ = nullptr,
78  std::chrono::milliseconds timeoutDurationUser_ = 0ms)
79  : state(state_),
80  stateAfterTimeout(stateAfterTimeout_),
81  messageHandler(std::move(handler_)),
82  timer(timer_),
83  enterStateHandler(enterState_),
84  timeoutHandler(std::move(timeoutHandler_)),
85  timeoutDurationUser(timeoutDurationUser_) {}
86 
87  DoIPServerState state; ///< The state
88  DoIPServerState stateAfterTimeout; ///< State after timeout
89  MessageHandler messageHandler; ///< Message handler
90  ConnectionTimers timer; ///< Associated timer
91  StateChangeHandler enterStateHandler; ///< Handler on state entry
92  TimeOutHandler timeoutHandler; ///< Handler on timeout
93  std::chrono::milliseconds timeoutDurationUser{0}; ///< Custom timeout duration
94  };
95 
96  /**
97  * @brief Sets the client address for the connection
98  * @param address The client address
99  */
100  void setClientAddress(const DoIPAddress &address) override;
101 
102  public:
103  /**
104  * @brief Constructs a DoIPDefaultConnection
105  * @param model The server model to use
106  */
108 
109  /**
110  * @brief Sends a DoIP protocol message to the client
111  * @param msg The message to send
112  * @return Number of bytes sent
113  */
114  ssize_t sendProtocolMessage(const DoIPMessage &msg) override;
115 
116  /**
117  * @brief Closes the connection
118  * @param reason The reason for closure
119  */
120  void closeConnection(DoIPCloseReason reason) override;
121 
122  /**
123  * @brief Checks if the connection is open
124  * @return true if open, false otherwise
125  */
126  bool isOpen() const override {
127  return m_isOpen;
128  }
129 
130  /**
131  * @brief Gets the reason for connection closure
132  * @return The close reason
133  */
134  DoIPCloseReason getCloseReason() const override {
135  return m_closeReason;
136  }
137 
138  /**
139  * @brief Checks if routing is currently activated
140  * @return true if routing is activated, false otherwise
141  */
142  bool isRoutingActivated() const { return m_state && m_state->state == DoIPServerState::RoutingActivated; }
143 
144  /**
145  * @brief Gets the alive check retry count
146  * @return The number of alive check retries
147  */
148  uint8_t getAliveCheckRetryCount() const { return m_aliveCheckRetryCount; }
149 
150  /**
151  * @brief Gets the initial inactivity timeout duration
152  * @return The initial inactivity timeout in milliseconds
153  */
154  std::chrono::milliseconds getInitialInactivityTimeout() const { return m_initialInactivityTimeout; }
155 
156  /**
157  * @brief Gets the general inactivity timeout duration
158  * @return The general inactivity timeout in milliseconds
159  */
160  std::chrono::milliseconds getGeneralInactivityTimeout() const { return m_generalInactivityTimeout; }
161 
162  /**
163  * @brief Gets the alive check timeout duration
164  * @return The alive check timeout in milliseconds
165  */
166  std::chrono::milliseconds getAliveCheckTimeout() const { return m_aliveCheckTimeout; }
167 
168  /**
169  * @brief Gets the downstream response timeout duration
170  * @return The downstream response timeout in milliseconds
171  */
172  std::chrono::milliseconds getDownstreamResponseTimeout() const { return m_downstreamResponseTimeout; }
173 
174  /**
175  * @brief Sets the alive check retry count
176  * @param count The number of retries for alive checks
177  */
178  void setAliveCheckRetryCount(uint8_t count) { m_aliveCheckRetryCount = count; }
179 
180  /**
181  * @brief Sets the initial inactivity timeout duration
182  * @param timeout The timeout duration in milliseconds
183  */
184  void setInitialInactivityTimeout(std::chrono::milliseconds timeout) { m_initialInactivityTimeout = timeout; }
185 
186  /**
187  * @brief Sets the general inactivity timeout duration
188  * @param timeout The timeout duration in milliseconds
189  */
190  void setGeneralInactivityTimeout(std::chrono::milliseconds timeout) { m_generalInactivityTimeout = timeout; }
191 
192  /**
193  * @brief Sets the alive check timeout duration
194  * @param timeout The timeout duration in milliseconds
195  */
196  void setAliveCheckTimeout(std::chrono::milliseconds timeout) { m_aliveCheckTimeout = timeout; }
197 
198  /**
199  * @brief Sets the downstream response timeout duration
200  * @param timeout The timeout duration in milliseconds
201  */
202  void setDownstreamResponseTimeout(std::chrono::milliseconds timeout) { m_downstreamResponseTimeout = timeout; }
203 
204  /**
205  * @brief Gets the server's logical address
206  * @return The server address
207  */
208  DoIPAddress getServerAddress() const override;
209 
210  /**
211  * @brief Gets the client's address
212  * @return The client address
213  */
214  DoIPAddress getClientAddress() const override;
215 
216  /**
217  * @brief Handles an incoming diagnostic message
218  * @param msg The diagnostic message
219  * @return Diagnostic acknowledgment (ACK/NACK)
220  */
221  DoIPDiagnosticAck notifyDiagnosticMessage(const DoIPMessage &msg) override;
222 
223  /**
224  * @brief Notifies application that connection is closing
225  * @param reason The close reason
226  */
227  void notifyConnectionClosed(DoIPCloseReason reason) override;
228 
229  /**
230  * @brief Notifies application that diagnostic ACK/NACK was sent
231  * @param ack The acknowledgment sent
232  */
233  void notifyDiagnosticAckSent(DoIPDiagnosticAck ack) override;
234 
235  /**
236  * @brief Checks if a downstream handler is present
237  * @return true if present, false otherwise
238  */
239  bool hasDownstreamHandler() const override;
240 
241  /**
242  * @brief Notifies application of a downstream request
243  * @param msg The downstream request message
244  * @return Downstream result
245  */
246  DoIPDownstreamResult notifyDownstreamRequest(const DoIPMessage &msg) override;
247 
248  /**
249  * @brief Receives a downstream response
250  * @param response The downstream response message
251  * @param result the downstream result
252  */
253  void receiveDownstreamResponse(const ByteArray &response, DoIPDownstreamResult result) override;
254 
255  /**
256  * @brief Gets the current state of the connection
257  * @return The current DoIPServerState
258  */
260  return m_state->state;
261  }
262 
263  /**
264  * @brief Gets the server model
265  * @return Reference to the server model pointer
266  */
268  return m_serverModel;
269  }
270 
271  /**
272  * @brief Handles a message (internal helper)
273  * @param message The message to handle
274  */
275  void handleMessage2(const DoIPMessage &message);
276 
277  protected:
279  std::array<StateDescriptor, 7> STATE_DESCRIPTORS;
281 
282  bool m_isOpen;
284  const StateDescriptor *m_state = nullptr;
286 
287  // Alive check retry (not covered by the standard)
288  uint8_t m_aliveCheckRetry{0};
289  uint8_t m_aliveCheckRetryCount{DOIP_ALIVE_CHECK_RETRIES};
290 
291  // Timer values
292  std::chrono::milliseconds m_initialInactivityTimeout{times::server::InitialInactivityTimeout}; // 2 seconds
293  std::chrono::milliseconds m_generalInactivityTimeout{times::server::GeneralInactivityTimeout}; // 5 minutes
294  std::chrono::milliseconds m_aliveCheckTimeout{times::server::AliveCheckResponseTimeout}; // 500 ms
295  std::chrono::milliseconds m_downstreamResponseTimeout{10s}; // 500 ms
296 
297  // State transition
298  void transitionTo(DoIPServerState newState);
299 
300  // State timer
301  std::chrono::milliseconds getTimerDuration(StateDescriptor const *stateDesc);
302 
303  void startStateTimer(StateDescriptor const *stateDesc);
304  void restartStateTimer();
305 
306  // handlers for each state
307  void handleSocketInitialized(DoIPServerEvent event, OptDoIPMessage msg);
308  void handleWaitRoutingActivation(DoIPServerEvent event, OptDoIPMessage msg);
309  void handleRoutingActivated(DoIPServerEvent event, OptDoIPMessage msg);
310  void handleWaitAliveCheckResponse(DoIPServerEvent event, OptDoIPMessage msg);
311  void handleWaitDownstreamResponse(DoIPServerEvent event, OptDoIPMessage msg);
312  void handleFinalize(DoIPServerEvent event, OptDoIPMessage msg);
313 
314  /**
315  * @brief Default timeout handler
316  *
317  * @param timer_id the timer ID that expired
318  */
319  void handleTimeout(ConnectionTimers timer_id);
320 
321  ssize_t sendRoutingActivationResponse(const DoIPAddress &source_address, DoIPRoutingActivationResult response_code);
322  ssize_t sendAliveCheckRequest();
323  ssize_t sendDiagnosticMessageResponse(const DoIPAddress &sourceAddress, DoIPDiagnosticAck ack);
324  ssize_t sendDownstreamResponse(const DoIPAddress &sourceAddress, const ByteArray& payload);
325 };
326 
327 } // namespace doip
328 
329 #endif /* DOIPDEFAULTCONNECTION_H */
Default implementation of IConnectionContext.
TimerManager< ConnectionTimers > m_timerManager
std::chrono::milliseconds getDownstreamResponseTimeout() const
Gets the downstream response timeout duration.
void setAliveCheckRetryCount(uint8_t count)
Sets the alive check retry count.
bool isOpen() const override
Checks if the connection is open.
bool isRoutingActivated() const
Checks if routing is currently activated.
std::chrono::milliseconds getGeneralInactivityTimeout() const
Gets the general inactivity timeout duration.
std::chrono::milliseconds getInitialInactivityTimeout() const
Gets the initial inactivity timeout duration.
std::array< StateDescriptor, 7 > STATE_DESCRIPTORS
void setDownstreamResponseTimeout(std::chrono::milliseconds timeout)
Sets the downstream response timeout duration.
DoIPCloseReason getCloseReason() const override
Gets the reason for connection closure.
UniqueServerModelPtr m_serverModel
std::chrono::milliseconds getAliveCheckTimeout() const
Gets the alive check timeout duration.
void setInitialInactivityTimeout(std::chrono::milliseconds timeout)
Sets the initial inactivity timeout duration.
uint8_t getAliveCheckRetryCount() const
Gets the alive check retry count.
DoIPServerState getState() const
Gets the current state of the connection.
void setGeneralInactivityTimeout(std::chrono::milliseconds timeout)
Sets the general inactivity timeout duration.
void setAliveCheckTimeout(std::chrono::milliseconds timeout)
Sets the alive check timeout duration.
UniqueServerModelPtr & getServerModel()
Gets the server model.
Represents a complete DoIP message with internal ByteArray representation.
Definition: DoIPMessage.h:82
Interface between DoIPServerStateMachine and DoIPConnection.
constexpr std::chrono::milliseconds AliveCheckResponseTimeout(500)
Time in ms to wait for a alive check response.
constexpr std::chrono::milliseconds InitialInactivityTimeout(200)
Maximum inactivity time in ms after a TCP connection was accepted.
constexpr std::chrono::milliseconds GeneralInactivityTimeout(500)
Maximum inactivity time in ms after a TCP message was sent or received.
Definition: AnsiColors.h:3
std::function< void(std::optional< DoIPMessage >)> MessageHandler
std::function< void(ConnectionTimers)> TimeOutHandler
uint16_t DoIPAddress
Represents a 16-bit DoIP address consisting of high and low significant bytes.
Definition: DoIPAddress.h:26
DoIPServerState
std::optional< DoIPNegativeDiagnosticAck > DoIPDiagnosticAck
Alias for diagnostic acknowledgment type.
DoIPServerEvent
std::ostream & operator<<(std::ostream &os, const ByteArray &arr)
Stream operator for ByteArray.
Definition: ByteArray.h:303
DoIPDownstreamResult
Result of a downstream request initiation.
std::function< void()> StateChangeHandler
std::optional< DoIPMessage > OptDoIPMessage
Definition: DoIPMessage.h:65
DoIPCloseReason
Reason for connection closure.
std::unique_ptr< DoIPServerModel > UniqueServerModelPtr
A dynamic array of bytes with utility methods for network protocol handling.
Definition: ByteArray.h:60