Skip to content

Commit

Permalink
Add Tls implementation in client & doip lib
Browse files Browse the repository at this point in the history
  • Loading branch information
Iandiehard committed Jan 6, 2024
1 parent 3fe5a76 commit e651757
Show file tree
Hide file tree
Showing 26 changed files with 664 additions and 287 deletions.
4 changes: 2 additions & 2 deletions diag-client-lib/appl/etc/diag_client_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"Network": {
"ProtocolKind": "DoIP",
"TcpIpAddress": "172.16.25.127",
"TLS": false
"TlsHandling": true
},
"ConversationName": "DiagTesterOne"
},
Expand All @@ -26,7 +26,7 @@
"Network": {
"ProtocolKind": "DoIP",
"TcpIpAddress": "172.16.25.127",
"TLS": false
"TlsHandling": false
},
"ConversationName": "DiagTesterTwo"
}
Expand Down
11 changes: 6 additions & 5 deletions diag-client-lib/appl/include/diagnostic_client_conversation.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ class DiagClientConversation final {
* @brief Definitions of Connection results
*/
enum class ConnectResult : std::uint8_t {
kConnectSuccess = 0U, /**< Successfully connected to Diagnostic Server */
kConnectFailed = 1U, /**< Connection failure to Diagnostic Server, check logs for more failure information */
kConnectTimeout = 2U /**< No Connection response received from Diagnostic Server */
kConnectSuccess = 0U, /**< Successfully connected to the Diagnostic Server */
kConnectFailed = 1U, /**< Connection failure to the Diagnostic Server, check logs for more failure information */
kConnectTimeout = 2U, /**< No Connection response received from the Diagnostic Server */
kTlsRequired = 3U /**< The Diagnostic Server only accepts secured connections, open TLS connection */
};

/**
Expand Down Expand Up @@ -91,13 +92,13 @@ class DiagClientConversation final {

/**
* @brief Function to connect to Diagnostic Server using Target address and IP address of the server
* @details This will try to initiate a TCP connection with Server and then send DoIP Routing Activation request
* @details This shall initiate a TCP connection with server and then send DoIP Routing Activation request
* @param[in] target_address
* Logical address of the Remote server
* @param[in] host_ip_addr
* IP address of the Remote server
* @return ConnectResult
* Connection result returned
* The connection result
* @implements DiagClientLib-Conversation-Connect
*/
ConnectResult ConnectToDiagServer(std::uint16_t target_address, IpAddress host_ip_addr) noexcept;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ diag::client::config_parser::DcmClientConfig ReadDcmClientConfig(boost_support::
conversation.rx_buffer_size = conversation_ptr.second.get<std::uint16_t>("RxBufferSize");
conversation.source_address = conversation_ptr.second.get<std::uint16_t>("SourceAddress");
conversation.network.tcp_ip_address = conversation_ptr.second.get<std::string>("Network.TcpIpAddress");
conversation.network.tls_handling = conversation_ptr.second.get<bool>("Network.TlsHandling");
config.conversations.emplace_back(conversation);
}
return config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace config_parser {
struct DoipNetworkType {
// local tcp address
std::string tcp_ip_address;
// tls handling (True = secured, False = unsecured)
bool tls_handling;
};

// Properties of a single conversation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace conversation_manager {
/**
* @brief Class to manage all the conversation created from usr request
*/
class ConversationManager {
class ConversationManager final {
public:
/**
* @brief Constructs an instance of ConversationManager
Expand Down
17 changes: 8 additions & 9 deletions diag-client-lib/appl/src/dcm/conversation/dm_conversation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ DmConversation::~DmConversation() = default;

void DmConversation::Startup() noexcept {
// initialize the connection
connection_ptr_->Initialize();
connection_->Initialize();
// start the connection
connection_ptr_->Start();
connection_->Start();
// Change the state to Active
activity_status_ = ActivityStatusType::kActive;
logger::DiagClientLogger::GetDiagClientLogger().GetLogger().LogInfo(__FILE__, __LINE__, __func__,
Expand All @@ -136,7 +136,7 @@ void DmConversation::Startup() noexcept {

void DmConversation::Shutdown() noexcept {
// shutdown connection
connection_ptr_->Stop();
connection_->Stop();
// Change the state to InActive
activity_status_ = ActivityStatusType::kInactive;
logger::DiagClientLogger::GetDiagClientLogger().GetLogger().LogInfo(__FILE__, __LINE__, __func__,
Expand All @@ -154,7 +154,7 @@ DiagClientConversation::ConnectResult DmConversation::ConnectToDiagServer(std::u
uds_transport::ByteVector payload{}; // empty payload
// Send Connect request to doip layer
DiagClientConversation::ConnectResult const connection_result{static_cast<DiagClientConversation::ConnectResult>(
connection_ptr_->ConnectToHost(std::make_unique<diag::client::uds_message::DmUdsMessage>(
connection_->ConnectToHost(std::make_unique<diag::client::uds_message::DmUdsMessage>(
source_address_, target_address, host_ip_addr, payload)))};
remote_address_ = host_ip_addr;
target_address_ = target_address;
Expand All @@ -181,9 +181,9 @@ DiagClientConversation::ConnectResult DmConversation::ConnectToDiagServer(std::u
DiagClientConversation::DisconnectResult DmConversation::DisconnectFromDiagServer() noexcept {
DiagClientConversation::DisconnectResult ret_val{DiagClientConversation::DisconnectResult::kDisconnectFailed};
// Check if already connected before disconnecting
if (connection_ptr_->IsConnectToHost()) {
if (connection_->IsConnectToHost()) {
// Send disconnect request to doip layer
ret_val = static_cast<DiagClientConversation::DisconnectResult>(connection_ptr_->DisconnectFromHost());
ret_val = static_cast<DiagClientConversation::DisconnectResult>(connection_->DisconnectFromHost());
if (ret_val == DiagClientConversation::DisconnectResult::kDisconnectSuccess) {
logger::DiagClientLogger::GetDiagClientLogger().GetLogger().LogInfo(
__FILE__, __LINE__, __func__, [this](std::stringstream &msg) {
Expand Down Expand Up @@ -216,7 +216,7 @@ Result<uds_message::UdsResponseMessagePtr, DiagClientConversation::DiagError> Dm
uds_transport::ByteVector payload{message->GetPayload()};
// Initiate Sending of diagnostic request
uds_transport::UdsTransportProtocolMgr::TransmissionResult const transmission_result{
connection_ptr_->Transmit(std::make_unique<diag::client::uds_message::DmUdsMessage>(
connection_->Transmit(std::make_unique<diag::client::uds_message::DmUdsMessage>(
source_address_, target_address_, message->GetHostIpAddress(), payload))};
if (transmission_result == uds_transport::UdsTransportProtocolMgr::TransmissionResult::kTransmitOk) {
// Diagnostic Request Sent successful
Expand Down Expand Up @@ -273,7 +273,6 @@ Result<uds_message::UdsResponseMessagePtr, DiagClientConversation::DiagError> Dm
<< "-> "
<< "Diagnostic Response P2 Star Timeout happened after " << p2_star_client_max_
<< " milliseconds";
;
});
result.EmplaceError(DiagClientConversation::DiagError::kDiagResponseTimeout);
conversation_state_.GetConversationStateContext().TransitionTo(ConversationState::kIdle);
Expand Down Expand Up @@ -319,7 +318,7 @@ Result<uds_message::UdsResponseMessagePtr, DiagClientConversation::DiagError> Dm
}

void DmConversation::RegisterConnection(std::unique_ptr<uds_transport::Connection> connection) noexcept {
connection_ptr_ = std::move(connection);
connection_ = std::move(connection);
}

::uds_transport::ConversionHandler &DmConversation::GetConversationHandler() noexcept {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ class DmConversation final : public Conversation {
/**
* @brief Store the underlying transport protocol connection object
*/
std::unique_ptr<::uds_transport::Connection> connection_ptr_;
std::unique_ptr<::uds_transport::Connection> connection_;

/**
* @brief Store the synchronous timer
Expand Down
5 changes: 5 additions & 0 deletions diag-client-lib/lib/boost-support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@ set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Boost 1.78.0)
find_package(OpenSSL)

file(GLOB LIBBOOST_COMMON_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp")
file(GLOB LIBBOOST_CLIENT_TCP_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/client/tcp/*.cpp")
file(GLOB LIBBOOST_SOCKET_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/socket/*.cpp")
file(GLOB LIBBOOST_SOCKET_TCP_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/socket/tcp/*.cpp")
file(GLOB LIBBOOST_SOCKET_UDP_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/socket/udp/*.cpp")
file(GLOB LIBBOOST_JSON_PARSER_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/parser/*.cpp")

set(LIBBOOST_SOCKET_SRCS
${LIBBOOST_SOCKET_SRCS}
${LIBBOOST_SOCKET_TCP_SRCS}
${LIBBOOST_SOCKET_UDP_SRCS}
)

add_library(${PROJECT_NAME}
${LIBBOOST_COMMON_SRCS}
${LIBBOOST_CLIENT_TCP_SRCS}
${LIBBOOST_SOCKET_SRCS}
${LIBBOOST_JSON_PARSER_SRCS}
)
Expand Down
223 changes: 223 additions & 0 deletions diag-client-lib/lib/boost-support/client/tcp/tcp_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/* Diagnostic Client library
* Copyright (C) 2023 Avijit Dey
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef DIAG_CLIENT_LIB_LIB_BOOST_SUPPORT_CLIENT_TCP_TCP_CLIENT_H_
#define DIAG_CLIENT_LIB_LIB_BOOST_SUPPORT_CLIENT_TCP_TCP_CLIENT_H_

#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>

#include "core/include/result.h"

namespace boost_support {
namespace client {
namespace tcp {

/**
* @brief Client class used to handle transmission and reception of tcp message from socket
* @tparam SocketType
* The type of socket to read and write from/to
*/
template<typename SocketType>
class TcpClient final {
public:
/**
* @brief Tcp error code
*/
enum class TcpErrorCode : std::uint8_t { kOpenFailed, kBindingFailed, kGenericError };

/**
* @brief Type alias for Tcp message
*/
using TcpMessage = typename SocketType::TcpMessage;

/**
* @brief Type alias for Tcp message pointer
*/
using TcpMessagePtr = typename SocketType::TcpMessagePtr;

/**
* @brief Type alias for Tcp message const pointer
*/
using TcpMessageConstPtr = typename SocketType::TcpMessageConstPtr;

/**
* @brief Tcp function template used for reception
*/
using HandlerRead = std::function<void(TcpMessagePtr)>;

public:
/**
* @brief Constructs an instance of TcpClient
* @param[in] socket
* The socket used for read and writing messages
* @param[in] handler_read
* The handler to send received data to user
*/
TcpClient(SocketType socket, HandlerRead handler_read) noexcept
: socket_{std::move(socket)},
handler_read_{std::move(handler_read)},
exit_request_{false},
running_{false},
cond_var_{},
thread_{},
mutex_{} {}

/**
* @brief Deleted copy assignment and copy constructor
*/
TcpClient(const TcpClient &other) noexcept = delete;
TcpClient &operator=(const TcpClient &other) &noexcept = delete;

/**
* @brief Deleted move assignment and move constructor
*/
TcpClient(TcpClient &&other) noexcept = delete;
TcpClient &operator=(TcpClient &&other) &noexcept = delete;

/**
* @brief Destruct an instance of TcpClientSocket
*/
~TcpClient() noexcept = default;

/**
* @brief Initialize the client
* @return Empty result on success otherwise error code
*/
void Initialize() noexcept {
// Open socket
socket_.Open();
// Start thread to receive messages
thread_ = std::thread([this]() {
std::unique_lock<std::mutex> lck(mutex_);
while (!exit_request_) {
if (!running_) {
cond_var_.wait(lck, [this]() { return exit_request_ || running_; });
}
if (!exit_request_.load()) {
if (running_) { running_ = ReadMessage(); }
}
}
});
}

/**
* @brief Function to connect to remote ip address and port number
* @param[in] host_ip_address
* The host ip address
* @param[in] host_port_num
* The host port number
* @return Empty result on success otherwise error code
*/
bool ConnectToHost(std::string_view host_ip_address, std::uint16_t host_port_num) noexcept {
return socket_.Connect(host_ip_address, host_port_num)
.AndThen([this]() noexcept {
{ // start reading
std::lock_guard<std::mutex> lock{mutex_};
running_ = true;
cond_var_.notify_all();
}
})
.HasValue();
}

/**
* @brief Function to Disconnect from host
* @return Empty result on success otherwise error code
*/
void DisconnectFromHost() noexcept {
{ // stop reading
std::lock_guard<std::mutex> lock{mutex_};
running_ = false;
}
static_cast<void>(socket_.Disconnect());
}

/**
* @brief Function to trigger transmission
* @param[in] message
* The tcp message to be transmitted
* @return Empty result on success otherwise error code
*/
bool Transmit(TcpMessageConstPtr message) noexcept { return socket_.Transmit(std::move(message)).HasValue(); }

/**
* @brief De-initialize the client
* @return Empty result on success otherwise error code
*/
void Deinitialize() noexcept {
socket_.Close();
{
std::unique_lock<std::mutex> lck(mutex_);
exit_request_ = true;
running_ = false;
}
cond_var_.notify_all();
thread_.join();
}

private:
/**
* @brief Store socket used for reading and writing tcp message
*/
SocketType socket_;

/**
* @brief Store the handler
*/
HandlerRead handler_read_;

/**
* @brief Flag to terminate the thread
*/
std::atomic_bool exit_request_;

/**
* @brief Flag to start the thread
*/
std::atomic_bool running_;

/**
* @brief Conditional variable to block the thread
*/
std::condition_variable cond_var_;

/**
* @brief Store the thread
*/
std::thread thread_;

/**
* @brief mutex to lock critical section
*/
std::mutex mutex_;

private:
/**
* @brief Function to send the received message to stored handler
* @return True if message is read successfully, otherwise False
*/
bool ReadMessage() {
bool is_message_read{false};
if (handler_read_) {
core_type::Result<TcpMessagePtr, typename SocketType::SocketError> read_result{socket_.Read()};
if (read_result.HasValue()) {
handler_read_(std::move(read_result).Value());
is_message_read = true;
}
}
return is_message_read;
}
};
} // namespace tcp
} // namespace client
} // namespace boost_support
#endif // DIAG_CLIENT_LIB_LIB_BOOST_SUPPORT_CLIENT_TCP_TCP_CLIENT_H_
Loading

0 comments on commit e651757

Please sign in to comment.