xmpp_component.hpp 6.82 KB
Newer Older
1 2 3 4 5
#ifndef XMPP_COMPONENT_INCLUDED
# define XMPP_COMPONENT_INCLUDED

#include <network/socket_handler.hpp>
#include <xmpp/xmpp_parser.hpp>
6
#include <bridge/bridge.hpp>
7 8

#include <unordered_map>
9 10
#include <memory>
#include <string>
11 12 13 14 15 16 17 18 19 20 21 22

/**
 * An XMPP component, communicating with an XMPP server using the protocole
 * described in XEP-0114: Jabber Component Protocol
 *
 * TODO: implement XEP-0225: Component Connections
 */
class XmppComponent: public SocketHandler
{
public:
  explicit XmppComponent(const std::string& hostname, const std::string& secret);
  ~XmppComponent();
23
  void on_connection_failed(const std::string& reason) override final;
louiz’'s avatar
louiz’ committed
24 25
  void on_connected() override final;
  void on_connection_close() override final;
26
  void parse_in_buffer(const size_t size) override final;
louiz’'s avatar
louiz’ committed
27 28 29 30 31 32 33 34
  /**
   * Send a "close" message to all our connected peers.  That message
   * depends on the protocol used (this may be a QUIT irc message, or a
   * <stream/>, etc).  We may also directly close the connection, or we may
   * wait for the remote peer to acknowledge it before closing.
   */
  void shutdown();
  bool is_document_open() const;
louiz’'s avatar
louiz’ committed
35 36 37 38 39
  /**
   * Run a check on all bridges, to remove all disconnected (socket is
   * closed, or no channel is joined) IrcClients. Some kind of garbage collector.
   */
  void clean();
40
  /**
louiz’'s avatar
louiz’ committed
41
   * Connect to the XMPP server.
42
   */
43
  void start();
44 45 46 47
  /**
   * Reset the component so we can use the component on a new XMPP stream
   */
  void reset();
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
  /**
   * Serialize the stanza and add it to the out_buf to be sent to the
   * server.
   */
  void send_stanza(const Stanza& stanza);
  /**
   * Handle the opening of the remote stream
   */
  void on_remote_stream_open(const XmlNode& node);
  /**
   * Handle the closing of the remote stream
   */
  void on_remote_stream_close(const XmlNode& node);
  /**
   * Handle received stanzas
   */
  void on_stanza(const Stanza& stanza);
  /**
   * Send an error stanza. Message being the name of the element inside the
   * stanza, and explanation being a short human-readable sentence
   * describing the error.
   */
  void send_stream_error(const std::string& message, const std::string& explanation);
71 72 73 74 75 76
  /**
   * Send error stanza, described in http://xmpp.org/rfcs/rfc6120.html#stanzas-error
   */
  void send_stanza_error(const std::string& kind, const std::string& to, const std::string& from,
                         const std::string& id, const std::string& error_type,
                         const std::string& defined_condition, const std::string& text);
77 78 79 80
  /**
   * Send the closing signal for our document (not closing the connection though).
   */
  void close_document();
81 82 83
  /**
   * Send a message from from@served_hostname, with the given body
   */
84 85
  void send_message(const std::string& from, Xmpp::body&& body,
                    const std::string& to, const std::string& type);
86 87 88
  /**
   * Send a join from a new participant
   */
89 90 91
  void send_user_join(const std::string& from,
                      const std::string& nick,
                      const std::string& realjid,
92 93 94 95
                      const std::string& affiliation,
                      const std::string& role,
                      const std::string& to,
                      const bool self);
96 97 98 99 100 101
  /**
   * Send an error to indicate that the user tried to join an invalid room
   */
  void send_invalid_room_error(const std::string& muc_jid,
                               const std::string& nick,
                               const std::string& to);
102 103 104
  /**
   * Send the MUC topic to the user
   */
105
  void send_topic(const std::string& from, Xmpp::body&& xmpp_topic, const std::string& to);
louiz’'s avatar
louiz’ committed
106 107 108
  /**
   * Send a (non-private) message to the MUC
   */
109
  void send_muc_message(const std::string& muc_name, const std::string& nick, Xmpp::body&& body, const std::string& jid_to);
louiz’'s avatar
louiz’ committed
110 111 112
  /**
   * Send an unavailable presence for this nick
   */
113
  void send_muc_leave(std::string&& muc_name, std::string&& nick, Xmpp::body&& message, const std::string& jid_to, const bool self);
louiz’'s avatar
louiz’ committed
114 115 116
  /**
   * Indicate that a participant changed his nick
   */
117 118 119 120 121 122 123
  void send_nick_change(const std::string& muc_name,
                        const std::string& old_nick,
                        const std::string& new_nick,
                        const std::string& affiliation,
                        const std::string& role,
                        const std::string& jid_to,
                        const bool self);
124 125 126 127 128 129 130 131
  /**
   * An user is kicked from a room
   */
  void kick_user(const std::string& muc_name,
                     const std::string& target,
                     const std::string& reason,
                     const std::string& author,
                     const std::string& jid_to);
132 133 134 135 136 137
  /**
   * Send a presence type=error with a conflict element
   */
  void send_nickname_conflict_error(const std::string& muc_name,
                                    const std::string& nickname,
                                    const std::string& jid_to);
138 139 140 141 142 143 144 145 146
  /**
   * Send a presence from the MUC indicating a change in the role and/or
   * affiliation of a participant
   */
  void send_affiliation_role_change(const std::string& muc_name,
                                    const std::string& target,
                                    const std::string& affiliation,
                                    const std::string& role,
                                    const std::string& jid_to);
147 148 149 150
  /**
   * Handle the various stanza types
   */
  void handle_handshake(const Stanza& stanza);
151
  void handle_presence(const Stanza& stanza);
louiz’'s avatar
louiz’ committed
152
  void handle_message(const Stanza& stanza);
153
  void handle_iq(const Stanza& stanza);
louiz’'s avatar
louiz’ committed
154
  void handle_error(const Stanza& stanza);
155

156 157 158 159 160 161 162 163 164
  /**
   * Whether or not we ever succeeded our authentication to the XMPP server
   */
  bool ever_auth;
  /**
   * Whether or not the last connection+auth attempt was successful
   */
  bool last_auth;

165
private:
166 167 168 169 170
  /**
   * Return the bridge associated with the given full JID. Create a new one
   * if none already exist.
   */
  Bridge* get_user_bridge(const std::string& user_jid);
171 172 173 174 175
  /**
   * Return a buffer provided by the XML parser, to read data directly into
   * it, and avoiding some unnecessary copy.
   */
  void* get_receive_buffer(const size_t size) const override final;
176 177 178 179 180
  XmppParser parser;
  std::string stream_id;
  std::string served_hostname;
  std::string secret;
  bool authenticated;
louiz’'s avatar
louiz’ committed
181 182 183 184
  /**
   * Whether or not OUR XMPP document is open
   */
  bool doc_open;
185 186 187

  std::unordered_map<std::string, std::function<void(const Stanza&)>> stanza_handlers;

188 189 190 191 192 193
  /**
   * One bridge for each user of the component. Indexed by the user's full
   * jid
   */
  std::unordered_map<std::string, std::unique_ptr<Bridge>> bridges;

194 195 196 197 198 199 200 201
  XmppComponent(const XmppComponent&) = delete;
  XmppComponent(XmppComponent&&) = delete;
  XmppComponent& operator=(const XmppComponent&) = delete;
  XmppComponent& operator=(XmppComponent&&) = delete;
};

#endif // XMPP_COMPONENT_INCLUDED