Send and receive messages

Also correctly respond to PING with the id, escape some XML content, but not
always
This commit is contained in:
Florent Le Coz
2013-11-07 01:53:09 +01:00
parent 4b76a30d04
commit a418b6ed5d
11 changed files with 224 additions and 28 deletions
+4
View File
@@ -15,3 +15,7 @@ Iid::Iid(const std::string& iid)
}
this->server = iid.substr(sep);
}
Iid::Iid()
{
}
+1
View File
@@ -20,6 +20,7 @@ class Iid
{
public:
explicit Iid(const std::string& iid);
explicit Iid();
std::string chan;
std::string server;
+54 -5
View File
@@ -12,7 +12,9 @@
IrcClient::IrcClient(const std::string& hostname, const std::string& username, Bridge* bridge):
hostname(hostname),
username(username),
bridge(bridge)
current_nick(username),
bridge(bridge),
welcomed(false)
{
std::cout << "IrcClient()" << std::endl;
}
@@ -51,6 +53,11 @@ IrcChannel* IrcClient::get_channel(const std::string& name)
}
}
std::string IrcClient::get_own_nick() const
{
return this->current_nick;
}
void IrcClient::parse_in_buffer()
{
while (true)
@@ -63,19 +70,23 @@ void IrcClient::parse_in_buffer()
std::cout << message << std::endl;
// TODO map function and command name properly
if (message.command == "PING")
this->send_pong_command();
this->send_pong_command(message);
else if (message.command == "NOTICE" ||
message.command == "375" ||
message.command == "372")
this->forward_server_message(message);
else if (message.command == "JOIN")
this->on_self_channel_join(message);
else if (message.command == "PRIVMSG")
this->on_channel_message(message);
else if (message.command == "353")
this->set_and_forward_user_list(message);
else if (message.command == "332")
this->on_topic_received(message);
else if (message.command == "366")
this->on_channel_completely_joined(message);
else if (message.command == "001")
this->on_welcome_message(message);
}
}
@@ -102,7 +113,7 @@ void IrcClient::send_message(IrcMessage&& message)
void IrcClient::send_user_command(const std::string& username, const std::string& realname)
{
this->send_message(IrcMessage("USER", {username, "NONE", "NONE", realname}));
this->send_message(IrcMessage("USER", {username, "ignored", "ignored", realname}));
}
void IrcClient::send_nick_command(const std::string& nick)
@@ -112,14 +123,32 @@ void IrcClient::send_nick_command(const std::string& nick)
void IrcClient::send_join_command(const std::string& chan_name)
{
if (this->welcomed == false)
{
this->channels_to_join.push_back(chan_name);
return ;
}
IrcChannel* channel = this->get_channel(chan_name);
if (channel->joined == false)
this->send_message(IrcMessage("JOIN", {chan_name}));
}
void IrcClient::send_pong_command()
bool IrcClient::send_channel_message(const std::string& chan_name, const std::string& body)
{
this->send_message(IrcMessage("PONG", {}));
IrcChannel* channel = this->get_channel(chan_name);
if (channel->joined == false)
{
std::cout << "Cannot send message to channel " << chan_name << ", it is not joined" << std::endl;
return false;
}
this->send_message(IrcMessage("PRIVMSG", {chan_name, body}));
return true;
}
void IrcClient::send_pong_command(const IrcMessage& message)
{
const std::string id = message.arguments[0];
this->send_message(IrcMessage("PONG", {id}));
}
void IrcClient::forward_server_message(const IrcMessage& message)
@@ -154,6 +183,17 @@ void IrcClient::on_self_channel_join(const IrcMessage& message)
channel->set_self(message.prefix);
}
void IrcClient::on_channel_message(const IrcMessage& message)
{
const IrcUser user(message.prefix);
const std::string nick = user.nick;
Iid iid;
iid.chan = message.arguments[0];
iid.server = this->hostname;
const std::string body = message.arguments[1];
this->bridge->send_muc_message(iid, nick, body);
}
void IrcClient::on_topic_received(const IrcMessage& message)
{
const std::string chan_name = message.arguments[1];
@@ -168,3 +208,12 @@ void IrcClient::on_channel_completely_joined(const IrcMessage& message)
this->bridge->send_self_join(this->hostname, chan_name, channel->get_self()->nick);
this->bridge->send_topic(this->hostname, chan_name, channel->topic);
}
void IrcClient::on_welcome_message(const IrcMessage& message)
{
this->current_nick = message.arguments[0];
this->welcomed = true;
for (const std::string& chan_name: this->channels_to_join)
this->send_join_command(chan_name);
this->channels_to_join.clear();
}
+30 -2
View File
@@ -44,6 +44,10 @@ public:
* Return the channel with this name, create it if it does not yet exist
*/
IrcChannel* get_channel(const std::string& name);
/**
* Return our own nick
*/
std::string get_own_nick() const;
/**
* 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
@@ -53,7 +57,7 @@ public:
/**
* Send the PONG irc command
*/
void send_pong_command();
void send_pong_command(const IrcMessage& message);
/**
* Send the USER irc command
*/
@@ -66,6 +70,11 @@ public:
* Send the JOIN irc command
*/
void send_join_command(const std::string& chan_name);
/**
* 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);
/**
* Forward the server message received from IRC to the XMPP component
*/
@@ -80,6 +89,10 @@ public:
* of user comes after so we do not send the self-presence over XMPP yet.
*/
void on_self_channel_join(const IrcMessage& message);
/**
* When a channel message is received
*/
void on_channel_message(const IrcMessage& message);
/**
* Save the topic in the IrcChannel
*/
@@ -89,6 +102,10 @@ public:
* received etc), send the self presence and topic to the XMPP user.
*/
void on_channel_completely_joined(const IrcMessage& message);
/**
* 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);
private:
/**
@@ -99,15 +116,26 @@ private:
* The user name used in the USER irc command
*/
const std::string username;
/**
* Our current nickname on the server
*/
std::string current_nick;
/**
* 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;
/**
* 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;
IrcClient(const IrcClient&) = delete;
IrcClient(IrcClient&&) = delete;