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 kDoipRoutingActivationResCodeUnknownSa{0x00};
35 constexpr std::uint8_t kDoipRoutingActivationResCodeAllSocketActive{0x01};
36 constexpr std::uint8_t kDoipRoutingActivationResCodeDifferentSa{0x02};
37 constexpr std::uint8_t kDoipRoutingActivationResCodeActiveSa{0x03};
38 constexpr std::uint8_t kDoipRoutingActivationResCodeAuthentnMissng{0x04};
39 constexpr std::uint8_t kDoipRoutingActivationResCodeConfirmtnRejectd{0x05};
41 constexpr std::uint8_t kDoipRoutingActivationResCodeTlsRequired{0x07};
44 
48 constexpr std::uint32_t kDoipRoutingActivationReqMinLen{7u}; // without OEM specific use byte
49 constexpr std::uint32_t kDoipRoutingActivationReqMaxLen{11u}; // with OEM specific use byte
50 // constexpr std::uint32_t kDoip_RoutingActivation_ResMinLen{9u}; //without 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:
85 
89  void Start() override {}
90 
94  void Stop() override {}
95 };
96 
100 class kWaitForRoutingActivationRes final : public utility::state::State<RoutingActivationState> {
101  public:
108  : State<RoutingActivationState>(state) {}
109 
113  void Start() override {}
114 
118  void Stop() override {}
119 };
120 
124 class kRoutingActivationSuccessful final : public utility::state::State<RoutingActivationState> {
125  public:
132  : State<RoutingActivationState>(state) {}
133 
137  void Start() override {}
138 
142  void Stop() override {}
143 };
144 
148 class kRoutingActivationFailed final : public utility::state::State<RoutingActivationState> {
149  public:
156  : State<RoutingActivationState>(state) {}
157 
161  void Start() override {}
162 
166  void Stop() override {}
167 };
168 
173  std::uint8_t act_type_;
174 };
175 
179 std::ostream &operator<<(std::ostream &msg, RoutingActivationAckType act_type) {
180  switch (act_type.act_type_) {
182  msg << "unknown source address.";
183  break;
185  msg << "all socket active.";
186  break;
188  msg << "SA different on already connected socket.";
189  break;
191  msg << "SA active on different socket.";
192  break;
194  msg << "missing authentication.";
195  break;
197  msg << "rejected confirmation.";
198  break;
200  msg << "unsupported routing activation type.";
201  break;
203  msg << "required TLS socket.";
204  break;
205  default:
206  msg << "unknown reason.";
207  break;
208  }
209  msg << " (0x" << std::hex << static_cast<int>(act_type.act_type_) << ")";
210  return msg;
211 }
212 
220 auto CreateDoipGenericHeader(std::uint16_t payload_type, std::uint32_t payload_len) noexcept
221  -> std::vector<std::uint8_t> {
222  std::vector<std::uint8_t> output_buffer{};
223  output_buffer.emplace_back(kDoip_ProtocolVersion);
224  output_buffer.emplace_back(~(static_cast<std::uint8_t>(kDoip_ProtocolVersion)));
225  output_buffer.emplace_back(static_cast<std::uint8_t>((payload_type & 0xFF00) >> 8));
226  output_buffer.emplace_back(static_cast<std::uint8_t>(payload_type & 0x00FF));
227  output_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0xFF000000) >> 24));
228  output_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0x00FF0000) >> 16));
229  output_buffer.emplace_back(static_cast<std::uint8_t>((payload_len & 0x0000FF00) >> 8));
230  output_buffer.emplace_back(static_cast<std::uint8_t>(payload_len & 0x000000FF));
231  return output_buffer;
232 }
233 } // namespace
234 
239  public:
244 
249 
256  : tcp_socket_handler_{tcp_socket_handler},
257  state_context_{},
258  sync_timer_{} {
259  // create and add state for routing activation
260  // kIdle
261  state_context_.AddState(RoutingActivationState::kIdle,
262  std::make_unique<kIdle>(RoutingActivationState::kIdle));
263  // kWaitForRoutingActivationRes
264  state_context_.AddState(RoutingActivationState::kWaitForRoutingActivationRes,
265  std::make_unique<kWaitForRoutingActivationRes>(
266  RoutingActivationState::kWaitForRoutingActivationRes));
267  // kRoutingActivationSuccessful
268  state_context_.AddState(RoutingActivationState::kRoutingActivationSuccessful,
269  std::make_unique<kRoutingActivationSuccessful>(
270  RoutingActivationState::kRoutingActivationSuccessful));
271  // kRoutingActivationFailed
272  state_context_.AddState(RoutingActivationState::kRoutingActivationFailed,
273  std::make_unique<kRoutingActivationFailed>(
274  RoutingActivationState::kRoutingActivationFailed));
275  // Transit to idle state
276  state_context_.TransitionTo(RoutingActivationState::kIdle);
277  }
278 
282  void Start() {}
283 
288  void Stop() {
290  state_context_.TransitionTo(RoutingActivationState::kIdle);
291  }
292 
297  void Reset() { Stop(); }
298 
304 
309  auto GetSocketHandler() noexcept -> sockets::TcpSocketHandler & { return tcp_socket_handler_; }
310 
315  auto GetSyncTimer() noexcept -> SyncTimer & { return sync_timer_; }
316 
317  private:
322 
327 
332 };
333 
335  : handler_impl_{std::make_unique<RoutingActivationHandlerImpl>(tcp_socket_handler)} {}
336 
338 
340 
342 
344 
346  DoipMessage &doip_payload) noexcept -> void {
347  RoutingActivationState final_state{RoutingActivationState::kRoutingActivationFailed};
348  if (handler_impl_->GetStateContext().GetActiveState().GetState() ==
349  RoutingActivationState::kWaitForRoutingActivationRes) {
350  // get the ack code
351  RoutingActivationAckType const rout_act_type{doip_payload.GetPayload()[0u]};
352  switch (rout_act_type.act_type_) {
354  // routing successful
355  final_state = RoutingActivationState::kRoutingActivationSuccessful;
356  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
357  FILE_NAME, __LINE__, __func__, [&doip_payload](std::stringstream &msg) {
358  msg << "RoutingActivation successfully activated in remote "
359  "server with logical Address"
360  << " (0x" << std::hex << doip_payload.GetServerAddress() << ")";
361  });
362  } break;
364  // trigger routing activation after sometime, not implemented yet
365  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
366  FILE_NAME, __LINE__, __func__, [&doip_payload](std::stringstream &msg) {
367  msg << "RoutingActivation is activated, confirmation required in "
368  "remote server with logical Address"
369  << " (0x" << std::hex << doip_payload.GetServerAddress() << ")";
370  });
371  } break;
372  default:
373  // failure, do nothing
374  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogWarn(
375  FILE_NAME, __LINE__, __func__, [&rout_act_type](std::stringstream &msg) {
376  msg << "Routing activation denied due to " << rout_act_type;
377  });
378  break;
379  }
380  handler_impl_->GetStateContext().TransitionTo(final_state);
381  handler_impl_->GetSyncTimer().CancelWait();
382  } else {
383  /* ignore */
384  }
385 }
386 
388  uds_transport::UdsMessageConstPtr routing_activation_request) noexcept
392  if (handler_impl_->GetStateContext().GetActiveState().GetState() ==
393  RoutingActivationState::kIdle) {
394  if (SendRoutingActivationRequest(std::move(routing_activation_request)) ==
396  // Wait for routing activation response
397  handler_impl_->GetStateContext().TransitionTo(
398  RoutingActivationState::kWaitForRoutingActivationRes);
399  handler_impl_->GetSyncTimer().WaitForTimeout(
400  [this, &result]() {
402  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
403  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
404  FILE_NAME, __LINE__, "", [](std::stringstream &msg) {
405  msg << "RoutingActivation response timeout, no response "
406  "received in: "
407  << kDoIPRoutingActivationTimeout << " milliseconds";
408  });
409  },
410  [this, &result]() {
411  if (handler_impl_->GetStateContext().GetActiveState().GetState() ==
412  RoutingActivationState::kRoutingActivationSuccessful) {
413  // success
415  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
416  FILE_NAME, __LINE__, "", [](std::stringstream &msg) {
417  msg << "RoutingActivation successful with remote server";
418  });
419  } else { // failed
420  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
421  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
422  FILE_NAME, __LINE__, "", [](std::stringstream &msg) {
423  msg << "RoutingActivation failed with remote server";
424  });
425  }
426  },
427  std::chrono::milliseconds{kDoIPRoutingActivationTimeout});
428  } else {
429  // failed, do nothing
430  handler_impl_->GetStateContext().TransitionTo(RoutingActivationState::kIdle);
431  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogError(
432  FILE_NAME, __LINE__, "", [](std::stringstream &msg) {
433  msg << "RoutingActivation Request send failed with remote server";
434  });
435  }
436  } else {
437  // channel not free
438  logger::DoipClientLogger::GetDiagClientLogger().GetLogger().LogVerbose(
439  FILE_NAME, __LINE__, "",
440  [](std::stringstream &msg) { msg << "RoutingActivation channel not free"; });
441  }
442  return result;
443 }
444 
446  return (handler_impl_->GetStateContext().GetActiveState().GetState() ==
447  RoutingActivationState::kRoutingActivationSuccessful);
448 }
449 
451  uds_transport::UdsMessageConstPtr message) noexcept
455 
456  // Create header
457  TcpMessage::BufferType compose_routing_activation_req{
459  compose_routing_activation_req.reserve(kDoipheadrSize + kDoipRoutingActivationReqMinLen);
460 
461  // Add source address
462  compose_routing_activation_req.emplace_back(
463  static_cast<std::uint8_t>((message->GetSa() & 0xFF00) >> 8u));
464  compose_routing_activation_req.emplace_back(static_cast<std::uint8_t>(message->GetSa() & 0x00FF));
465  // Add activation type
466  compose_routing_activation_req.emplace_back(kDoip_RoutingActivation_ReqActType_Default);
467  // Add reservation byte , default zeroes
468  compose_routing_activation_req.emplace_back(0x00);
469  compose_routing_activation_req.emplace_back(0x00);
470  compose_routing_activation_req.emplace_back(0x00);
471  compose_routing_activation_req.emplace_back(0x00);
472 
473  TcpMessagePtr doip_routing_act_req{
474  std::make_unique<TcpMessage>(message->GetHostIpAddress(), message->GetHostPortNumber(),
475  std::move(compose_routing_activation_req))};
476  // Initiate transmission
477  if (handler_impl_->GetSocketHandler().Transmit(std::move(doip_routing_act_req))) {
479  }
480  return ret_val;
481 }
482 
483 } // namespace tcp_channel
484 } // namespace channel
485 } // 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::MessagePtr TcpMessagePtr
Type alias for Tcp message pointer.
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
Handler class to manage different socket of various client (Udp / Tcp)
void TransitionTo(EnumState state)
Definition: state.h:70
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:91
auto IsTimerActive()
Function to query if timer is running.
Definition: sync_timer.h:83
#define FILE_NAME
Definition: file_path.h:14
constexpr std::uint8_t kDoipRoutingActivationResCodeUnknownSa
Routing Activation response code values.
constexpr std::uint8_t kDoip_RoutingActivation_ReqActType_Default
Routing Activation request activation types.
std::ostream & operator<<(std::ostream &msg, RoutingActivationAckType act_type)
Function to stream the routing activation type.
constexpr std::uint32_t kDoIPRoutingActivationTimeout
The timeout value for a DoIP Routing Activation request.
auto CreateDoipGenericHeader(std::uint16_t payload_type, std::uint32_t payload_len) noexcept -> std::vector< std::uint8_t >
Function to create doip generic header.
SocketHandler< boost_support::client::tcp::TcpClient > TcpSocketHandler
Type alias of Tcp socket handler.
constexpr std::uint8_t kDoipheadrSize
constexpr std::uint8_t kDoip_ProtocolVersion
std::unique_ptr< const UdsMessage > UdsMessageConstPtr
Definition: uds_message.h:69
State
Definitions of different connection state.
Definition: tls_client.cpp:56