Diag-Client-Lib
doip_routing_activation_handler.cpp
Go to the documentation of this file.
1 /* Diagnostic Client library
2  * Copyright (C) 2024 Avijit Dey
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8 
10 
11 #include <utility>
12 
15 #include "common/logger.h"
16 #include "utility/state.h"
17 #include "utility/sync_timer.h"
18 
19 namespace doip_client {
20 namespace channel {
21 namespace tcp_channel {
22 namespace {
23 
27 constexpr std::uint8_t kDoip_RoutingActivation_ReqActType_Default{0x00};
28 constexpr std::uint8_t kDoip_RoutingActivation_ReqActType_WWHOBD{0x01};
29 constexpr std::uint8_t kDoip_RoutingActivation_ReqActType_CentralSec{0xE0};
30 
34 constexpr std::uint8_t kDoip_RoutingActivation_ResCode_UnknownSA{0x00};
36 constexpr std::uint8_t kDoip_RoutingActivation_ResCode_DifferentSA{0x02};
37 constexpr std::uint8_t kDoip_RoutingActivation_ResCode_ActiveSA{0x03};
41 constexpr std::uint8_t kDoip_RoutingActivation_ResCode_TLSRequired{0x07};
44 
48 constexpr std::uint32_t kDoip_RoutingActivation_ReqMinLen{7u}; //without OEM specific use byte
49 constexpr std::uint32_t kDoip_RoutingActivation_ResMinLen{9u}; //without OEM specific use byte
50 constexpr std::uint32_t kDoip_RoutingActivation_ReqMaxLen{11u}; //with OEM specific use byte
51 constexpr std::uint32_t kDoip_RoutingActivation_ResMaxLen{13u}; //with OEM specific use byte
52 
56 constexpr std::uint16_t kDoip_RoutingActivation_ReqType{0x0005};
57 constexpr std::uint16_t kDoip_RoutingActivation_ResType{0x0006};
58 
62 constexpr std::uint32_t kDoIPRoutingActivationTimeout{1000u}; // 1 sec
63 
67 enum class RoutingActivationState : std::uint8_t {
68  kIdle = 0U,
72 };
73 
77 class kIdle final : public utility::state::State<RoutingActivationState> {
78  public:
84  explicit kIdle(RoutingActivationState state) : State<RoutingActivationState>(state) {}
85 
89  void Start() override {}
90 
94  void Stop() override {}
95 };
96 
100 class kWaitForRoutingActivationRes final : public utility::state::State<RoutingActivationState> {
101  public:
108 
112  void Start() override {}
113 
117  void Stop() override {}
118 };
119 
123 class kRoutingActivationSuccessful final : public utility::state::State<RoutingActivationState> {
124  public:
131 
135  void Start() override {}
136 
140  void Stop() override {}
141 };
142 
146 class kRoutingActivationFailed final : public utility::state::State<RoutingActivationState> {
147  public:
154 
158  void Start() override {}
159 
163  void Stop() override {}
164 };
165 
166 } // namespace
167 
172  std::uint8_t act_type_;
173 };
174 
178 std::ostream &operator<<(std::ostream &msg, RoutingActivationAckType act_type) {
179  switch (act_type.act_type_) {
181  msg << "unknown source address.";
182  break;
184  msg << "all Socket active.";
185  break;
187  msg << "SA different on already connected socket.";
188  break;
190  msg << "SA active on different socket.";
191  break;
193  msg << "missing authentication.";
194  break;
196  msg << "rejected confirmation.";
197  break;
199  msg << "unsupported routing activation type.";
200  break;
202  msg << "required TLS socket.";
203  break;
204  default:
205  msg << "unknown reason.";
206  break;
207  }
208  msg << " (0x" << std::hex << static_cast<int>(act_type.act_type_) << ")";
209  return msg;
210 }
211 
216  public:
221 
226 
233  : tcp_socket_handler_{tcp_socket_handler},
234  state_context_{},
235  sync_timer_{} {
236  // create and add state for routing activation
237  // kIdle
238  state_context_.AddState(RoutingActivationState::kIdle, std::make_unique<kIdle>(RoutingActivationState::kIdle));
239  // kWaitForRoutingActivationRes
241  RoutingActivationState::kWaitForRoutingActivationRes,
242  std::make_unique<kWaitForRoutingActivationRes>(RoutingActivationState::kWaitForRoutingActivationRes));
243  // kRoutingActivationSuccessful
245  RoutingActivationState::kRoutingActivationSuccessful,
246  std::make_unique<kRoutingActivationSuccessful>(RoutingActivationState::kRoutingActivationSuccessful));
247  // kRoutingActivationFailed
249  RoutingActivationState::kRoutingActivationFailed,
250  std::make_unique<kRoutingActivationFailed>(RoutingActivationState::kRoutingActivationFailed));
251  // Transit to idle state
252  state_context_.TransitionTo(RoutingActivationState::kIdle);
253  }
254 
258  void Start() {}
259 
264  void Stop() {
266  state_context_.TransitionTo(RoutingActivationState::kIdle);
267  }
268 
273  void Reset() { Stop(); }
274 
280 
285  auto GetSocketHandler() noexcept -> sockets::TcpSocketHandler & { return tcp_socket_handler_; }
286 
291  auto GetSyncTimer() noexcept -> SyncTimer & { return sync_timer_; }
292 
293  private:
298 
303 
308 };
309 
311  : handler_impl_{std::make_unique<RoutingActivationHandlerImpl>(tcp_socket_handler)} {}
312 
314 
316 
318 
320 
322  RoutingActivationState final_state{RoutingActivationState::kRoutingActivationFailed};
323  if (handler_impl_->GetStateContext().GetActiveState().GetState() ==
324  RoutingActivationState::kWaitForRoutingActivationRes) {
325  // get the ack code
326  RoutingActivationAckType const rout_act_type{doip_payload.GetPayload()[0u]};
327  switch (rout_act_type.act_type_) {
329  // routing successful
330  final_state = RoutingActivationState::kRoutingActivationSuccessful;
331  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
332  __FILE__, __LINE__, __func__, [&doip_payload](std::stringstream &msg) {
333  msg << "RoutingActivation successfully activated in remote server with logical Address"
334  << " (0x" << std::hex << doip_payload.GetServerAddress() << ")";
335  });
336  } break;
338  // trigger routing activation after sometime, not implemented yet
339  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
340  __FILE__, __LINE__, __func__, [&doip_payload](std::stringstream &msg) {
341  msg << "RoutingActivation is activated, confirmation required in remote server with logical Address"
342  << " (0x" << std::hex << doip_payload.GetServerAddress() << ")";
343  });
344  } break;
345  default:
346  // failure, do nothing
347  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogWarn(
348  __FILE__, __LINE__, __func__,
349  [&rout_act_type](std::stringstream &msg) { msg << "Routing activation denied due to " << rout_act_type; });
350  break;
351  }
352  handler_impl_->GetStateContext().TransitionTo(final_state);
353  handler_impl_->GetSyncTimer().CancelWait();
354  } else {
355  /* ignore */
356  }
357 }
358 
360  uds_transport::UdsMessageConstPtr routing_activation_request) noexcept
364  if (handler_impl_->GetStateContext().GetActiveState().GetState() == RoutingActivationState::kIdle) {
365  if (SendRoutingActivationRequest(std::move(routing_activation_request)) ==
367  // Wait for routing activation response
368  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kWaitForRoutingActivationRes);
369  handler_impl_->GetSyncTimer().WaitForTimeout(
370  [this, &result]() {
372  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
373  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
374  __FILE__, __LINE__, "", [](std::stringstream &msg) {
375  msg << "RoutingActivation response timeout, no response received in: "
376  << kDoIPRoutingActivationTimeout << " milliseconds";
377  });
378  },
379  [this, &result]() {
380  if (handler_impl_->GetStateContext().GetActiveState().GetState() ==
381  RoutingActivationState::kRoutingActivationSuccessful) {
382  // success
384  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
385  __FILE__, __LINE__, "",
386  [](std::stringstream &msg) { msg << "RoutingActivation successful with remote server"; });
387  } else { // failed
388  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
389  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
390  __FILE__, __LINE__, "",
391  [](std::stringstream &msg) { msg << "RoutingActivation failed with remote server"; });
392  }
393  },
394  std::chrono::milliseconds{kDoIPRoutingActivationTimeout});
395  } else {
396  // failed, do nothing
397  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
398  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
399  __FILE__, __LINE__, "",
400  [](std::stringstream &msg) { msg << "RoutingActivation Request send failed with remote server"; });
401  }
402  } else {
403  // channel not free
404  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogVerbose(
405  __FILE__, __LINE__, "", [](std::stringstream &msg) { msg << "RoutingActivation channel not free"; });
406  }
407  return result;
408 }
409 
411  return (handler_impl_->GetStateContext().GetActiveState().GetState() ==
412  RoutingActivationState::kRoutingActivationSuccessful);
413 }
414 
419  TcpMessagePtr doip_routing_act_req{std::make_unique<TcpMessage>()};
420  // reserve bytes in vector
421  doip_routing_act_req->GetTxBuffer().reserve(kDoipheadrSize + kDoip_RoutingActivation_ReqMinLen);
422  // create header
423  CreateDoipGenericHeader(doip_routing_act_req->GetTxBuffer(), kDoip_RoutingActivation_ReqType,
425  // Add source address
426  doip_routing_act_req->GetTxBuffer().emplace_back(static_cast<std::uint8_t>((message->GetSa() & 0xFF00) >> 8u));
427  doip_routing_act_req->GetTxBuffer().emplace_back(static_cast<std::uint8_t>(message->GetSa() & 0x00FF));
428  // Add activation type
429  doip_routing_act_req->GetTxBuffer().emplace_back(kDoip_RoutingActivation_ReqActType_Default);
430  // Add reservation byte , default zeroes
431  doip_routing_act_req->GetTxBuffer().emplace_back(0x00);
432  doip_routing_act_req->GetTxBuffer().emplace_back(0x00);
433  doip_routing_act_req->GetTxBuffer().emplace_back(0x00);
434  doip_routing_act_req->GetTxBuffer().emplace_back(0x00);
435 
436  // Initiate transmission
437  if (handler_impl_->GetSocketHandler().Transmit(std::move(doip_routing_act_req))) {
439  }
440  return ret_val;
441 }
442 
443 void RoutingActivationHandler::CreateDoipGenericHeader(std::vector<std::uint8_t> &doip_header_buffer,
444  std::uint16_t payload_type, std::uint32_t payload_len) {
445  doip_header_buffer.emplace_back(kDoip_ProtocolVersion);
446  doip_header_buffer.emplace_back(~(static_cast<std::uint8_t>(kDoip_ProtocolVersion)));
447  doip_header_buffer.emplace_back(static_cast<std::uint8_t>((payload_type & 0xFF00) >> 8));
448  doip_header_buffer.emplace_back(static_cast<std::uint8_t>(payload_type & 0x00FF));
449  doip_header_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0xFF000000) >> 24));
450  doip_header_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0x00FF0000) >> 16));
451  doip_header_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0x0000FF00) >> 8));
452  doip_header_buffer.emplace_back(static_cast<std::uint8_t>(payload_len & 0x000000FF));
453 }
454 
455 } // namespace tcp_channel
456 } // namespace channel
457 } // namespace doip_client
Immutable class to store received doip message.
Definition: doip_message.h:21
auto GetStateContext() noexcept -> RoutingActivationStateContext &
Function to get the Routing Activation State context.
RoutingActivationHandlerImpl(sockets::TcpSocketHandler &tcp_socket_handler)
Constructs an instance of RoutingActivationHandlerImpl.
auto GetSocketHandler() noexcept -> sockets::TcpSocketHandler &
Function to get the socket handler.
sockets::TcpSocketHandler::TcpMessagePtr TcpMessagePtr
Type alias for Tcp message pointer.
static void CreateDoipGenericHeader(std::vector< std::uint8_t > &doip_header, std::uint16_t payload_type, std::uint32_t payload_len)
Function to create doip generic header.
void ProcessDoIPRoutingActivationResponse(DoipMessage &doip_payload) noexcept
Function to process received routing activation response.
auto SendRoutingActivationRequest(uds_transport::UdsMessageConstPtr routing_activation_request) noexcept -> uds_transport::UdsTransportProtocolMgr::TransmissionResult
Function to send routing activation request.
~RoutingActivationHandler()
Destruct an instance of RoutingActivationHandler.
RoutingActivationHandler(sockets::TcpSocketHandler &tcp_socket_handler)
Constructs an instance of RoutingActivationHandler.
std::unique_ptr< RoutingActivationHandlerImpl > handler_impl_
Stores the Handler implementation.
auto HandleRoutingActivationRequest(uds_transport::UdsMessageConstPtr routing_activation_request) noexcept -> uds_transport::UdsTransportProtocolMgr::ConnectionResult
Function to handle sending of routing activation request.
auto IsRoutingActivated() noexcept -> bool
Check if routing activation is active for this handler.
static auto GetDiagClientLogger() noexcept -> DoipClientLogger &
Definition: logger.h:20
Class used to create a tcp socket for handling transmission and reception of tcp message from driver.
void TransitionTo(EnumState state)
Definition: state.h:69
void AddState(EnumState state, std::unique_ptr< State< EnumState >> state_ptr)
Definition: state.h:58
void CancelWait()
Function to cancel the synchronous wait.
Definition: sync_timer.h:90
auto IsTimerActive()
Function to query if timer is running.
Definition: sync_timer.h:82
constexpr std::uint8_t kDoip_RoutingActivation_ResCode_UnknownSA
Routing Activation response code values.
constexpr std::uint8_t kDoip_RoutingActivation_ReqActType_Default
Routing Activation request activation types.
constexpr std::uint32_t kDoIPRoutingActivationTimeout
The timeout value for a DoIP Routing Activation request.
std::ostream & operator<<(std::ostream &msg, DiagAckType diag_ack_type)
Function to stream the diagnostic acknowledgement type.
void CreateDoipGenericHeader(std::vector< std::uint8_t > &doip_header_buffer, std::uint16_t payload_type, std::uint32_t payload_len)
Create the doip generic header.
constexpr std::uint8_t kDoipheadrSize
constexpr std::uint8_t kDoip_ProtocolVersion
std::unique_ptr< const UdsMessage > UdsMessageConstPtr
Definition: uds_message.h:69