The Battle for Wesnoth  1.15.12+dev
wesnothd_connection.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2018 by Sergey Popov <loonycyborg@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #ifdef _WIN32
18 
19 #ifdef INADDR_ANY
20 #undef INADDR_ANY
21 #endif
22 
23 #ifdef INADDR_BROADCAST
24 #undef INADDR_BROADCAST
25 #endif
26 
27 #ifdef INADDR_NONE
28 #undef INADDR_NONE
29 #endif
30 
31 #endif // endif _WIN32
32 
33 #include "configr_assign.hpp"
35 
36 #if BOOST_VERSION >= 106600
37 #include <boost/asio/io_context.hpp>
38 #else
39 #include <boost/asio/io_service.hpp>
40 #endif
41 #include <boost/asio/ip/tcp.hpp>
42 #include <boost/asio/streambuf.hpp>
43 
44 #include <condition_variable>
45 #include <deque>
46 #include <future>
47 #include <list>
48 #include <mutex>
49 #include <queue>
50 #include <thread>
51 
52 class config;
53 
54 union data_union {
55  char binary[4];
56  uint32_t num;
57 };
58 
59 /** A class that represents a TCP/IP connection to the wesnothd server. */
61 {
62 public:
64 
66  wesnothd_connection& operator=(const wesnothd_connection&) = delete;
67 
69 
70  /**
71  * Constructor.
72  *
73  * @param host Name of the host to connect to
74  * @param service Service identifier such as "80" or "http"
75  */
76  wesnothd_connection(const std::string& host, const std::string& service);
77 
78  /**
79  * Queues the given data to be sent to the server.
80  *
81  * @param request The data to send
82  */
83  void send_data(const configr_of& request);
84 
85  /**
86  * Receives the next pending data pack from the server, if available.
87  *
88  * @param result The object to which the received data will be written.
89  * @returns True if any data was available, false otherwise.
90  */
91  bool receive_data(config& result);
92 
93  /**
94  * Unlike @ref receive_data, waits until data is available instead of returning immediately.
95  *
96  * @param data Config object passed to @ref receive_data
97  * @returns True, since data will always be available.
98  */
99  bool wait_and_receive_data(config& data);
100 
101  /** Waits until the server handshake is complete. */
102  void wait_for_handshake();
103 
104  void cancel();
105 
106  void stop();
107 
108  std::size_t bytes_to_write() const
109  {
110  return bytes_to_write_;
111  }
112 
113  std::size_t bytes_written() const
114  {
115  return bytes_written_;
116  }
117 
118  std::size_t bytes_to_read() const
119  {
120  return bytes_to_read_;
121  }
122 
123  std::size_t bytes_read() const
124  {
125  return bytes_read_;
126  }
127 
128  bool has_data_received() const
129  {
130  return !recv_queue_.empty();
131  }
132 
133  bool is_sending_data() const
134  {
135  return !send_queue_.empty();
136  }
137 
138 private:
139  std::thread worker_thread_;
140 
141 #if BOOST_VERSION >= 106600
142  boost::asio::io_context io_context_;
143 #else
144  boost::asio::io_service io_context_;
145 #endif
146 
147  typedef boost::asio::ip::tcp::resolver resolver;
148  resolver resolver_;
149 
150  typedef boost::asio::ip::tcp::socket socket;
151  socket socket_;
152 
153  boost::system::error_code last_error_;
154 
155  std::mutex last_error_mutex_;
156 
157  std::promise<void> handshake_finished_;
158 
159  boost::asio::streambuf read_buf_;
160 
161 #if BOOST_VERSION >= 106600
162  using results_type = resolver::results_type;
163  using endpoint = const boost::asio::ip::tcp::endpoint&;
164 #else
167 #endif
168 
169  void handle_resolve(const boost::system::error_code& ec, results_type results);
170  void handle_connect(const boost::system::error_code& ec, endpoint endpoint);
171 
172  void handshake();
173  void handle_handshake(const boost::system::error_code& ec);
174 
176 
177  std::size_t is_write_complete(const boost::system::error_code& error, std::size_t bytes_transferred);
178  void handle_write(const boost::system::error_code& ec, std::size_t bytes_transferred);
179 
180  std::size_t is_read_complete(const boost::system::error_code& error, std::size_t bytes_transferred);
181  void handle_read(const boost::system::error_code& ec, std::size_t bytes_transferred);
182 
183  void send();
184  void recv();
185 
186  template<typename T>
187  using data_queue = std::queue<T, std::list<T>>;
188 
189 #if BOOST_VERSION >= 106600
191 #else
193 #endif
195 
196  std::mutex recv_queue_mutex_;
197 
198  std::condition_variable recv_queue_lock_;
199 
200  uint32_t payload_size_;
201 
202  // TODO: do i need to guard the following 4 values with a mutex?
203  std::size_t bytes_to_write_;
204  std::size_t bytes_written_;
205  std::size_t bytes_to_read_;
206  std::size_t bytes_read_;
207 };
An error occurred inside the underlying network communication code (boost asio) TODO: find a short na...
resolver::iterator endpoint
std::condition_variable recv_queue_lock_
std::promise< void > handshake_finished_
std::size_t bytes_to_write() const
boost::asio::ip::tcp::socket socket
resolver::iterator results_type
data_queue< std::shared_ptr< boost::asio::streambuf > > send_queue_
std::queue< T, std::list< T > > data_queue
A class that represents a TCP/IP connection to the wesnothd server.
std::size_t bytes_read() const
void send(const std::string &, const std::string &, type)
Displays a desktop notification message, from owner, of type t.
boost::asio::streambuf read_buf_
boost::system::error_code last_error_
boost::asio::io_service io_context_
std::size_t bytes_to_read() const
std::size_t bytes_written() const
boost::asio::ip::tcp::resolver resolver
data_queue< config > recv_queue_
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
std::string::const_iterator iterator
Definition: tokenizer.hpp:24