remote_client_base.hpp 3.03 KB
Newer Older
1 2 3 4 5 6
/** @addtogroup Network
 *  @{
 */

/**
 * Represents one single remote client. It is kept in a list, by the Server
7 8
 * object. Using the MessageHandler interface, it executes callbacks
 * upon receiving message from the client, and sends messages when
9
 * we need to communicate something to it.
10
 * The derived classes must install their own callback, install a transfer handler
11
 * in it or not, etc.
12
 * @class RemoteClientBase
13 14
 */

15 16
#ifndef REMOTE_CLIENT_BASE
# define REMOTE_CLIENT_BASE
17

18 19 20 21 22 23
#include <cstdint>

#include <functional>

#include <boost/asio.hpp>

24 25
#include <network/message_handler.hpp>
#include <network/message.hpp>
26 27 28
#include <network/timed_event_handler.hpp>
#include <network/timed_event.hpp>
#include <network/ping_handler.hpp>
29 30 31 32 33 34
#include <network/ioservice.hpp>

#include <logging/logging.hpp>

// In seconds
static constexpr int ping_interval = 10;
35

36 37
template <typename SocketType>
class RemoteClientBase: public MessageHandler<SocketType>, public TimedEventHandler, public PingHandler
38 39
{
public:
louiz’'s avatar
louiz’ committed
40 41 42
  template <typename... SocketArgs>
  RemoteClientBase(SocketArgs&&... socket_args):
    MessageHandler<SocketType>(std::forward<SocketArgs>(socket_args)...),
43
    id(RemoteClientBase<SocketType>::clients_number++)
44
  { }
45

46
  virtual ~RemoteClientBase() = default;
47

48 49 50
  /**
   * starts the client (install the read handler, etc)
   */
louiz’'s avatar
louiz’ committed
51
  virtual void start()
52 53 54 55 56 57 58
  {
    log_debug("Starting RemoteClientBase " << this->id);
    this->install_callbacks();
    this->install_timed_event(std::bind(&RemoteClientBase::send_ping, this), ping_interval);
    this->install_read_handler();
  }

59 60 61
  /**
   * Send a ping request to the remote client.
   */
62 63 64 65 66 67 68 69
  void send_ping()
  {
    Message* message = new Message;
    message->set_name("PING");
    this->request_answer(message, std::bind(&RemoteClientBase::on_pong, this, std::placeholders::_1), "PONG");
    this->ping_sent();
  }

70 71 72
  /**
   * Called when the response to our ping request is received.
   */
73 74 75 76 77 78 79
  void on_pong(Message*)
  {
    this->pong_received();
    log_debug("Current ping: " << this->get_latency() << "micro seconds.");
    this->install_timed_event(std::bind(&RemoteClientBase::send_ping, this), ping_interval);
  }

80 81 82 83 84
  /**
   * The number of clients is incremented each time
   * a new client is accepted.
   */
  static unsigned long int clients_number;
85

86 87 88
  /**
   * Returns the client number (aka id).
   */
89
  uint32_t get_id() const { return this->id; }
90

91 92 93 94 95
  boost::asio::ip::tcp::endpoint& get_endpoint()
  {
    return this->endpoint;
  }

96
protected:
97 98 99
  /**
   * The client number (aka id).
   */
100
  const uint32_t id;
101
  /**
102 103 104
   * Creates the default callbacks associated with a network message.
   * It is executed whenever that message is received.
   * See MessageHandler for details
105
   */
106
private:
107 108
  virtual void on_connection_closed() = 0;
  virtual void install_callbacks() = 0;
109
  /**
110 111 112
   * A endpoint containing the information of the remote peer.  It is set by
   * asio, when async_accept succeeds, just before the accept handler is
   * called.
113
   */
114
  boost::asio::ip::tcp::endpoint endpoint;
115 116
};

117 118
#endif // REMOTE_CLIENT_BASE

119
/**@}*/