Commit 04b8a290 authored by louiz’'s avatar louiz’

Simplify the network module by making the asio::io_service object global

Since each process has only one single io_service object
parent bd760470
......@@ -3,8 +3,7 @@
#include <boost/archive/text_iarchive.hpp>
#include <world/world.hpp>
RemoteGameClient::RemoteGameClient(boost::asio::io_service& io_service):
RemoteClientBase(io_service),
RemoteGameClient::RemoteGameClient():
server(nullptr)
{
}
......
......@@ -14,7 +14,7 @@ class GameServer;
class RemoteGameClient: public RemoteClientBase
{
public:
RemoteGameClient(boost::asio::io_service& io_service);
RemoteGameClient();
~RemoteGameClient();
void on_connection_closed() override final;
void set_game_server(GameServer* server);
......
......@@ -2,8 +2,7 @@
#include <master_server/master_server.hpp>
#include "master.pb.h"
RemoteClient::RemoteClient(boost::asio::io_service& io_service):
RemoteClientBase(io_service),
RemoteClient::RemoteClient():
user(nullptr),
server(nullptr),
senders{}
......
......@@ -24,7 +24,7 @@ class TransferSender;
class RemoteClient: public RemoteClientBase
{
public:
explicit RemoteClient(boost::asio::io_service&);
RemoteClient();
~RemoteClient();
void on_connection_closed() override final;
void set_server(MasterServer* server);
......
/**
* A very simple base class that must be inherited by all network object
* that needs their own ioservice (for example anything that has a socket,
* or a timer, etc). But not by class that need to share a io_service that
* was created earlier. Basically, this means only Server, Client and
* GameClient should inherite this. All remote_client etc need to share the
* Server's io_service.
*/
#ifndef BASE_IOSERVICE
# define BASE_IOSERVICE
#include <boost/asio.hpp>
class BaseIoservice
{
public:
explicit BaseIoservice() {}
~BaseIoservice() {}
/**
* Returns a reference to the io_service object, so other affiliated
* objects can use it to create some io-related objects.
*/
boost::asio::io_service& get_io_service()
{
return this->io_service;
}
protected:
boost::asio::io_service io_service;
private:
BaseIoservice(const BaseIoservice&) = delete;
BaseIoservice(BaseIoservice&&) = delete;
BaseIoservice& operator=(const BaseIoservice&) = delete;
BaseIoservice& operator=(BaseIoservice&&) = delete;
};
#endif // BASE_IOSERVICE
/**
* A very simple base class that must be inherited by all network object
* that needs a socket.
* If an io_service is provided, we use it. Otherwise we use our own
* io_service.
*/
#ifndef BASE_SOCKET
# define BASE_SOCKET
#include <boost/asio.hpp>
#include <network/ioservice.hpp>
class BaseSocket
{
public:
explicit BaseSocket(boost::asio::io_service& io_service):
socket(io_service) {}
explicit BaseSocket():
socket(IoService::get())
{
}
~BaseSocket() = default;
const boost::asio::ip::tcp::socket& get_socket() const
{
return this->socket;
......@@ -23,11 +25,10 @@ public:
{
return this->socket;
}
~BaseSocket() {}
protected:
boost::asio::ip::tcp::socket socket;
private:
boost::asio::ip::tcp::socket socket;
BaseSocket(const BaseSocket&) = delete;
BaseSocket(BaseSocket&&) = delete;
BaseSocket& operator=(const BaseSocket&) = delete;
......
#include <logging/logging.hpp>
#include <network/client.hpp>
#include <boost/algorithm/string.hpp>
Client::Client()
{
}
Client::~Client()
{
}
void Client::install_callbacks()
{
this->install_callback("TRANSFER", std::bind(&Client::transfer_init_callback,
this, std::placeholders::_1));
}
void Client::transfer_init_callback(Message* received_message)
{
std::string arg(received_message->body, received_message->body_size);
std::vector<std::string> args;
boost::split(args, arg, boost::is_any_of("|"));
if (args.size() != 3)
{
log_warning("File transfer information are wrong: " << arg);
return ;
}
log_debug("Starting file transfer reception: " << arg);
TransferReceiver* receiver = new TransferReceiver(this, args[0], args[1], atoi(args[2].data()));
this->receivers.push_back(receiver);
}
void Client::on_transfer_ended(const TransferReceiver* receiver)
{
log_debug("on_transfer_ended");
std::vector<TransferReceiver*>::iterator it;
for (it = this->receivers.begin(); it < this->receivers.end(); ++it)
if (*it == receiver)
{
this->receivers.erase(it);
break ;
}
delete receiver;
}
void Client::on_connection_closed()
{
}
/** @addtogroup Network
* @{
*/
/**
* @class Client
*/
#ifndef __CLIENT_HPP__
# define __CLIENT_HPP__
#include <network/client_base.hpp>
#include <network/transfer_receiver.hpp>
using boost::asio::ip::tcp;
class Client: public ClientBase
{
public:
Client();
~Client();
/**
* Install all the default callbacks.
*/
virtual void install_callbacks();
virtual void on_connection_closed();
/**
* Called when a file transfer is finished.
*/
void on_transfer_ended(const TransferReceiver*);
private:
/**
* Called when the server initiate a file transfer with us.
* Install the temporary callback to receive each file chunk.
*/
void transfer_init_callback(Message*);
std::vector<TransferReceiver*> receivers;
boost::asio::io_service io_service;
};
#endif /*__CLIENT_HPP__ */
/**@}*/
......@@ -2,18 +2,16 @@
#include <network/client_base.hpp>
#include <boost/algorithm/string.hpp>
ClientBase::ClientBase():
BaseIoservice(),
MessageHandler(io_service)
ClientBase::ClientBase()
{
}
ClientBase::~ClientBase()
{
if (this->socket.is_open())
if (this->get_socket().is_open())
{
log_debug("Closing connection");
this->socket.close();
this->get_socket().close();
}
}
......@@ -25,7 +23,7 @@ void ClientBase::connect(const std::string& host,
{
// TODO use resolve and DNS
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host), port);
this->socket.async_connect(endpoint,
this->get_socket().async_connect(endpoint,
std::bind(&ClientBase::connect_handler, this,
on_success, on_failure,
std::placeholders::_1));
......@@ -64,7 +62,7 @@ void ClientBase::ping_callback(Message*)
void ClientBase::poll()
{
while (this->io_service.poll() != 0)
while (IoService::get().poll() != 0)
;
}
......
......@@ -17,7 +17,6 @@
#ifndef __CLIENT_BASE_HPP__
# define __CLIENT_BASE_HPP__
#include <network/base_ioservice.hpp>
#include <network/message_handler.hpp>
#include <network/ping_handler.hpp>
#include <network/timed_event_handler.hpp>
......@@ -26,8 +25,8 @@
#include <utils/time.hpp>
class ClientBase: public BaseIoservice, public MessageHandler,
public TimedEventHandler, public PingHandler
class ClientBase:public MessageHandler, public TimedEventHandler,
public PingHandler
{
public:
ClientBase();
......
#include <network/ioservice.hpp>
boost::asio::io_service IoService::io_service;
#ifndef IOSERVICE_HPP_INCLUDED
#define IOSERVICE_HPP_INCLUDED
#include <boost/asio.hpp>
class IoService
{
public:
IoService();
~IoService();
static boost::asio::io_service& get()
{
return IoService::io_service;
}
private:
static boost::asio::io_service io_service;
IoService(const IoService&) = delete;
IoService(IoService&&) = delete;
IoService& operator=(const IoService&) = delete;
IoService& operator=(IoService&&) = delete;
};
#endif /* IOSERVICE_HPP_INCLUDED */
......@@ -2,8 +2,7 @@
#include <network/message_handler.hpp>
#include <network/message.hpp>
MessageHandler::MessageHandler(boost::asio::io_service& io_service):
BaseSocket(io_service),
MessageHandler::MessageHandler():
writing(false)
{
}
......@@ -96,7 +95,7 @@ void MessageHandler::read_handler(const boost::system::error_code& error, const
// We check what we need to read on the socket to have the rest of the binary datas
const std::size_t length_to_read = this->data.size() >= size ? 0 : size - this->data.size();
boost::asio::async_read(this->socket,
boost::asio::async_read(this->get_socket(),
this->data,
boost::asio::transfer_at_least(length_to_read),
std::bind(&MessageHandler::binary_read_handler, this,
......@@ -143,7 +142,7 @@ void MessageHandler::binary_read_handler(const boost::system::error_code& error,
void MessageHandler::install_read_handler(void)
{
boost::asio::async_read_until(this->socket,
boost::asio::async_read_until(this->get_socket(),
this->data,
':',
std::bind(&MessageHandler::read_handler, this,
......@@ -201,7 +200,7 @@ void MessageHandler::actually_send(Message* message)
std::vector<boost::asio::const_buffer> buffs;
buffs.push_back(boost::asio::buffer(message->header.data(), message->header.length()));
buffs.push_back(boost::asio::buffer(message->body, message->body_size));
async_write(this->socket,
async_write(this->get_socket(),
buffs,
std::bind(&MessageHandler::send_handler, this,
std::placeholders::_1,
......
......@@ -27,7 +27,7 @@ typedef std::function<void(Message*)> t_read_callback;
class MessageHandler: public BaseSocket
{
public:
explicit MessageHandler(boost::asio::io_service&);
explicit MessageHandler();
virtual ~MessageHandler();
void install_read_handler();
......
#include <logging/logging.hpp>
#include <network/remote_client_base.hpp>
#include <network/ioservice.hpp>
// In seconds
static constexpr int ping_interval = 10;
unsigned long int RemoteClientBase::clients_number = 0;
RemoteClientBase::RemoteClientBase(boost::asio::io_service& io_service):
MessageHandler(io_service),
id(RemoteClientBase::clients_number++),
io_service(io_service)
RemoteClientBase::RemoteClientBase():
id(RemoteClientBase::clients_number++)
{
}
......@@ -19,7 +21,7 @@ void RemoteClientBase::start()
{
log_debug("Starting RemoteClientBase " << this->id);
this->install_callbacks();
this->install_timed_event(this->io_service, std::bind(&RemoteClientBase::send_ping, this), 2);
this->install_timed_event(std::bind(&RemoteClientBase::send_ping, this), ping_interval);
MessageHandler::install_read_handler();
}
......@@ -35,5 +37,5 @@ void RemoteClientBase::on_pong(Message*)
{
this->pong_received();
log_debug("Current ping: " << this->get_latency() << "micro seconds.");
this->install_timed_event(this->io_service, std::bind(&RemoteClientBase::send_ping, this), 2);
this->install_timed_event(std::bind(&RemoteClientBase::send_ping, this), ping_interval);
}
......@@ -27,13 +27,12 @@
#include <boost/chrono.hpp>
#include <logging/logging.hpp>
#include <network/base_ioservice.hpp>
#include <network/base_socket.hpp>
#include <network/message.hpp>
#include <utils/time.hpp>
template <class T>
class Server: public BaseIoservice, public BaseSocket
class Server: public BaseSocket
{
public:
/**
......@@ -41,12 +40,11 @@ public:
* @param port The port on which the servers accepts new connections.
*/
Server(short port):
BaseIoservice(),
BaseSocket(io_service),
BaseSocket(),
port(port),
timeout(io_service),
acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
stop_signal_set(io_service),
timeout(IoService::get()),
acceptor(IoService::get(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
stop_signal_set(IoService::get()),
started(false)
{
}
......@@ -90,7 +88,7 @@ public:
{
if (t == 0)
{
while (this->io_service.poll())
while (IoService::get().poll())
;
return ;
}
......@@ -103,8 +101,8 @@ public:
this->timeout.async_wait([](const boost::system::error_code&){});
// Wait for one event to happen (either a timeout or something
// on the socket).
this->io_service.run_one();
while (this->io_service.poll() != 0)
IoService::get().run_one();
while (IoService::get().poll() != 0)
; // Execute all other available handlers, if any
}
/**
......@@ -209,7 +207,7 @@ public:
private:
void install_accept_handler(void)
{
T* new_client = new T(this->io_service);
T* new_client = new T();
this->acceptor.async_accept(new_client->get_socket(),
std::bind(&Server<T>::handle_accept,
......
#include <logging/logging.hpp>
#include <network/timed_event_handler.hpp>
#include <network/ioservice.hpp>
TimedEventHandler::TimedEventHandler()
{
......@@ -16,12 +17,12 @@ TimedEventHandler::~TimedEventHandler()
}
}
void TimedEventHandler::install_timed_event(boost::asio::io_service& io_service,
const timed_callback_t callback,
void TimedEventHandler::install_timed_event(const timed_callback_t callback,
const int delay)
{
log_debug("installing timed_event");
boost::asio::deadline_timer* timer = new boost::asio::deadline_timer(io_service, boost::posix_time::seconds(delay));
boost::asio::deadline_timer* timer = new boost::asio::deadline_timer(
IoService::get(), boost::posix_time::seconds(delay));
TimedEvent* event = new TimedEvent(this, timer, callback);
this->events.push_back(event);
}
......
......@@ -23,7 +23,7 @@ public:
/**
* Install a timed event to be executed in the futur at the specified date.
*/
void install_timed_event(boost::asio::io_service&, const timed_callback_t, const int);
void install_timed_event(const timed_callback_t, const int);
/**
* Remove the event from the list. It is deleted and canceled (if it was
* not already called, it'll never be).
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment