Initial implementation of the client side of the new network API.
Also added a method to get the ip address of the server in ANA's client.
This commit is contained in:
parent
830022f221
commit
a572690b5d
6 changed files with 214 additions and 42 deletions
|
@ -4,7 +4,7 @@ PROJECT_NAME = ana
|
|||
|
||||
PROJECT_NUMBER =
|
||||
|
||||
OUTPUT_DIRECTORY = doc/code
|
||||
OUTPUT_DIRECTORY = code
|
||||
|
||||
CREATE_SUBDIRS = YES
|
||||
|
||||
|
|
|
@ -743,6 +743,9 @@ namespace ana
|
|||
*/
|
||||
virtual void set_connect_timeout( size_t ms ) = 0;
|
||||
|
||||
/** Returns the string representing the ip address of the connected client. */
|
||||
virtual std::string ip_address() const = 0;
|
||||
|
||||
/** Standard destructor. */
|
||||
virtual ~client() {}
|
||||
};
|
||||
|
|
|
@ -268,6 +268,11 @@ void asio_client::expecting_message( size_t ms_until_timeout )
|
|||
wait_for_incoming_message( ms_until_timeout );
|
||||
}
|
||||
|
||||
std::string asio_client::ip_address() const
|
||||
{
|
||||
return socket_.remote_endpoint().address().to_string();
|
||||
}
|
||||
|
||||
void asio_client::disconnect_listener()
|
||||
{
|
||||
io_service_.stop();
|
||||
|
|
|
@ -106,6 +106,8 @@ class asio_client : public ana::client,
|
|||
|
||||
virtual void expecting_message( size_t ms_until_timeout );
|
||||
|
||||
virtual std::string ip_address() const;
|
||||
|
||||
void handle_connect(const boost::system::error_code& ec,
|
||||
tcp::resolver::iterator endpoint_iterator,
|
||||
ana::connection_handler*,
|
||||
|
|
|
@ -17,82 +17,196 @@
|
|||
* See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/* STL headers ----------------------------------- */
|
||||
|
||||
#include <string>
|
||||
#include <stringstream>
|
||||
|
||||
/* Boost headers --------------------------------- */
|
||||
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
|
||||
/* Local headers --------------------------------- */
|
||||
|
||||
#include "network_askync.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
using namespace network;
|
||||
|
||||
/* ----------------------------------- Utility Functions ----------------------------------- */
|
||||
|
||||
namespace utils
|
||||
{
|
||||
|
||||
std::string compress_config( const config& cfg )
|
||||
{
|
||||
std::ostringstream out;
|
||||
compress_config( cfg, out );
|
||||
return out.str( );
|
||||
}
|
||||
|
||||
|
||||
void compress_config( const config& cfg, std::ostringstream& out)
|
||||
{
|
||||
boost::iostreams::filtering_stream<boost::iostreams::output> filter;
|
||||
filter.push(boost::iostreams::gzip_compressor());
|
||||
filter.push(out);
|
||||
write(filter, cfg);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
void read_config( const ana::detail::read_buffer& buffer, config& cfg)
|
||||
{
|
||||
std::istringstream input( buffer->string() );
|
||||
|
||||
read_gz(cfg, input);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------- Client Implementation --------------------------------- */
|
||||
|
||||
client::client( handler& handler ) :
|
||||
client_( ... )
|
||||
client::client( handler& handler,
|
||||
const std::string& address = "server.wesnoth.org",
|
||||
const std::string& port = "15000" )
|
||||
:
|
||||
status_( DISCONNECTED ),
|
||||
client_( address, port ),
|
||||
handler_( handler ),
|
||||
wesnoth_id_( 0 )
|
||||
{
|
||||
client_->set_listener_handler( this );
|
||||
client_->set_raw_data_mode();
|
||||
client_->run();
|
||||
client_->start_logging();
|
||||
}
|
||||
|
||||
client::~client()
|
||||
{
|
||||
client_->disconnect();
|
||||
delete client_;
|
||||
}
|
||||
|
||||
void client::set_send_timeout( ana::timeout_policy type, size_t ms )
|
||||
{
|
||||
client_->set_timeouts( type, ms );
|
||||
}
|
||||
|
||||
void client::set_connect_timeout( size_t ms )
|
||||
void client::async_connect( size_t timeout )
|
||||
{
|
||||
//TODO: Deal with the case that the client is not disconnected.
|
||||
|
||||
client_->set_connect_timeout( timeout );
|
||||
client_->connect();
|
||||
}
|
||||
|
||||
void client::async_connect( const std::string& address = "server.wesnoth.org",
|
||||
const std::string& port = "15000" )
|
||||
void client::async_connect_through_proxy( size_t timeout,
|
||||
const std::string& proxy_addr,
|
||||
const std::string& proxy_port,
|
||||
const std::string& user_name,
|
||||
const std::string& password)
|
||||
{
|
||||
client_->set_connect_timeout( timeout );
|
||||
client_->connect_trough_proxy(proxy_addr, proxy_port, this, user_name, password);
|
||||
}
|
||||
|
||||
void client::async_connect_through_proxy( const std::string& proxy_addr = "server.wesnoth.org",
|
||||
const std::string& proxy_port = "15000",
|
||||
const std::string& user_name = "",
|
||||
const std::string& password = "")
|
||||
operation_id client::async_send( const config& )
|
||||
{
|
||||
return client_->send( ana::buffer( compress_config( config ) ) );
|
||||
}
|
||||
|
||||
operation_id client::async_send( const config&, ana::send_type = ana::COPY_BUFFER)
|
||||
void client::waiting_for_message( size_t time )
|
||||
{
|
||||
client_->expecting_message( time );
|
||||
}
|
||||
|
||||
void client::waiting_for_message( time )
|
||||
{
|
||||
}
|
||||
|
||||
ana::stats* client::get_stats( ana::stat_type = ana::ACCUMULATED )
|
||||
ana::stats* client::get_stats( ana::stat_type type )
|
||||
{
|
||||
return client_->get_stats( type );
|
||||
}
|
||||
|
||||
void client::cancel_pending( )
|
||||
{
|
||||
client_->cancel_pending();
|
||||
}
|
||||
|
||||
void client::disconnect()
|
||||
{
|
||||
client_->disconnect();
|
||||
}
|
||||
|
||||
std::string client::ip_address_of_server() const
|
||||
{
|
||||
return client_->ip_address();
|
||||
}
|
||||
|
||||
network::wesnoth_id client::get_wesnoth_id() const
|
||||
{
|
||||
return wesnoth_id_;
|
||||
}
|
||||
|
||||
/*------- Private methods ---------------------------------*/
|
||||
|
||||
void client::set_wesnoth_id( wesnoth_id id)
|
||||
{
|
||||
wesnoth_id_ = id;
|
||||
}
|
||||
|
||||
/*------- Client handlers for ANA's network events. -------*/
|
||||
|
||||
void client::handle_connect( ana::error_code error, net_id server_id )
|
||||
{
|
||||
ana::serializer::bostream bos;
|
||||
|
||||
uint32_t handshake( 0 );
|
||||
bos << handshake;
|
||||
|
||||
client_->send( ana::buffer( bos.str()), this );
|
||||
|
||||
status_ = PENDING_HANDSHAKE;
|
||||
}
|
||||
|
||||
void client::handle_disconnect( ana::error_code error, net_id server_id)
|
||||
{
|
||||
handler_.handle_disconnect( error, server_id );
|
||||
}
|
||||
|
||||
void client::handle_receive( ana::error_code error, ana::net_id id, ana::detail::read_buffer buf)
|
||||
{
|
||||
if ( status_ == CONNECTED )
|
||||
{
|
||||
config cfg;
|
||||
|
||||
if ( ! error )
|
||||
read_config( buf, cfg)
|
||||
|
||||
handler_.handle_receive( error, id, cfg );
|
||||
}
|
||||
else if ( status_ == PENDING_HANDSHAKE )
|
||||
{
|
||||
wesnoth_id my_id;
|
||||
ana::serializer::bistream bis;
|
||||
|
||||
client->wait_raw_object(bis, sizeof(my_id) );
|
||||
|
||||
bis >> my_id;
|
||||
ana::network_to_host_long( my_id );
|
||||
|
||||
set_wesnoth_id( my_id );
|
||||
|
||||
client_->set_header_first_mode();
|
||||
client_->run_listener();
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Can't receive a message while disconnected.");
|
||||
}
|
||||
|
||||
void client::handle_send( ana::error_code error, ana::net_id client, ana::operation_id op_id)
|
||||
{
|
||||
handler_.handle_receive( error, client, op_id );
|
||||
}
|
||||
|
||||
/* --------------------------------- Server Implementation --------------------------------- */
|
||||
|
|
|
@ -68,6 +68,14 @@ Feature Requests:
|
|||
/** Namespace of the asynchronous network API. */
|
||||
namespace network
|
||||
{
|
||||
|
||||
/**
|
||||
* A wesnoth ID of a network component.
|
||||
* For instance, when a client connects to a server, it is a assigned a server side
|
||||
* wesnoth_id from the server.
|
||||
*/
|
||||
typedef uint32_t wesnoth_id;
|
||||
|
||||
/**
|
||||
* Main interface for handlers of Wesnoth network events.
|
||||
*
|
||||
|
@ -151,11 +159,19 @@ namespace network
|
|||
/**
|
||||
* Create a client, and associate a handler object to it.
|
||||
*
|
||||
* Note: The parameter is a reference because it can't be a NULL pointer.
|
||||
* @param handler : The handler of the network events of this client.
|
||||
* @param address : The address of the server you are trying to connect to. Defaults
|
||||
* to Wesnoth's official server.
|
||||
* @param port : The port you are trying to connect to. Defaults to Wesnoth's default.
|
||||
*
|
||||
* Note: The handler parameter is a reference because it can't be a NULL pointer.
|
||||
*/
|
||||
client( handler& handler );
|
||||
client( handler& handler,
|
||||
const std::string& address = "server.wesnoth.org",
|
||||
const std::string& port = "15000" );
|
||||
// Idea: Add a set_handler method to change handlers during execution.
|
||||
|
||||
/** Standard destructor. */
|
||||
~client();
|
||||
|
||||
/**
|
||||
|
@ -167,14 +183,6 @@ namespace network
|
|||
*/
|
||||
void set_send_timeout( ana::timeout_policy type, size_t ms = 0 );
|
||||
|
||||
/**
|
||||
* Set timeouts for connect operations for the client.
|
||||
*
|
||||
* Examples:
|
||||
* - set_connect_timeout( ana::time::seconds( 10 ) );
|
||||
*/
|
||||
void set_connect_timeout( size_t ms = 0 );
|
||||
|
||||
|
||||
// Possibilities: Either use set_timeout to set general timeouts for groups of
|
||||
// operations or have a timeout parameter for each time you call a method.
|
||||
|
@ -183,24 +191,25 @@ namespace network
|
|||
* Attempt an asynchronous connection to a server, it will call the corresponding
|
||||
* handle_connect with the results eventually.
|
||||
*
|
||||
* @param address : The address of the server you are trying to connect to. Defaults
|
||||
* to Wesnoth's official server.
|
||||
* @param port : The port you are trying to connect to. Defaults to Wesnoth's default.
|
||||
* @param time : Time to connection attempt timeout, e.g. ana::time::seconds( 10 ).
|
||||
* Default: no timeout.
|
||||
*/
|
||||
void async_connect( const std::string& address = "server.wesnoth.org",
|
||||
const std::string& port = "15000" );
|
||||
void async_connect( size_t timeout = 0 );
|
||||
|
||||
/**
|
||||
* Attempt an asynchronous connection through proxy, will call handle_connect
|
||||
* with results eventually.
|
||||
*
|
||||
* @param time : Time to connection attempt timeout, e.g. ana::time::seconds( 10 ).
|
||||
* Default: no timeout.
|
||||
* @param address : The address of the server you are trying to connect to. Defaults
|
||||
* to Wesnoth's official server.
|
||||
* @param port : The port you are trying to connect to. Defaults to Wesnoth's default.
|
||||
* @param user_name : The proxy's user name used for credentials.
|
||||
* @param password : The proxy's password used for credentials.
|
||||
*/
|
||||
void async_connect_through_proxy( const std::string& proxy_addr = "server.wesnoth.org",
|
||||
void async_connect_through_proxy( size_t timeout = 0,
|
||||
const std::string& proxy_addr = "server.wesnoth.org",
|
||||
const std::string& proxy_port = "15000",
|
||||
const std::string& user_name = "",
|
||||
const std::string& password = "");
|
||||
|
@ -209,26 +218,27 @@ namespace network
|
|||
* Attempt to send a WML document to the server.
|
||||
*
|
||||
* @param config : The WML document to send.
|
||||
* @param send_type : The type of send operation, use ana::DONT_COPY to avoid
|
||||
* unnecessary memory duplication. However, you must ensure that
|
||||
* the config object used will be alive until the call of
|
||||
* the handle_send with the returned operation_id. The default
|
||||
* value will be ana::COPY_BUFFER.
|
||||
*
|
||||
* @returns the ana::operation_id corresponding to this operation.
|
||||
*
|
||||
* @sa ana::operation_id
|
||||
* @sa ana::send_type
|
||||
*/
|
||||
operation_id async_send( const config&, ana::send_type = ana::COPY_BUFFER);
|
||||
operation_id async_send( const config& );
|
||||
|
||||
/**
|
||||
* Signal the client that you are waiting for a message from the server
|
||||
* The time parameter indicates how long you are willing to wait
|
||||
* If a message is received before this time period the appropiate call to
|
||||
* handle_receive will be made with ana::timeout_error.
|
||||
* @param time: Indicates how long you are willing to wait. If a message
|
||||
* is received before this time period the appropiate call to
|
||||
* handle_receive will be made with ana::timeout_error. To create a time
|
||||
* duration, use the functions declared in the ana::time namespace.
|
||||
*
|
||||
* Example :
|
||||
* - client.waiting_for_message( ana::time::seconds( 5 ) );
|
||||
*
|
||||
* @sa ana::time
|
||||
*/
|
||||
void waiting_for_message( time );
|
||||
void waiting_for_message( size_t time );
|
||||
|
||||
/**
|
||||
* Get network stats for the client, the parameter indicates the time period
|
||||
|
@ -247,7 +257,23 @@ namespace network
|
|||
*/
|
||||
std::string ip_address_of_server() const;
|
||||
|
||||
/**
|
||||
* Returns the wesnoth_id of this client.
|
||||
*
|
||||
* @sa wesnoth_id
|
||||
*/
|
||||
wesnoth_id get_wesnoth_id() const;
|
||||
|
||||
private:
|
||||
/* ------------------------------ Private methods -----------------------------*/
|
||||
|
||||
/**
|
||||
* Sets the wesnoth_id of this client.
|
||||
*
|
||||
* @sa wesnoth_id
|
||||
*/
|
||||
void set_wesnoth_id( wesnoth_id );
|
||||
|
||||
/* ------------------------ Inhereted handler methods -------------------------*/
|
||||
|
||||
virtual void handle_connect( ana::error_code error, net_id server_id );
|
||||
|
@ -262,11 +288,33 @@ namespace network
|
|||
net_id client,
|
||||
ana::operation_id op_id);
|
||||
|
||||
/* ------------------------------- Private Types ------------------------------*/
|
||||
|
||||
/** Connection status. */
|
||||
enum client_status
|
||||
{
|
||||
/** Not connected to the server. */
|
||||
DISCONNECTED,
|
||||
|
||||
/** Waiting for handshake completion. */
|
||||
PENDING_HANDSHAKE,
|
||||
|
||||
/** Connected to the server. */
|
||||
CONNECTED
|
||||
};
|
||||
|
||||
/* -------------------------------- Attributes --------------------------------*/
|
||||
|
||||
client_status status_;
|
||||
|
||||
/** The ana::client object representing this client. @sa ana::client */
|
||||
ana::client* client_;
|
||||
|
||||
/** The object handling the network events for this client. */
|
||||
handler& handler_;
|
||||
|
||||
/** The wesnoth_id assigned by the server. */
|
||||
wesnoth_id wesnoth_id_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue