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