$darkmode
socket.hpp
1 #pragma once
2 
3 #include <memory>
4 #include <vector>
5 
6 #include <iostream>
7 #if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1800
8 #else
9 #define ASIO_HAS_BOOST_DATE_TIME
10 #define LRDB_USE_BOOST_ASIO
11 #endif
12 
13 #ifdef LRDB_USE_BOOST_ASIO
14 #include <boost/asio.hpp>
15 #else
16 #define ASIO_STANDALONE
17 #include <asio.hpp>
18 #endif
19 
20 namespace lrdb {
21 #ifdef LRDB_USE_BOOST_ASIO
22 namespace asio {
23 using boost::system::error_code;
24 using namespace boost::asio;
25 }
26 #else
27 #endif
28 
29 // one to one server socket
31  public:
32  command_stream_socket(uint16_t port = 21110)
33  : endpoint_(asio::ip::tcp::v4(), port),
34  acceptor_(io_service_, endpoint_),
35  socket_(io_service_) {
36  async_accept();
37  }
38 
40  close();
41  acceptor_.close();
42  }
43 
44  void close() {
45  socket_.close();
46  if (on_close) {
47  on_close();
48  }
49  }
50  void reconnect() {
51  close();
52  async_accept();
53  }
54 
55  std::function<void(const std::string& data)> on_data;
56  std::function<void()> on_connection;
57  std::function<void()> on_close;
58  std::function<void(const std::string&)> on_error;
59 
60  bool is_open() const { return socket_.is_open(); }
61  void poll() { io_service_.poll(); }
62  void run_one() { io_service_.run_one(); }
63  void wait_for_connection() {
64  while (!is_open()) {
65  io_service_.run_one();
66  }
67  }
68 
69  // sync
70  bool send_message(const std::string& message) {
71  asio::error_code ec;
72  std::string data = message + "\r\n";
73  asio::write(socket_, asio::buffer(data), ec);
74  if (ec) {
75  if (on_error) {
76  on_error(ec.message());
77  }
78  reconnect();
79  return false;
80  }
81  return true;
82  }
83 
84  private:
85  void async_accept() {
86  acceptor_.async_accept(socket_, [&](const asio::error_code& ec) {
87  if (!ec) {
88  connected_done();
89  } else {
90  if (on_error) {
91  on_error(ec.message());
92  }
93  reconnect();
94  }
95  });
96  }
97  void connected_done() {
98  if (on_connection) {
99  on_connection();
100  }
101  start_receive_commands();
102  }
103  void start_receive_commands() {
104  asio::async_read_until(socket_, read_buffer_, "\n",
105  [&](const asio::error_code& ec, std::size_t) {
106  if (!ec) {
107  std::istream is(&read_buffer_);
108  std::string command;
109  std::getline(is, command);
110  if (on_data) {
111  on_data(command);
112  }
113  start_receive_commands();
114  } else {
115  if (on_error) {
116  on_error(ec.message());
117  }
118  reconnect();
119  }
120  });
121  }
122 
123  asio::io_service io_service_;
124  asio::ip::tcp::endpoint endpoint_;
125  asio::ip::tcp::acceptor acceptor_;
126  asio::ip::tcp::socket socket_;
127  asio::streambuf read_buffer_;
128 };
129 }
Definition: socket.hpp:30