JSON-RPC 2.0
JSON-RPC 2.0 Modern C++ Library
Loading...
Searching...
No Matches
socket_transport.cpp
Go to the documentation of this file.
2
3#include <stdexcept>
4
5#include <spdlog/spdlog.h>
6
7namespace jsonrpc::transport {
8
10 const std::string &host, uint16_t port, bool is_server)
11 : socket_(io_context_), host_(host), port_(port), is_server_(is_server) {
12 spdlog::info(
13 "Initializing SocketTransport with host: {} and port: {}", host, port);
14
15 if (is_server_) {
16 BindAndListen();
17 } else {
18 Connect();
19 }
20}
21
22auto SocketTransport::GetSocket() -> asio::ip::tcp::socket & {
23 return socket_;
24}
25
27 spdlog::info("Closing socket and shutting down SocketTransport.");
28 std::error_code ec;
29 socket_.close(ec);
30 if (ec) {
31 spdlog::warn("Socket close error: {}", ec.message());
32 }
33 io_context_.stop();
34}
35
36void SocketTransport::Connect() {
37 asio::ip::tcp::resolver resolver(io_context_);
38 auto endpoints = resolver.resolve(host_, std::to_string(port_));
39
40 asio::steady_timer timer(io_context_);
41 timer.expires_after(std::chrono::seconds(3));
42
43 std::error_code connect_error;
44 asio::async_connect(
45 socket_, endpoints,
46 [&](const asio::error_code &error, const asio::ip::tcp::endpoint &) {
47 if (!error) {
48 timer.cancel();
49 } else {
50 connect_error = error;
51 }
52 });
53
54 timer.async_wait([&](const asio::error_code &error) {
55 if (!error) {
56 connect_error = asio::error::timed_out;
57 socket_.close();
58 }
59 });
60
61 io_context_.run();
62
63 if (connect_error) {
64 spdlog::error(
65 "Error connecting to {}:{}. Error: {}", host_, port_,
66 connect_error.message());
67 throw std::runtime_error("Error connecting to socket");
68 }
69}
70
71void SocketTransport::BindAndListen() {
72 try {
73 asio::ip::tcp::acceptor acceptor(
74 io_context_, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port_));
75 acceptor.listen();
76 spdlog::info("Listening on {}:{}", host_, port_);
77 acceptor.accept(socket_);
78 spdlog::info("Accepted connection on {}:{}", host_, port_);
79 } catch (const std::exception &e) {
80 spdlog::error(
81 "Error binding/listening on {}:{}. Error: {}", host_, port_, e.what());
82 throw std::runtime_error("Error binding/listening on socket");
83 }
84}
85
86void SocketTransport::SendMessage(const std::string &message) {
87 try {
88 asio::write(socket_, asio::buffer(message + "\n"));
89 spdlog::debug("Sent message: {}", message);
90 } catch (const std::exception &e) {
91 spdlog::error("Error sending message: {}", e.what());
92 throw std::runtime_error("Error sending message");
93 }
94}
95
96auto SocketTransport::ReceiveMessage() -> std::string {
97 try {
98 asio::streambuf buffer;
99 asio::read_until(socket_, buffer, '\n');
100 std::istream is(&buffer);
101 std::string message;
102 std::getline(is, message);
103 spdlog::debug("Received message: {}", message);
104 return message;
105 } catch (const std::exception &e) {
106 spdlog::error("Error receiving message: {}", e.what());
107 socket_.close();
108 return "";
109 }
110}
111
112} // namespace jsonrpc::transport
auto GetSocket() -> asio::ip::tcp::socket &
void SendMessage(const std::string &message) override
Sends a message in string to the transport layer.
SocketTransport(const std::string &host, uint16_t port, bool is_server)
Constructs a SocketTransport.
auto ReceiveMessage() -> std::string override
Receives a message from the transport layer.