summaryrefslogtreecommitdiff
path: root/src/bridge
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2013-11-06 20:51:05 +0100
committerFlorent Le Coz <louiz@louiz.org>2013-11-06 21:01:18 +0100
commitbf7b05ef72bbdac97704d262ddfe418908267535 (patch)
treeb23b3a5a5d469c47c37422559be76ee34238649a /src/bridge
parentdea7f60fa1ae6a46228daa36bcb3fec1a6c6ffc3 (diff)
downloadbiboumi-bf7b05ef72bbdac97704d262ddfe418908267535.tar.gz
biboumi-bf7b05ef72bbdac97704d262ddfe418908267535.tar.bz2
biboumi-bf7b05ef72bbdac97704d262ddfe418908267535.tar.xz
biboumi-bf7b05ef72bbdac97704d262ddfe418908267535.zip
Implement the Bridge class to translate between the two protocols
Add all useful classes as well: Jid, Iid, IrcChannel, IrcUser etc to properly keep the informations about what we receive from the IRC server. Only handle the MUC join stanza, and send the list of users in the IRC channel to the XMPP user, and the IRC channel’s topic, for now.
Diffstat (limited to 'src/bridge')
-rw-r--r--src/bridge/bridge.cpp57
-rw-r--r--src/bridge/bridge.hpp94
2 files changed, 151 insertions, 0 deletions
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
new file mode 100644
index 0000000..638777d
--- /dev/null
+++ b/src/bridge/bridge.cpp
@@ -0,0 +1,57 @@
+#include <bridge/bridge.hpp>
+#include <xmpp/xmpp_component.hpp>
+#include <network/poller.hpp>
+
+Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller):
+ user_jid(user_jid),
+ xmpp(xmpp),
+ poller(poller)
+{
+}
+
+Bridge::~Bridge()
+{
+}
+
+IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string& username)
+{
+ try
+ {
+ return this->irc_clients.at(hostname).get();
+ }
+ catch (const std::out_of_range& exception)
+ {
+ this->irc_clients.emplace(hostname, std::make_shared<IrcClient>(hostname, username, this));
+ std::shared_ptr<IrcClient> irc = this->irc_clients.at(hostname);
+ this->poller->add_socket_handler(irc);
+ irc->start();
+ return irc.get();
+ }
+}
+
+void Bridge::join_irc_channel(const Iid& iid, const std::string& username)
+{
+ IrcClient* irc = this->get_irc_client(iid.server, username);
+ irc->send_join_command(iid.chan);
+}
+
+void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg)
+{
+ const std::string body = std::string("[") + author + std::string("] ") + msg;
+ this->xmpp->send_message(from, body, this->user_jid);
+}
+
+void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick)
+{
+ this->xmpp->send_user_join(chan_name + "%" + hostname, nick, this->user_jid);
+}
+
+void Bridge::send_self_join(const std::string& hostname, const std::string& chan_name, const std::string nick)
+{
+ this->xmpp->send_self_join(chan_name + "%" + hostname, nick, this->user_jid);
+}
+
+void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic)
+{
+ this->xmpp->send_topic(chan_name + "%" + hostname, topic, this->user_jid);
+}
diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp
new file mode 100644
index 0000000..f9ddcca
--- /dev/null
+++ b/src/bridge/bridge.hpp
@@ -0,0 +1,94 @@
+#ifndef BRIDGE_INCLUDED
+# define BRIDGE_INCLUDED
+
+#include <irc/irc_client.hpp>
+#include <irc/iid.hpp>
+
+#include <unordered_map>
+#include <string>
+#include <memory>
+
+class XmppComponent;
+class Poller;
+
+/**
+ * One bridge is spawned for each XMPP user that uses the component. The
+ * bridge spawns IrcClients when needed (when the user wants to join a
+ * channel on a new server) and does the translation between the two
+ * protocols.
+ */
+class Bridge
+{
+public:
+ explicit Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller);
+ ~Bridge();
+
+ /***
+ **
+ ** From XMPP to IRC.
+ **
+ **/
+
+ void join_irc_channel(const Iid& iid, const std::string& username);
+
+ /***
+ **
+ ** From IRC to XMPP.
+ **
+ **/
+
+ /**
+ * Send a message corresponding to a server NOTICE, the from attribute
+ * should be juste the server hostname@irc.component.
+ */
+ void send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg);
+ /**
+ * Send the presence of a new user in the MUC.
+ */
+ void send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick);
+ /**
+ * Send the self presence of an user when the MUC is fully joined.
+ */
+ void send_self_join(const std::string& hostname, const std::string& chan_name, const std::string nick);
+ /**
+ * Send the topic of the MUC to the user
+ */
+ void send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic);
+
+private:
+ /**
+ * Returns the client for the given hostname, create one (and use the
+ * username in this case) if none is found, and connect that newly-created
+ * client immediately.
+ */
+ IrcClient* get_irc_client(const std::string& hostname, const std::string& username);
+ /**
+ * The JID of the user associated with this bridge. Messages from/to this
+ * JID are only managed by this bridge.
+ */
+ std::string user_jid;
+ /**
+ * One IrcClient for each IRC server we need to be connected to.
+ * The pointer is shared by the bridge and the poller.
+ */
+ std::unordered_map<std::string, std::shared_ptr<IrcClient>> irc_clients;
+ /**
+ * A raw pointer, because we do not own it, the XMPP component owns us,
+ * but we still need to communicate with it, when sending messages from
+ * IRC to XMPP.
+ */
+ XmppComponent* xmpp;
+ /**
+ * Poller, to give it the IrcClients that we spawn, to make it manage
+ * their sockets.
+ * We don't own it.
+ */
+ Poller* poller;
+
+ Bridge(const Bridge&) = delete;
+ Bridge(Bridge&& other) = delete;
+ Bridge& operator=(const Bridge&) = delete;
+ Bridge& operator=(Bridge&&) = delete;
+};
+
+#endif // BRIDGE_INCLUDED