summaryrefslogtreecommitdiff
path: root/src/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp')
-rw-r--r--src/xmpp/jid.cpp19
-rw-r--r--src/xmpp/jid.hpp26
-rw-r--r--src/xmpp/stanza.hpp18
-rw-r--r--src/xmpp/xmpp_component.cpp110
-rw-r--r--src/xmpp/xmpp_component.hpp36
5 files changed, 202 insertions, 7 deletions
diff --git a/src/xmpp/jid.cpp b/src/xmpp/jid.cpp
new file mode 100644
index 0000000..78b28a0
--- /dev/null
+++ b/src/xmpp/jid.cpp
@@ -0,0 +1,19 @@
+#include <xmpp/jid.hpp>
+
+Jid::Jid(const std::string& jid)
+{
+ std::string::size_type at = jid.find("@");
+ if (at != std::string::npos)
+ {
+ this->local = jid.substr(0, at);
+ at++;
+ }
+ else
+ at = 0;
+ std::string::size_type slash = jid.find("/", at);
+ if (slash != std::string::npos)
+ {
+ this->resource = jid.substr(slash + 1);
+ }
+ this->domain = jid.substr(at, slash - at);
+}
diff --git a/src/xmpp/jid.hpp b/src/xmpp/jid.hpp
new file mode 100644
index 0000000..3027497
--- /dev/null
+++ b/src/xmpp/jid.hpp
@@ -0,0 +1,26 @@
+#ifndef JID_INCLUDED
+# define JID_INCLUDED
+
+#include <string>
+
+/**
+ * Parse a JID into its different subart
+ */
+class Jid
+{
+public:
+ explicit Jid(const std::string& jid);
+
+ std::string domain;
+ std::string local;
+ std::string resource;
+
+private:
+ Jid(const Jid&) = delete;
+ Jid(Jid&&) = delete;
+ Jid& operator=(const Jid&) = delete;
+ Jid& operator=(Jid&&) = delete;
+};
+
+
+#endif // JID_INCLUDED
diff --git a/src/xmpp/stanza.hpp b/src/xmpp/stanza.hpp
new file mode 100644
index 0000000..697bda4
--- /dev/null
+++ b/src/xmpp/stanza.hpp
@@ -0,0 +1,18 @@
+#ifndef Stanza
+# define Stanza
+
+class Stanza
+{
+public:
+ explicit Stanza();
+ ~Stanza();
+private:
+ Stanza(const Stanza&) = delete;
+ Stanza(Stanza&&) = delete;
+ Stanza& operator=(const Stanza&) = delete;
+ Stanza& operator=(Stanza&&) = delete;
+};
+
+#endif // Stanza
+
+
diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp
index 0563aa7..3a288c7 100644
--- a/src/xmpp/xmpp_component.cpp
+++ b/src/xmpp/xmpp_component.cpp
@@ -1,4 +1,7 @@
+#include <utils/make_unique.hpp>
+
#include <xmpp/xmpp_component.hpp>
+#include <xmpp/jid.hpp>
#include <iostream>
@@ -20,6 +23,8 @@ XmppComponent::XmppComponent(const std::string& hostname, const std::string& sec
std::placeholders::_1));
this->stanza_handlers.emplace("handshake",
std::bind(&XmppComponent::handle_handshake, this,std::placeholders::_1));
+ this->stanza_handlers.emplace("presence",
+ std::bind(&XmppComponent::handle_presence, this,std::placeholders::_1));
}
XmppComponent::~XmppComponent()
@@ -46,7 +51,6 @@ void XmppComponent::on_connected()
node["xmlns:stream"] = "http://etherx.jabber.org/streams";
node["to"] = "irc.abricot";
this->send_stanza(node);
-
}
void XmppComponent::on_connection_close()
@@ -99,16 +103,17 @@ void XmppComponent::on_stanza(const Stanza& stanza)
{
std::cout << "=========== STANZA ============" << std::endl;
std::cout << stanza.to_string() << std::endl;
+ std::function<void(const Stanza&)> handler;
try
{
- const auto& handler = this->stanza_handlers.at(stanza.get_name());
- handler(stanza);
+ handler = this->stanza_handlers.at(stanza.get_name());
}
catch (const std::out_of_range& exception)
{
std::cout << "No handler for stanza of type " << stanza.get_name() << std::endl;
return;
}
+ handler(stanza);
}
void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation)
@@ -133,5 +138,104 @@ void XmppComponent::close_document()
void XmppComponent::handle_handshake(const Stanza& stanza)
{
+ (void)stanza;
this->authenticated = true;
}
+
+void XmppComponent::handle_presence(const Stanza& stanza)
+{
+ Bridge* bridge = this->get_user_bridge(stanza["from"]);
+ Jid to(stanza["to"]);
+ Iid iid(to.local);
+ if (!iid.chan.empty() && !iid.server.empty())
+ bridge->join_irc_channel(iid, to.resource);
+}
+
+Bridge* XmppComponent::get_user_bridge(const std::string& user_jid)
+{
+ try
+ {
+ return this->bridges.at(user_jid).get();
+ }
+ catch (const std::out_of_range& exception)
+ {
+ this->bridges.emplace(user_jid, std::make_unique<Bridge>(user_jid, this, this->poller));
+ return this->bridges.at(user_jid).get();
+ }
+}
+
+void XmppComponent::send_message(const std::string& from, const std::string& body, const std::string& to)
+{
+ XmlNode node("message");
+ node["to"] = to;
+ node["from"] = from + "@" + this->served_hostname;
+ XmlNode body_node("body");
+ body_node.set_inner(body);
+ body_node.close();
+ node.add_child(std::move(body_node));
+ node.close();
+ this->send_stanza(node);
+}
+
+void XmppComponent::send_user_join(const std::string& from, const std::string& nick, const std::string& to)
+{
+ XmlNode node("presence");
+ node["to"] = to;
+ node["from"] = from + "@" + this->served_hostname + "/" + nick;
+
+ XmlNode x("x");
+ x["xmlns"] = "http://jabber.org/protocol/muc#user";
+
+ // TODO: put real values here
+ XmlNode item("item");
+ item["affiliation"] = "member";
+ item["role"] = "participant";
+ item.close();
+ x.add_child(std::move(item));
+ x.close();
+ node.add_child(std::move(x));
+ node.close();
+ this->send_stanza(node);
+}
+
+void XmppComponent::send_self_join(const std::string& from, const std::string& nick, const std::string& to)
+{
+ XmlNode node("presence");
+ node["to"] = to;
+ node["from"] = from + "@" + this->served_hostname + "/" + nick;
+
+ XmlNode x("x");
+ x["xmlns"] = "http://jabber.org/protocol/muc#user";
+
+ // TODO: put real values here
+ XmlNode item("item");
+ item["affiliation"] = "member";
+ item["role"] = "participant";
+ item.close();
+ x.add_child(std::move(item));
+
+ XmlNode status("status");
+ status["code"] = "110";
+ status.close();
+ x.add_child(std::move(status));
+
+ x.close();
+
+ node.add_child(std::move(x));
+ node.close();
+ this->send_stanza(node);
+}
+
+void XmppComponent::send_topic(const std::string& from, const std::string& topic, const std::string& to)
+{
+ XmlNode message("message");
+ message["to"] = to;
+ message["from"] = from + "@" + this->served_hostname;
+ message["type"] = "groupchat";
+ XmlNode subject("subject");
+ subject.set_inner(topic);
+ subject.close();
+ message.add_child(std::move(subject));
+ message.close();
+ this->send_stanza(message);
+}
diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp
index 464ecaa..725b495 100644
--- a/src/xmpp/xmpp_component.hpp
+++ b/src/xmpp/xmpp_component.hpp
@@ -1,13 +1,13 @@
#ifndef XMPP_COMPONENT_INCLUDED
# define XMPP_COMPONENT_INCLUDED
-#include <string>
-
#include <network/socket_handler.hpp>
-
#include <xmpp/xmpp_parser.hpp>
+#include <bridge/bridge.hpp>
#include <unordered_map>
+#include <memory>
+#include <string>
/**
* An XMPP component, communicating with an XMPP server using the protocole
@@ -55,13 +55,35 @@ public:
* Send the closing signal for our document (not closing the connection though).
*/
void close_document();
-
+ /**
+ * Send a message from from@served_hostname, with the given body
+ */
+ void send_message(const std::string& from, const std::string& body, const std::string& to);
+ /**
+ * Send a join from a new participant
+ */
+ void send_user_join(const std::string& from, const std::string& nick, const std::string& to);
+ /**
+ * Send the self join to the user
+ */
+ void send_self_join(const std::string& from, const std::string& nick, const std::string& to);
+ /**
+ * Send the MUC topic to the user
+ */
+ void send_topic(const std::string& from, const std::string& topic, const std::string& to);
/**
* Handle the various stanza types
*/
void handle_handshake(const Stanza& stanza);
+ void handle_presence(const Stanza& stanza);
private:
+ /**
+ * 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);
+
XmppParser parser;
std::string stream_id;
std::string served_hostname;
@@ -70,6 +92,12 @@ private:
std::unordered_map<std::string, std::function<void(const Stanza&)>> stanza_handlers;
+ /**
+ * 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;
+
XmppComponent(const XmppComponent&) = delete;
XmppComponent(XmppComponent&&) = delete;
XmppComponent& operator=(const XmppComponent&) = delete;