Guest User

NetworkClient

a guest
Sep 25th, 2019
240
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class NetworkClient
  2. {
  3. public:
  4.     NetworkClient(const std::string &host, const std::string &port);
  5.     NetworkClient(const NetworkClient&) = delete;
  6.     NetworkClient& operator=(const NetworkClient&) = delete;
  7.     ~NetworkClient();
  8.  
  9.     void connect();
  10.     void disconnect();
  11.  
  12.     int write(const uint8_t *buffer, std::size_t size);
  13.     int write(const std::string &buffer);
  14.  
  15.     int wait(std::chrono::steady_clock::duration timeout);
  16.     int available();
  17.     int read_some(uint8_t *buffer, std::size_t size);
  18.     int read_some_wait(uint8_t *buffer, std::size_t size);
  19.     int read_exactly(uint8_t *buffer, std::size_t size, std::chrono::steady_clock::duration timeout);
  20.     int read_until(std::string &buffer, char delim, std::chrono::steady_clock::duration timeout);
  21.  
  22.     operator bool() const { return connected; }
  23.     bool is_connected() const { return connected; }
  24.  
  25.     std::string get_host() const { return host; }
  26.     std::string get_port() const { return port; }
  27.  
  28. protected:
  29.     bool connected = false;
  30.     std::string host;
  31.     std::string port;
  32.  
  33.     std::shared_ptr<boost::asio::io_context> io_context;
  34.     std::unique_ptr<boost::asio::ip::tcp::resolver> resolver;
  35.     std::unique_ptr<boost::asio::ip::tcp::socket> socket;
  36.  
  37.     bool run_for(std::chrono::steady_clock::duration timeout); /// Run operation with timeout
  38.     bool run_until(const std::chrono::steady_clock::time_point &timepoint); /// Run operation until timepoint
  39. };
  40.  
  41. NetworkClient::NetworkClient(const std::string &host, const std::string &port): host(host), port(port)
  42. {
  43.     connect();
  44. }
  45.  
  46. NetworkClient::~NetworkClient()
  47. {
  48.     if (connected) {
  49.         disconnect();
  50.     }
  51. }
  52.  
  53. void NetworkClient::connect()
  54. {
  55.     io_context = std::make_shared<boost::asio::io_context>();
  56.     resolver = std::make_unique<boost::asio::ip::tcp::resolver>(*io_context);
  57.     socket = std::make_unique<boost::asio::ip::tcp::socket>(*io_context);
  58.     boost::system::error_code ec;
  59.     boost::asio::connect(*socket, resolver->resolve(host, port, ec), ec);
  60.     if (ec)
  61.         connected = false;
  62.     else
  63.         connected = true;
  64. }
  65.  
  66. void NetworkClient::disconnect()
  67. {
  68.     boost::system::error_code ec;
  69.     socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
  70.     socket->close(ec);
  71.     io_context->stop();
  72.     connected = false;
  73. }
  74.  
  75. int NetworkClient::write(const uint8_t *buffer, std::size_t size)
  76. {
  77.     boost::system::error_code ec;
  78.     size_t length = boost::asio::write(*socket, boost::asio::buffer(buffer, size), ec);
  79.     if (ec)
  80.         return -1;
  81.     return length;
  82. }
  83.  
  84. int NetworkClient::write(const std::string &buffer)
  85. {
  86.     return write(reinterpret_cast<const uint8_t *>(buffer.c_str()), buffer.size() + 1);
  87. }
  88.  
  89. int NetworkClient::wait(std::chrono::steady_clock::duration timeout)
  90. {
  91.     boost::system::error_code ec;
  92.     socket->async_wait(boost::asio::ip::tcp::socket::wait_read,
  93.                        [&](const boost::system::error_code& result_error)
  94.                        {
  95.                            ec = result_error;
  96.                        });
  97.     bool timedout = run_for(timeout);
  98.     if (ec || timedout)
  99.         return -1;
  100.     return 0;
  101. }
  102.  
  103. int NetworkClient::available()
  104. {
  105.     boost::system::error_code ec;
  106.     std::size_t available = socket->available(ec);
  107.     if (ec)
  108.         return -1;
  109.     return available;
  110. }
  111.  
  112. int NetworkClient::read_some(uint8_t *buffer, std::size_t size)
  113. {
  114.     boost::system::error_code ec;
  115.     std::size_t available = socket->available(ec);
  116.     if (ec)
  117.         return -1;
  118.  
  119.     if (available > 0) {
  120.         if (available > size)
  121.             available = size;
  122.         std::size_t length = boost::asio::read(*socket, boost::asio::buffer(buffer, available), ec);
  123.         if (ec)
  124.             return -1;
  125.         return length;
  126.     }
  127.     return 0;
  128. }
  129.  
  130. int NetworkClient::read_some_wait(uint8_t *buffer, std::size_t size)
  131. {
  132.     boost::system::error_code ec;
  133.  
  134.     std::size_t length = socket->read_some(boost::asio::buffer(buffer, size), ec);
  135.     if (ec)
  136.         return -1;
  137.     return length;
  138. }
  139.  
  140. int NetworkClient::read_exactly(uint8_t *buffer, std::size_t size, std::chrono::steady_clock::duration timeout)
  141. {
  142.     boost::system::error_code ec;
  143.     std::size_t n = 0;
  144.     boost::asio::async_read(*socket, boost::asio::buffer(buffer, size),
  145.                             [&](const boost::system::error_code& result_error, std::size_t result_n)
  146.                             {
  147.                                 ec = result_error;
  148.                                 n = result_n;
  149.                             });
  150.  
  151.     bool timedout = run_for(timeout);
  152.  
  153.     if (!timedout && ec)
  154.         return -1;
  155.     return n;
  156. }
  157.  
  158. int NetworkClient::read_until(std::string &buffer, char delim, std::chrono::steady_clock::duration timeout)
  159. {
  160.     boost::system::error_code ec;
  161.     std::size_t n = 0;
  162.     boost::asio::async_read_until(*socket, boost::asio::dynamic_buffer(buffer), delim,
  163.                                   [&](const boost::system::error_code& result_error, std::size_t result_n)
  164.                                   {
  165.                                       ec = result_error;
  166.                                       n = result_n;
  167.                                   });
  168.  
  169.     bool timedout = run_for(timeout);
  170.  
  171.     if (!timedout && ec)
  172.         return -1;
  173.     return n;
  174. }
  175.  
  176. bool NetworkClient::run_for(std::chrono::steady_clock::duration timeout)
  177. {
  178.     io_context->restart();
  179.     io_context->run_for(timeout);
  180.  
  181.     if (!io_context->stopped()) {
  182.         socket->cancel(); // close()
  183.         io_context->run();
  184.         return true;
  185.     }
  186.  
  187.     return false;
  188. }
  189.  
  190. bool NetworkClient::run_until(const std::chrono::steady_clock::time_point &timepoint)
  191. {
  192.     io_context->restart();
  193.     io_context->run_until(timepoint);
  194.  
  195.     if (!io_context->stopped()) {
  196.         socket->cancel();
  197.         io_context->run();
  198.         return true;
  199.     }
  200.  
  201.     return false;
  202. }
RAW Paste Data