Started working on the new asio based network subsystem.

This commit is contained in:
Sergey Popov 2011-06-18 23:10:55 +00:00
parent d78714487c
commit 301427f778
9 changed files with 172 additions and 12 deletions

View file

@ -282,6 +282,15 @@ if env["prereqs"]:
conf.CheckLib("m")
conf.CheckFunc("round")
def CheckAsio(conf, do_check):
if not do_check:
return True
if env["PLATFORM"] == 'win32':
conf.env.Append(LIBS = ["libws2_32"])
return conf.CheckBoost("system") and \
conf.CheckBoost("thread") and \
conf.CheckBoost("asio", header_only = True)
have_server_prereqs = \
conf.CheckCPlusPlus(gcc_version = "3.3") and \
conf.CheckGettextLibintl() and \
@ -289,19 +298,14 @@ if env["prereqs"]:
conf.CheckBoostIostreamsGZip() and \
conf.CheckBoost("smart_ptr", header_only = True) and \
conf.CheckSDL(require_version = '1.2.7') and \
conf.CheckSDL('SDL_net') or Warning("Base prerequisites are not met.")
if have_server_prereqs and env["use_network_ana"]:
if env["PLATFORM"] == 'win32':
env.Append(LIBS = ["libws2_32"])
have_server_prereqs = \
conf.CheckBoost("system") and \
conf.CheckBoost("thread") and \
conf.CheckBoost("asio", header_only = True) or Warning("Base prerequisites are not met.")
conf.CheckSDL('SDL_net') and \
CheckAsio(conf, env["use_network_ana"]) or Warning("Base prerequisites are not met.")
env = conf.Finish()
client_env = env.Clone()
conf = client_env.Configure(**configure_args)
have_client_prereqs = have_server_prereqs and \
CheckAsio(conf, not env["use_network_ana"]) and \
conf.CheckPango("cairo") and \
conf.CheckPKG("fontconfig") and \
conf.CheckBoost("program_options", require_version="1.35.0") and \

View file

@ -5,6 +5,10 @@ Version 1.9.7+svn:
* Moved Reverse Time Graphics display option to Advanced Preferences
* Moved Scroll Tracking of Unit Actions display option to Advanced
Preferences, renamed to Follow Unit Actions
* Miscellaneous and bug fixes:
* Started working on the new asio based network subsystem. boost.asio
(along with boost.thread and boost.system) is now a dependency for
the client no matter whether ANA is enabled.
Version 1.9.7:
* Graphics:

View file

