Diag-Client-Lib
tcp_server.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 */
9 
10 #include "common/logger.h"
11 
12 namespace boost_support {
13 namespace socket {
14 namespace tcp {
15 
16 using TcpIpAddress = boost::asio::ip::address;
17 using TcpErrorCodeType = boost::system::error_code;
18 
19 CreateTcpServerSocket::CreateTcpServerSocket(std::string_view local_ip_address, uint16_t local_port_num)
20  : local_ip_address_{local_ip_address},
21  local_port_num_{local_port_num} {
22  // Create accepter
23  tcp_accepter_ = std::make_unique<TcpAccepter>(io_context_, Tcp::endpoint(Tcp::v4(), local_port_num_), true);
25  __FILE__, __LINE__, __func__, [&local_ip_address, &local_port_num](std::stringstream &msg) {
26  msg << "Tcp Socket Accepter created at "
27  << "<" << local_ip_address << "," << local_port_num << ">";
28  });
29 }
30 
32  TcpHandlerRead &&tcp_handler_read) {
34  Tcp::endpoint endpoint{};
35  CreateTcpServerSocket::TcpServerConnection tcp_connection{io_context_, std::move(tcp_handler_read)};
36 
37  // blocking accept
38  static_cast<void>(tcp_accepter_->accept(tcp_connection.GetSocket(), endpoint, ec));
39  if (ec.value() == boost::system::errc::success) {
41  __FILE__, __LINE__, __func__, [endpoint](std::stringstream &msg) {
42  msg << "Tcp Socket connection received from client "
43  << "<" << endpoint.address().to_string() << "," << endpoint.port() << ">";
44  });
45  } else {
47  __FILE__, __LINE__, __func__,
48  [ec](std::stringstream &msg) { msg << "Tcp Socket Connect to client failed with error: " << ec.message(); });
49  }
50  return tcp_connection;
51 }
52 
54  TcpHandlerRead &&tcp_handler_read)
55  : tcp_socket_{io_context},
56  tcp_handler_read_{tcp_handler_read} {}
57 
59 
61  TcpErrorCodeType ec{};
62  bool ret_val{false};
63  boost::asio::write(
64  tcp_socket_,
65  boost::asio::buffer(tcp_tx_message->GetTxBuffer(), std::size_t(tcp_tx_message->GetTxBuffer().size())), ec);
66  // Check for error
67  if (ec.value() == boost::system::errc::success) {
68  Tcp::endpoint endpoint_{tcp_socket_.remote_endpoint()};
70  __FILE__, __LINE__, __func__, [endpoint_](std::stringstream &msg) {
71  msg << "Tcp message sent to "
72  << "<" << endpoint_.address().to_string() << "," << endpoint_.port() << ">";
73  });
74  ret_val = true;
75  } else {
77  __FILE__, __LINE__, __func__,
78  [ec](std::stringstream &msg) { msg << "Tcp message sending failed with error: " << ec.message(); });
79  }
80  return ret_val;
81 }
82 
85  bool connection_closed{false};
86 
87  // create and reserve the buffer
88  TcpMessage::BufferType rx_buffer{};
89  rx_buffer.resize(kDoipheadrSize);
90  // start blocking read to read Header first
91  boost::asio::read(tcp_socket_, boost::asio::buffer(&rx_buffer[0], kDoipheadrSize), ec);
92  // Check for error
93  if (ec.value() == boost::system::errc::success) {
94  // read the next bytes to read
95  std::uint32_t const read_next_bytes = [&rx_buffer]() noexcept -> std::uint32_t {
96  return static_cast<std::uint32_t>((static_cast<std::uint32_t>(rx_buffer[4u] << 24u) & 0xFF000000) |
97  (static_cast<std::uint32_t>(rx_buffer[5u] << 16u) & 0x00FF0000) |
98  (static_cast<std::uint32_t>(rx_buffer[6u] << 8u) & 0x0000FF00) |
99  (static_cast<std::uint32_t>(rx_buffer[7u] & 0x000000FF)));
100  }();
101  // reserve the buffer
102  rx_buffer.resize(kDoipheadrSize + std::size_t(read_next_bytes));
103  boost::asio::read(tcp_socket_, boost::asio::buffer(&rx_buffer[kDoipheadrSize], read_next_bytes), ec);
104 
105  // all message received, transfer to upper layer
106  Tcp::endpoint endpoint_{tcp_socket_.remote_endpoint()};
107  TcpMessagePtr tcp_rx_message{
108  std::make_unique<TcpMessage>(endpoint_.address().to_string(), endpoint_.port(), std::move(rx_buffer))};
110  __FILE__, __LINE__, __func__, [endpoint_](std::stringstream &msg) {
111  msg << "Tcp Message received from "
112  << "<" << endpoint_.address().to_string() << "," << endpoint_.port() << ">";
113  });
114  // send data to upper layer
115  tcp_handler_read_(std::move(tcp_rx_message));
116  } else if (ec.value() == boost::asio::error::eof) {
118  __FILE__, __LINE__, __func__,
119  [ec](std::stringstream &msg) { msg << "Remote Disconnected with: " << ec.message(); });
120  connection_closed = true;
121  } else {
123  __FILE__, __LINE__, __func__,
124  [ec](std::stringstream &msg) { msg << "Remote Disconnected with undefined error: " << ec.message(); });
125  connection_closed = true;
126  }
127  return connection_closed;
128 }
129 
131  TcpErrorCodeType ec{};
132  bool ret_val{false};
133  // Graceful shutdown
134  if (tcp_socket_.is_open()) {
135  tcp_socket_.shutdown(TcpSocket::shutdown_both, ec);
136  if (ec.value() == boost::system::errc::success) {
137  ret_val = true;
138  } else {
140  __FILE__, __LINE__, __func__,
141  [ec](std::stringstream &msg) { msg << "Tcp Socket Disconnection failed with error: " << ec.message(); });
142  }
143  tcp_socket_.close();
144  }
145  return ret_val;
146 }
147 
148 } // namespace tcp
149 } // namespace socket
150 } // namespace boost_support
static auto GetLibBoostLogger() noexcept -> LibBoostLogger &
Definition: logger.h:20
TcpServerConnection(boost::asio::io_context &io_context, TcpHandlerRead &&tcp_handler_read)
Definition: tcp_server.cpp:53
std::unique_ptr< TcpAccepter > tcp_accepter_
Definition: tcp_server.h:88
CreateTcpServerSocket(std::string_view local_ip_address, uint16_t local_port_num)
Definition: tcp_server.cpp:19
std::function< void(TcpMessagePtr)> TcpHandlerRead
Definition: tcp_server.h:28
TcpServerConnection GetTcpServerConnection(TcpHandlerRead &&tcp_handler_read)
Definition: tcp_server.cpp:31
std::vector< uint8_t > BufferType
Type alias for underlying buffer.
Definition: tcp_message.h:48
std::unique_ptr< const TcpMessage > TcpMessageConstPtr
The unique pointer to const TcpMessage.
Definition: tcp_message.h:172
boost::asio::ip::address TcpIpAddress
Definition: tcp_server.cpp:16
boost::system::error_code TcpErrorCodeType
Definition: tcp_server.cpp:17
constexpr std::uint8_t kDoipheadrSize
Doip HeaderSize.
Definition: tcp_message.h:182
std::unique_ptr< TcpMessage > TcpMessagePtr
The unique pointer to TcpMessage.
Definition: tcp_message.h:177