irc_client.hpp 4.76 KB
Newer Older
1 2 3
#ifndef IRC_CLIENT_INCLUDED
# define IRC_CLIENT_INCLUDED

4
#include <irc/irc_message.hpp>
5 6
#include <irc/irc_channel.hpp>
#include <irc/iid.hpp>
louiz’'s avatar
louiz’ committed
7

8 9
#include <network/socket_handler.hpp>

10
#include <unordered_map>
11 12
#include <string>

13 14
class Bridge;

15 16 17 18 19 20 21 22 23
/**
 * Represent one IRC client, i.e. an endpoint connected to a single IRC
 * server, through a TCP socket, receiving and sending commands to it.
 *
 * TODO: TLS support, maybe, but that's not high priority
 */
class IrcClient: public SocketHandler
{
public:
24
  explicit IrcClient(const std::string& hostname, const std::string& username, Bridge* bridge);
25
  ~IrcClient();
26 27 28 29
  /**
   * Connect to the IRC server
   */
  void start();
louiz’'s avatar
louiz’ committed
30 31 32 33
  /**
   * Called when successfully connected to the server
   */
  void on_connected();
34 35 36 37 38 39 40 41 42
  /**
   * Close the connection, remove us from the poller
   */
  void on_connection_close();
  /**
   * Parse the data we have received so far and try to get one or more
   * complete messages from it.
   */
  void parse_in_buffer();
43 44 45 46
  /**
   * Return the channel with this name, create it if it does not yet exist
   */
  IrcChannel* get_channel(const std::string& name);
louiz’'s avatar
louiz’ committed
47 48 49 50
  /**
   * Returns true if the channel is joined
   */
  bool is_channel_joined(const std::string& name);
louiz’'s avatar
louiz’ committed
51 52 53 54
  /**
   * Return our own nick
   */
  std::string get_own_nick() const;
louiz’'s avatar
louiz’ committed
55 56 57 58 59 60
  /**
   * Serialize the given message into a line, and send that into the socket
   * (actually, into our out_buf and signal the poller that we want to wach
   * for send events to be ready)
   */
  void send_message(IrcMessage&& message);
61 62 63
  /**
   * Send the PONG irc command
   */
louiz’'s avatar
louiz’ committed
64
  void send_pong_command(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
65 66 67 68 69 70 71 72 73
  /**
   * Send the USER irc command
   */
  void send_user_command(const std::string& username, const std::string& realname);
  /**
   * Send the NICK irc command
   */
  void send_nick_command(const std::string& username);
  /**
louiz’'s avatar
louiz’ committed
74
   * Send the JOIN irc command.
louiz’'s avatar
louiz’ committed
75 76
   */
  void send_join_command(const std::string& chan_name);
louiz’'s avatar
louiz’ committed
77 78 79 80 81
  /**
   * Send a PRIVMSG command for a channel
   * Return true if the message was actually sent
   */
  bool send_channel_message(const std::string& chan_name, const std::string& body);
louiz’'s avatar
louiz’ committed
82 83 84 85
  /**
   * Send a PRIVMSG command for an user
   */
  void send_private_message(const std::string& username, const std::string& body);
louiz’'s avatar
louiz’ committed
86 87 88 89
  /**
   * Send the PART irc command
   */
  void send_part_command(const std::string& chan_name, const std::string& status_message);
90 91 92 93 94 95 96 97 98 99 100 101 102
  /**
   * Forward the server message received from IRC to the XMPP component
   */
  void forward_server_message(const IrcMessage& message);
  /**
   * Forward the join of an other user into an IRC channel, and save the
   * IrcUsers in the IrcChannel
   */
  void set_and_forward_user_list(const IrcMessage& message);
  /**
   * Remember our nick and host, when we are joined to the channel. The list
   * of user comes after so we do not send the self-presence over XMPP yet.
   */
louiz’'s avatar
louiz’ committed
103
  void on_channel_join(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
104 105 106 107
  /**
   * When a channel message is received
   */
  void on_channel_message(const IrcMessage& message);
108 109 110 111 112 113 114 115 116
  /**
   * Save the topic in the IrcChannel
   */
  void on_topic_received(const IrcMessage& message);
  /**
   * The channel has been completely joined (self presence, topic, all names
   * received etc), send the self presence and topic to the XMPP user.
   */
  void on_channel_completely_joined(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
117 118 119 120
  /**
   * When a message 001 is received, join the rooms we wanted to join, and set our actual nickname
   */
  void on_welcome_message(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
121 122 123 124
  /**
   * When a PART message is received
   */
  void on_part(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
125 126 127 128
  /**
   * When a NICK message is received
   */
  void on_nick(const IrcMessage& message);
louiz’'s avatar
louiz’ committed
129 130 131 132
  /**
   * When a QUIT message is received
   */
  void on_quit(const IrcMessage& message);
133 134

private:
135 136 137 138 139 140 141 142
  /**
   * The hostname of the server we are connected to.
   */
  const std::string hostname;
  /**
   * The user name used in the USER irc command
   */
  const std::string username;
louiz’'s avatar
louiz’ committed
143 144 145 146
  /**
   * Our current nickname on the server
   */
  std::string current_nick;
147 148 149 150 151 152 153 154
  /**
   * Raw pointer because the bridge owns us.
   */
  Bridge* bridge;
  /**
   * The list of joined channels, indexed by name
   */
  std::unordered_map<std::string, std::unique_ptr<IrcChannel>> channels;
louiz’'s avatar
louiz’ committed
155 156 157 158 159 160 161 162
  /**
   * A list of chan we want to join, but we need a response 001 from
   * the server before sending the actual JOIN commands. So we just keep the
   * channel names in a list, and send the JOIN commands for each of them
   * whenever the WELCOME message is received.
   */
  std::vector<std::string> channels_to_join;
  bool welcomed;
163

164 165 166 167 168 169 170
  IrcClient(const IrcClient&) = delete;
  IrcClient(IrcClient&&) = delete;
  IrcClient& operator=(const IrcClient&) = delete;
  IrcClient& operator=(IrcClient&&) = delete;
};

#endif // IRC_CLIENT_INCLUDED