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

/**
 * Handles the reading part of the socket.
7 8 9
 * Keeps a list of callbacks to call, associated with a message name, and
 * execute them when the associated message is received.
 * @class MessageHandler
10 11
 */

12 13
#ifndef MESSAGE_HANDLER_HPP
# define MESSAGE_HANDLER_HPP
14

15
#include <deque>
louiz’'s avatar
louiz’ committed
16
#include <map>
17
#include <functional>
louiz’'s avatar
louiz’ committed
18

19
#include <boost/asio.hpp>
louiz’'s avatar
louiz’ committed
20

21
#include <network/transfer_sender.hpp>
22
#include <network/base_socket.hpp>
23
#include <network/message.hpp>
louiz’'s avatar
louiz’ committed
24

25
typedef std::function<void(Message*)> t_read_callback;
louiz’'s avatar
louiz’ committed
26

27
class MessageHandler: public BaseSocket
louiz’'s avatar
louiz’ committed
28 29
{
public:
30 31
  explicit MessageHandler(boost::asio::io_service&);
  virtual ~MessageHandler();
louiz’'s avatar
louiz’ committed
32

33 34
  void install_read_handler();
  /**
35
   * called when there's something to read on the socket. Reads the message
36
   * the size of the arguments, and then calls binary_read_handler to read
37
   * the arguments of the message, if any.
38 39 40
   */
  void read_handler(const boost::system::error_code& error, const std::size_t bytes_transferred);
  /**
41 42
   * Read the arguments after a message (can read 0 bytes too) and pass that
   * to the callback that was associated with this message.
43
   */
44
  void binary_read_handler(const boost::system::error_code&, Message*, std::size_t, std::vector<t_read_callback> callbacks);
45
  /**
46
   * Sends a message, and use install_callback_once to wait for the answer
47 48
   * and call that callback to handle it.
   */
49
  void request_answer(Message*, t_read_callback on_answer, std::string name = "");
50
  /**
51 52
   * Install a new callback associated with a message. This callback will
   * be called upon receiving that message.
53
   */
54
  void install_callback(const std::string&, t_read_callback);
55
  /**
56 57 58
   * Install a new callback associated with a message. This callback will
   * be called upon receiving that message, but only once. This is used
   * for example if you send a message waiting for and answer, you install
59 60
   * a callback that will handle that answer, and only this one.
   */
61
  void install_callback_once(const std::string&, t_read_callback);
62 63 64
  /**
   * Remove a callback that has been installed.
   */
65
  void remove_callback(const std::string&);
66
  /**
67 68 69 70
   * Add the given message to the messages_to_send queue, then
   * calls check_messages_to_send. Which may send the next available
   * message, if there's no async_write() call already running.
   * It does not necessarily actually send the message on the socket.
71
   */
72
  void send(Message* message, std::function< void(void) > on_sent = 0);
73 74
  void send_message(const char* name, const google::protobuf::Message& msg);
  void send_message(const char* name, const std::string& archive);
75

louiz’'s avatar
louiz’ committed
76
protected:
77
  /**
78 79
   * Returns all the callbacks associated with the passed message name.
   * Returns an empty vector if nothing was found.
80
   */
81
  std::vector<t_read_callback> get_callbacks(const std::string&);
82 83 84
  /**
   * @todo Check if the data was correctly sent on the socket
   */
85
  void send_handler(const boost::system::error_code&, std::size_t, Message*);
86
  /**
87
   * Actually sends the message on the socket, calling async_write.
88
   */
89
  void actually_send(Message*);
90 91
  /**
   * Checks if there's something to send on the socket. We first check if
92
   * the writing boolean is false, and then we pop the next available message
93
   * from the queue (if any) and we send it using async_write.
94
   * @returns true if a message was sent, false otherwise.
95
   */
96
  bool check_messages_to_send();
97 98 99
  /**
   * A buffer keeping the data that is read on the socket.
   */
100
  boost::asio::streambuf data;
101 102 103 104
  /**
   * What happens when a read error occurs.
   */
  virtual void on_connection_closed() = 0;
105

louiz’'s avatar
louiz’ committed
106
private:
107 108
  MessageHandler(const MessageHandler&);
  MessageHandler& operator=(const MessageHandler&);
louiz’'s avatar
louiz’ committed
109

110 111
  std::multimap<const std::string, t_read_callback > callbacks;
  std::multimap<const std::string, t_read_callback > callbacks_once;
112 113 114 115
  /**
   * A queue of messages. If there's not async_write running, we pop one
   * from it and we send it.
   */
116
  std::deque<Message*> messages_to_send;
117
  /**
118
   * Tells us if we are waiting for an async_write to finish or not.
119
   * This must be set to true when calling async_write(), to false
120
   * in the write handler. It is used by check_messages_to_send.
121 122
   */
  bool writing;
louiz’'s avatar
louiz’ committed
123 124
};

125
#endif // MESSAGE_HANDLER_HPP