#include "deliantra/asio_communicator.h" #include #include #include #include void asio_communicator::receive () { read_msg (); } void asio_communicator::send (std::string const &command) { m_request.clear (); m_request.push_back ((command.length () & 0xff00) >> 8 * 1); m_request.push_back ((command.length () & 0x00ff) >> 8 * 0); m_request.insert (m_request.end (), command.begin (), command.end ()); boost::asio::async_write (m_socket, boost::asio::buffer (m_request), boost::bind (&asio_communicator::handle_send, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void asio_communicator::set_packet_handler (interface::packet_handler &handler) { on = &handler; } asio_communicator::asio_communicator ( boost::asio::io_service &io_service , std::string const &server , std::string const &port ) : m_resolver (io_service) , m_socket (io_service) { /* * Start an asynchronous resolve to translate the server and service names * into a list of endpoints. */ tcp::resolver::query query (server, port); m_resolver.async_resolve (query, boost::bind (&asio_communicator::handle_resolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } void asio_communicator::handle_resolve ( boost::system::error_code const &err , tcp::resolver::iterator endpoint_iterator ) { if (!err) { /* * Attempt a connection to the first endpoint in the list. Each endpoint * will be tried until we successfully establish a connection. */ tcp::endpoint endpoint = *endpoint_iterator; m_socket.async_connect (endpoint, boost::bind (&asio_communicator::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else throw std::runtime_error (std::string (__func__) + ": " + err.message ()); } void asio_communicator::handle_connect ( boost::system::error_code const &err , tcp::resolver::iterator endpoint_iterator ) { if (!err) on->ready (); else if (endpoint_iterator != tcp::resolver::iterator ()) { /* The connection failed. Try the next endpoint in the list. */ m_socket.close (); tcp::endpoint endpoint = *endpoint_iterator; m_socket.async_connect (endpoint, boost::bind (&asio_communicator::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else throw std::runtime_error (std::string (__func__) + ": " + err.message ()); } void asio_communicator::handle_send ( boost::system::error_code const &err , size_t n ) { if (err) throw std::runtime_error (std::string (__func__) + ": " + err.message ()); } void asio_communicator::read (void (asio_communicator::*handler) (boost::system::error_code const &err, size_t n), size_t length) { m_response.resize (length); boost::asio::async_read (m_socket, boost::asio::buffer (m_response), boost::bind (handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void asio_communicator::read_msg () { read (&asio_communicator::read_msg_length, 2); } void asio_communicator::read_msg_length (boost::system::error_code const &err, size_t n) { if (!err) { size_t length = m_response.at (0) << 8 * 1 | m_response.at (1) << 8 * 0 ; read (&asio_communicator::read_msg_body, length); } else throw std::runtime_error (std::string (__func__) + ": " + err.message ()); } void asio_communicator::read_msg_body (boost::system::error_code const &err, size_t n) { if (!err) on->receive (std::string (m_response.begin (), m_response.end ())); else throw std::runtime_error (std::string (__func__) + ": " + err.message ()); }