summaryrefslogtreecommitdiff
path: root/src/bridge
diff options
context:
space:
mode:
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