Diag-Client-Lib
vd_conversation.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 <sstream>
12 #include <string>
13 #include <utility>
14 
15 #include "src/common/logger.h"
17 
18 namespace diag {
19 namespace client {
20 namespace conversation {
21 
22 std::string ConvertToHexString(std::uint8_t char_start, std::uint8_t char_count,
23  std::vector<std::uint8_t> &input_buffer) {
24  std::string hex_string{};
25  std::uint8_t total_char_count{static_cast<uint8_t>(char_start + char_count)};
26 
27  for (std::uint8_t char_start_count = char_start; char_start_count < total_char_count; char_start_count++) {
28  std::stringstream vehicle_info_data_eid{};
29  int payload_byte{input_buffer[char_start_count]};
30  if ((payload_byte <= 15)) {
31  // "0" appended in case of value upto 15/0xF
32  vehicle_info_data_eid << "0";
33  }
34  vehicle_info_data_eid << std::hex << payload_byte << ":";
35  hex_string.append(vehicle_info_data_eid.str());
36  }
37  hex_string.pop_back(); // remove last ":" appended before
38  return hex_string;
39 }
40 
41 std::string ConvertToAsciiString(std::uint8_t char_start, std::uint8_t char_count,
42  std::vector<std::uint8_t> &input_buffer) {
43  std::string ascii_string{};
44  std::uint8_t total_char_count{static_cast<uint8_t>(char_start + char_count)};
45 
46  for (std::uint8_t char_start_count = char_start; char_start_count < total_char_count; char_start_count++) {
47  std::stringstream vehicle_info_data_vin{};
48  vehicle_info_data_vin << input_buffer[char_start_count];
49  ascii_string.append(vehicle_info_data_vin.str());
50  }
51  return ascii_string;
52 }
53 
54 void SerializeEIDGIDFromString(std::string &input_string, std::vector<uint8_t> &output_buffer, std::uint8_t total_size,
55  std::uint8_t substring_range) {
56 
57  for (auto char_count = 0U; char_count < total_size; char_count += substring_range) {
58  std::string input_string_new{input_string.substr(char_count, static_cast<std::uint8_t>(substring_range))};
59  std::stringstream input_string_stream{input_string_new};
60  int get_byte;
61  input_string_stream >> std::hex >> get_byte;
62  output_buffer.emplace_back(static_cast<std::uint8_t>(get_byte));
63  }
64 }
65 
66 void SerializeVINFromString(std::string &input_string, std::vector<uint8_t> &output_buffer, std::uint8_t total_size,
67  std::uint8_t substring_range) {
68 
69  for (auto char_count = 0U; char_count < total_size; char_count += substring_range) {
70  std::string input_string_new{input_string.substr(char_count, static_cast<std::uint8_t>(substring_range))};
71  std::stringstream input_string_stream{input_string_new};
72  int get_byte{input_string_stream.get()};
73  output_buffer.emplace_back(static_cast<std::uint8_t>(get_byte));
74  }
75 }
76 
77 // Vehicle Info Message implementation class
79  public:
81  std::map<std::uint16_t, vehicle_info::VehicleAddrInfoResponse> &vehicle_info_collection)
83  for (std::pair<std::uint16_t, vehicle_info::VehicleAddrInfoResponse> vehicle_info: vehicle_info_collection) {
84  Push(vehicle_info.second);
85  }
86  }
87 
88  ~VehicleInfoMessageImpl() override = default;
89 
91 
92  private:
93  // Function to push the vehicle address info received
94  void Push(vehicle_info::VehicleAddrInfoResponse &vehicle_addr_info_response) {
95  vehicle_info_messages_.emplace_back(vehicle_addr_info_response);
96  }
97 
98  // store the vehicle info message list
100 };
101 
106  public:
115  VdConversation &vd_conversion)
116  : ::uds_transport::ConversionHandler{handler_id},
117  vd_conversation_{vd_conversion} {}
118 
122  VdConversationHandler(const VdConversationHandler &other) noexcept = delete;
123  VdConversationHandler &operator=(const VdConversationHandler &other) noexcept = delete;
124 
128  VdConversationHandler(VdConversationHandler &&other) noexcept = delete;
130 
134  ~VdConversationHandler() override = default;
135 
161  std::pair<::uds_transport::UdsTransportProtocolMgr::IndicationResult, ::uds_transport::UdsMessagePtr> IndicateMessage(
163  ::uds_transport::UdsMessage::TargetAddressType type, ::uds_transport::ChannelID channel_id, std::size_t size,
164  ::uds_transport::Priority priority, ::uds_transport::ProtocolKind protocol_kind,
165  core_type::Span<std::uint8_t> payloadInfo) const noexcept override {
166  return (vd_conversation_.IndicateMessage(source_addr, target_addr, type, channel_id, size, priority, protocol_kind,
167  payloadInfo));
168  }
169 
176  void HandleMessage(::uds_transport::UdsMessagePtr message) const noexcept override {
177  vd_conversation_.HandleMessage(std::move(message));
178  }
179 
180  private:
185 };
186 
187 // Conversation class
188 VdConversation::VdConversation(std::string_view conversion_name, VDConversationType &conversion_identifier)
189  : vd_conversion_handler_{std::make_unique<VdConversationHandler>(conversion_identifier.handler_id, *this)},
190  conversation_name_{conversion_name},
191  broadcast_address_{conversion_identifier.udp_broadcast_address},
192  connection_ptr_{},
193  vehicle_info_collection_{},
194  vehicle_info_container_mutex_{} {}
195 
197 
198 void VdConversation::Startup() noexcept {
199  // initialize the connection
200  static_cast<void>(connection_ptr_->Initialize());
201  // start the connection
202  connection_ptr_->Start();
203 }
204 
205 void VdConversation::Shutdown() noexcept {
206  // shutdown connection
207  connection_ptr_->Stop();
208 }
209 
210 void VdConversation::RegisterConnection(std::unique_ptr<uds_transport::Connection> connection) noexcept {
211  connection_ptr_ = std::move(connection);
212 }
213 
216  vehicle_info::VehicleInfoListRequestType vehicle_info_request) noexcept {
217  using VehicleIdentificationResponseResult =
220 
221  VehicleIdentificationResponseResult result{
222  VehicleIdentificationResponseResult::FromError(DiagClient::VehicleInfoResponseError::kTransmitFailed)};
223 
224  // Deserialize first , Todo: Add optional when deserialize fails
225  std::pair<PreselectionMode, PreselectionValue> vehicle_info_request_deserialized_value{
226  DeserializeVehicleInfoRequest(vehicle_info_request)};
227 
228  if (VerifyVehicleInfoRequest(vehicle_info_request_deserialized_value.first,
229  static_cast<uint8_t>(vehicle_info_request_deserialized_value.second.size()))) {
230  if (connection_ptr_->Transmit(std::make_unique<diag::client::vd_message::VdMessage>(
231  vehicle_info_request_deserialized_value.first, vehicle_info_request_deserialized_value.second,
233  // Check if any response received
234  if (vehicle_info_collection_.empty()) {
235  // no response received
237  logger::DiagClientLogger::GetDiagClientLogger().GetLogger().LogWarn(
238  __FILE__, __LINE__, __func__, [&](std::stringstream &msg) {
239  msg << "'" << conversation_name_ << "'"
240  << "-> "
241  << "No vehicle identification response received, timed out without response";
242  });
243  } else {
244  result.EmplaceValue(std::make_unique<VehicleInfoMessageImpl>(vehicle_info_collection_));
245  // all the responses are copied, now clear the map
246  vehicle_info_collection_.clear();
247  }
248  }
249  } else {
251  }
252  return result;
253 }
254 
256 
257 std::pair<::uds_transport::UdsTransportProtocolMgr::IndicationResult, ::uds_transport::UdsMessagePtr>
259  uds_transport::UdsMessage::Address /* target_addr */,
262  core_type::Span<std::uint8_t> payload_info) noexcept {
263  using IndicationResult =
264  std::pair<::uds_transport::UdsTransportProtocolMgr::IndicationResult, ::uds_transport::UdsMessagePtr>;
266  if (!payload_info.empty()) {
268  ret_val.second = std::make_unique<diag::client::vd_message::VdMessage>();
269  ret_val.second->GetPayload().resize(size);
270  }
271  return ret_val;
272 }
273 
275  if (message != nullptr) {
276  std::lock_guard<std::mutex> const lock{vehicle_info_container_mutex_};
277  std::pair<std::uint16_t, VehicleAddrInfoResponseStruct> vehicle_info_request{
278  DeserializeVehicleInfoResponse(std::move(message))};
279 
280  vehicle_info_collection_.emplace(vehicle_info_request.first, vehicle_info_request.second);
281  }
282 }
283 
285  std::uint8_t preselection_value_length) {
286  bool is_veh_info_valid{false};
287  // 0U : No preselection
288  if (preselection_mode == 0U && (preselection_value_length == 0U)) {
289  is_veh_info_valid = true;
290  }
291  // 1U : DoIP Entities with given VIN
292  else if (preselection_mode == 1U && (preselection_value_length == 17U)) {
293  is_veh_info_valid = true;
294  }
295  // 2U : DoIP Entities with given EID
296  else if (preselection_mode == 2U && (preselection_value_length == 6U)) {
297  is_veh_info_valid = true;
298  } else {
299  // do nothing
300  }
301 
302  return is_veh_info_valid;
303 }
304 
305 std::pair<VdConversation::LogicalAddress, VdConversation::VehicleAddrInfoResponseStruct>
307  constexpr std::uint8_t start_index_vin{0U};
308  constexpr std::uint8_t total_vin_length{17U};
309  constexpr std::uint8_t start_index_eid{19U};
310  constexpr std::uint8_t start_index_gid{25U};
311  constexpr std::uint8_t total_eid_gid_length{6U};
312 
313  std::string const vehicle_info_data_vin{
314  ConvertToAsciiString(start_index_vin, total_vin_length, message->GetPayload())};
315  std::string const vehicle_info_data_eid{
316  ConvertToHexString(start_index_eid, total_eid_gid_length, message->GetPayload())};
317  std::string const vehicle_info_data_gid{
318  ConvertToHexString(start_index_gid, total_eid_gid_length, message->GetPayload())};
319 
320  LogicalAddress const logical_address{
321  (static_cast<std::uint16_t>(((message->GetPayload()[17U] & 0xFF) << 8) | (message->GetPayload()[18U] & 0xFF)))};
322 
323  // Create the structure out of the extracted string
324  VehicleAddrInfoResponseStruct const vehicle_addr_info{std::string{message->GetHostIpAddress()}, // remote ip address
325  logical_address, // logical address
326  vehicle_info_data_vin, // vin
327  vehicle_info_data_eid, // eid
328  vehicle_info_data_gid}; // gid
329 
330  return std::pair<std::uint16_t, VdConversation::VehicleAddrInfoResponseStruct>{logical_address, vehicle_addr_info};
331 }
332 
334  return *vd_conversion_handler_;
335 }
336 
337 std::pair<VdConversation::PreselectionMode, VdConversation::PreselectionValue>
339 
340  std::pair<VdConversation::PreselectionMode, VdConversation::PreselectionValue> ret_val{};
341  ret_val.first = vehicle_info_request.preselection_mode;
342 
343  if (ret_val.first == 1U) {
344  // 1U : DoIP Entities with given VIN
345  SerializeVINFromString(vehicle_info_request.preselection_value, ret_val.second,
346  static_cast<uint8_t>(vehicle_info_request.preselection_value.length()), 1U);
347  } else if (ret_val.first == 2U) {
348  // 2U : DoIP Entities with given EID
349  vehicle_info_request.preselection_value.erase(
350  remove(vehicle_info_request.preselection_value.begin(), vehicle_info_request.preselection_value.end(), ':'),
351  vehicle_info_request.preselection_value.end());
352  SerializeEIDGIDFromString(vehicle_info_request.preselection_value, ret_val.second,
353  static_cast<uint8_t>(vehicle_info_request.preselection_value.length()), 2U);
354  } else {
355  // log failure
356  }
357  return ret_val;
358 }
359 
360 } // namespace conversation
361 } // namespace client
362 } // namespace diag
Class type to contains a value (of type ValueType), or an error (of type ErrorType)
Definition: result.h:29
VehicleInfoResponseError
Definitions of Vehicle Identification response error code.
Class to manage reception from transport protocol handler to vd connection handler.
~VdConversationHandler() override=default
Destructs an instance of DmConversationHandler.
VdConversationHandler(VdConversationHandler &&other) noexcept=delete
Deleted move assignment and move constructor.
void HandleMessage(::uds_transport::UdsMessagePtr message) const noexcept override
Function to Hands over a valid received Uds message.
VdConversationHandler & operator=(const VdConversationHandler &other) noexcept=delete
VdConversation & vd_conversation_
Store the reference of vd conversation.
VdConversationHandler(::uds_transport::conversion_manager::ConversionHandlerID handler_id, VdConversation &vd_conversion)
Constructs an instance of VdConversationHandler.
VdConversationHandler(const VdConversationHandler &other) noexcept=delete
Deleted copy assignment and copy constructor.
std::pair<::uds_transport::UdsTransportProtocolMgr::IndicationResult, ::uds_transport::UdsMessagePtr > IndicateMessage(::uds_transport::UdsMessage::Address source_addr, ::uds_transport::UdsMessage::Address target_addr, ::uds_transport::UdsMessage::TargetAddressType type, ::uds_transport::ChannelID channel_id, std::size_t size, ::uds_transport::Priority priority, ::uds_transport::ProtocolKind protocol_kind, core_type::Span< std::uint8_t > payloadInfo) const noexcept override
Function to indicate a start of reception of message.
VdConversationHandler & operator=(VdConversationHandler &&other) noexcept=delete
Class to search for available diagnostic server over a network.
::uds_transport::ConversionHandler & GetConversationHandler() noexcept override
Function to get the conversation handler from conversation object.
static std::pair< PreselectionMode, PreselectionValue > DeserializeVehicleInfoRequest(vehicle_info::VehicleInfoListRequestType &vehicle_info_request)
Function to deserialize the Vehicle Information request from user.
static std::pair< LogicalAddress, VehicleAddrInfoResponseStruct > DeserializeVehicleInfoResponse(::uds_transport::UdsMessagePtr message)
Function to deserialize the received Vehicle Identification Response/ Announcement.
~VdConversation() override
Destructs an instance of DmConversation.
std::pair<::uds_transport::UdsTransportProtocolMgr::IndicationResult, ::uds_transport::UdsMessagePtr > IndicateMessage(::uds_transport::UdsMessage::Address source_addr, ::uds_transport::UdsMessage::Address target_addr, ::uds_transport::UdsMessage::TargetAddressType type, ::uds_transport::ChannelID channel_id, std::size_t size, ::uds_transport::Priority priority, ::uds_transport::ProtocolKind protocol_kind, core_type::Span< std::uint8_t > payloadInfo) noexcept override
Function to indicate a start of reception of message.
VdConversation(std::string_view conversion_name, VDConversationType &conversion_identifier)
Constructs an instance of VdConversation.
void Shutdown() noexcept override
Function to shutdown the DmConversation.
std::unique_ptr<::uds_transport::Connection > connection_ptr_
Store the underlying transport protocol connection object.
void RegisterConnection(std::unique_ptr<::uds_transport::Connection > connection) noexcept override
Function to register the conversation to underlying transport protocol handler.
std::uint16_t LogicalAddress
Type alias of logical address.
std::unique_ptr<::uds_transport::ConversionHandler > vd_conversion_handler_
Store the vd conversation handler.
void Startup() noexcept override
Function to start the DmConversation.
bool VerifyVehicleInfoRequest(PreselectionMode preselection_mode, std::uint8_t preselection_value_length)
Function to verify the received vehicle info request.
vehicle_info::VehicleInfoMessageResponseUniquePtr GetDiagnosticServerList()
Function to get the list of available diagnostic server.
void HandleMessage(::uds_transport::UdsMessagePtr message) noexcept override
Function to Hands over a valid received Uds message.
core_type::Result< diag::client::vehicle_info::VehicleInfoMessageResponseUniquePtr, DiagClient::VehicleInfoResponseError > SendVehicleIdentificationRequest(vehicle_info::VehicleInfoListRequestType vehicle_info_request) noexcept override
Function to send vehicle identification request and get the Diagnostic Server list.
std::uint8_t PreselectionMode
Type alias of pre-selection mode.
void Push(vehicle_info::VehicleAddrInfoResponse &vehicle_addr_info_response)
VehicleInfoListResponseType & GetVehicleList() override
Function to get the list of vehicle available in the network.
VehicleInfoMessageImpl(std::map< std::uint16_t, vehicle_info::VehicleAddrInfoResponse > &vehicle_info_collection)
static auto GetDiagClientLogger() noexcept -> DiagClientLogger &
Get the diag client logger instance.
Definition: logger.h:32
Class provide storage of list of all available vehicle entity.
std::vector< VehicleAddrInfoResponse > VehicleInfoListResponseType
Alias to collection of Vehicle info response.
Class to manage reception from transport protocol handler to connection handler.
ConversionHandler(conversion_manager::ConversionHandlerID handler_id)
Constructs an instance of ConversionHandler.
void SerializeVINFromString(std::string &input_string, std::vector< uint8_t > &output_buffer, std::uint8_t total_size, std::uint8_t substring_range)
void SerializeEIDGIDFromString(std::string &input_string, std::vector< uint8_t > &output_buffer, std::uint8_t total_size, std::uint8_t substring_range)
std::string ConvertToAsciiString(std::uint8_t char_start, std::uint8_t char_count, std::vector< std::uint8_t > &input_buffer)
std::string ConvertToHexString(std::uint8_t char_start, std::uint8_t char_count, std::vector< std::uint8_t > &input_buffer)
std::unique_ptr< VehicleInfoMessage > VehicleInfoMessageResponseUniquePtr
The unique_ptr for Vehicle Identification Response Message.
std::string_view ProtocolKind
std::unique_ptr< UdsMessage > UdsMessagePtr
Definition: uds_message.h:71
uint32_t ChannelID
std::uint8_t Priority
Structure containing VD conversation type.
std::uint8_t preselection_mode
Mode to be used during sending of Vehicle Identification request. 0U : No preselection 1U : DoIP Enti...
std::string preselection_value
Value to be used based on preselection mode. VIN when preselection_mode = 1U EID when preselection_mo...
Structure containing available Vehicle Address Information.