@ -524,6 +524,7 @@ set(wesnoth-main_SRC
multiplayer_lobby.cpp
multiplayer_ui.cpp
multiplayer_wait.cpp
network_asio.cpp
pathfind/pathfind.cpp
pathfind/teleport.cpp
persist_context.cpp

View file

@ -381,6 +381,7 @@ wesnoth_sources = Split("""
multiplayer_lobby.cpp
multiplayer_ui.cpp
multiplayer_wait.cpp
network_asio.cpp
pathfind/pathfind.cpp
pathfind/teleport.cpp
persist_context.cpp

View file

@ -1125,8 +1125,11 @@ namespace {
try {
if(gui2::new_widgets) {
gui2::tnetwork_transmission network_receive("WIP network transmission dialog");
network_receive.show(disp.video());
network_asio::connection connection(remote_host, lexical_cast<std::string>(remote_port));
gui2::tnetwork_transmission network_connect(connection, "WIP network transmission dialog");
bool result = network_connect.show(disp.video());
if(!result)
return;
}
const network::manager net_manager;
const network::connection sock =
@ -1363,6 +1366,9 @@ namespace {
} catch(network::error& e) {
ERR_NET << "network::error thrown during transaction with add-on server; \""<< e.message << "\"\n";
gui2::show_error_message(disp.video(), _("Remote host disconnected."));
} catch(const network_asio::error& e) {
ERR_NET << "network_asio::error thrown during transaction with add-on server; \""<< e.what() << "\"\n";
gui2::show_error_message(disp.video(), _("Remote host disconnected."));
} catch(io_exception& e) {
ERR_FS << "io_exception thrown while installing an addon; \"" << e.what() << "\"\n";
gui2::show_error_message(disp.video(), _("A problem occurred when trying to create the files necessary to install this add-on."));

View file

@ -30,6 +30,14 @@ namespace gui2 {
REGISTER_DIALOG(network_transmission)
void tnetwork_transmission::pump_monitor::process(events::pump_info&)
{
connection_.poll();
if(connection_.connected() && window_) {
window_.get().set_retval(twindow::OK);
}
}
void tnetwork_transmission::pre_show(CVideo& /*video*/, twindow& window)
{
// ***** ***** ***** ***** Set up the widgets ***** ***** ***** *****
@ -37,10 +45,13 @@ void tnetwork_transmission::pre_show(CVideo& /*video*/, twindow& window)
find_widget<tlabel>(&window, "title", false).set_label(title_);
}
pump_monitor.window_ = window;
}
void tnetwork_transmission::post_show(twindow& /*window*/)
{
pump_monitor.window_.reset();
}
} // namespace gui2

View file

@ -18,6 +18,8 @@
#include "gui/dialogs/dialog.hpp"
#include "gui/widgets/control.hpp"
#include "network_asio.hpp"
#include <boost/optional.hpp>
namespace gui2 {
@ -31,9 +33,20 @@ class tnetwork_transmission;
*/
class tnetwork_transmission : public tdialog
{
network_asio::connection& connection_;
class pump_monitor : public events::pump_monitor
{
network_asio::connection& connection_;
virtual void process(events::pump_info&);
public:
pump_monitor(network_asio::connection& connection) : connection_(connection) {}
boost::optional<twindow&> window_;
} pump_monitor;
public:
tnetwork_transmission(const std::string& title)
: title_(title)
tnetwork_transmission(network_asio::connection& connection, const std::string& title)
: connection_(connection), pump_monitor(connection), title_(title)
{}
protected:

52
src/network_asio.cpp Normal file
View file

@ -0,0 +1,52 @@
#include "network_asio.hpp"
#include <boost/bind.hpp>
#include <iostream>
namespace network_asio {
connection::connection(const std::string& host, const std::string& service) :
resolver_(io_service_), socket_(io_service_), connected_(false)
{
resolver_.async_resolve(
boost::asio::ip::tcp::resolver::query(host, service),
boost::bind(&connection::handle_resolve, this, _1, _2)
);
}
void connection::handle_resolve(
const boost::system::error_code& ec,
resolver::iterator iterator
)
{
if(ec)
throw error(ec);
std::cout << iterator->endpoint().address() << '\n';
connect(iterator);
}
void connection::connect(resolver::iterator iterator)
{
socket_.async_connect(*iterator, boost::bind(
&connection::handle_connect, this, _1, iterator)
);
}
void connection::handle_connect(
const boost::system::error_code& ec,
resolver::iterator iterator
)
{
if(ec) {
socket_.close();
if(++iterator == resolver::iterator())
throw error(ec);
else
connect(iterator);
} else {
std::cout << "Connected!\n";
connected_ = true;
}
}
}

68
src/network_asio.hpp Normal file
View file

@ -0,0 +1,68 @@
#ifndef NETWORK_ASIO_HPP_INCLUDED
#define NETWORK_ASIO_HPP_INCLUDED
#include <boost/asio.hpp>
#include "exceptions.hpp"
namespace network_asio {
struct error : public game::error
{
error(const boost::system::error_code& error) : game::error(error.message()) {}
};
/** A class that represents a TCP/IP connection. */
class connection
{
boost::asio::io_service io_service_;
typedef boost::asio::ip::tcp::resolver resolver;
resolver resolver_;
typedef boost::asio::ip::tcp::socket socket;
socket socket_;
bool connected_;
void handle_resolve(
const boost::system::error_code& ec,
resolver::iterator iterator
);
void connect(resolver::iterator iterator);
void handle_connect(
const boost::system::error_code& ec,
resolver::iterator iterator
);
public:
/**
* Constructor.
*
* @param host Name of the host to connect to
* @param service Service identifier such as "80" or "http"
*/
connection(const std::string& host, const std::string& service);
/** Handle all pending asynchonous events and return */
std::size_t poll()
{
try {
return io_service_.poll();
} catch(const boost::system::system_error& err) {
throw error(err.code());
}
}
/** Run asio's event loop
*
* Handle asynchronous events blocking until all asynchronous
* operations have finished
*/
void run() { io_service_.run(); }
bool connected() const { return connected_; }
};
}
#endif