diff options
author | louiz’ <louiz@louiz.org> | 2017-07-28 18:03:16 +0200 |
---|---|---|
committer | louiz’ <louiz@louiz.org> | 2017-07-28 18:03:16 +0200 |
commit | 8c92473a6681aaf671b21780202dde731772cee8 (patch) | |
tree | 6ff2ae92dc06ff873c2d0e162f50cc649f3b8198 /src/xmpp/biboumi_component.cpp | |
parent | 76f5fa81f2026770c907bee0e931aae8d8c7a1bd (diff) | |
parent | 6187423e6ed834570783ef3097a6ef73cc58107a (diff) | |
download | biboumi-8c92473a6681aaf671b21780202dde731772cee8.tar.gz biboumi-8c92473a6681aaf671b21780202dde731772cee8.tar.bz2 biboumi-8c92473a6681aaf671b21780202dde731772cee8.tar.xz biboumi-8c92473a6681aaf671b21780202dde731772cee8.zip |
Merge branch 'master' into debian
Diffstat (limited to 'src/xmpp/biboumi_component.cpp')
-rw-r--r-- | src/xmpp/biboumi_component.cpp | 141 |
1 files changed, 123 insertions, 18 deletions
diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 32f3968..0e1d270 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -83,6 +83,14 @@ void BiboumiComponent::shutdown() { for (auto& pair: this->bridges) pair.second->shutdown("Gateway shutdown"); +#ifdef USE_DATABASE + for (const Database::RosterItem& roster_item: Database::get_full_roster()) + { + this->send_presence_to_contact(roster_item.col<Database::LocalJid>(), + roster_item.col<Database::RemoteJid>(), + "unavailable"); + } +#endif } void BiboumiComponent::clean() @@ -160,16 +168,50 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) { if (type == "subscribe") { // Auto-accept any subscription request for an IRC server - this->accept_subscription(to_str, from.bare()); - this->ask_subscription(to_str, from.bare()); + this->send_presence_to_contact(to_str, from.bare(), "subscribed", id); + if (iid.type == Iid::Type::None || bridge->find_irc_client(iid.get_server())) + this->send_presence_to_contact(to_str, from.bare(), ""); + this->send_presence_to_contact(to_str, from.bare(), "subscribe"); +#ifdef USE_DATABASE + if (!Database::has_roster_item(to_str, from.bare())) + Database::add_roster_item(to_str, from.bare()); +#endif + } + else if (type == "unsubscribe") + { + this->send_presence_to_contact(to_str, from.bare(), "unavailable", id); + this->send_presence_to_contact(to_str, from.bare(), "unsubscribed"); + this->send_presence_to_contact(to_str, from.bare(), "unsubscribe"); +#ifdef USE_DATABASE + const bool res = Database::has_roster_item(to_str, from.bare()); + if (res) + Database::delete_roster_item(to_str, from.bare()); +#endif + } + else if (type == "probe") + { + if ((iid.type == Iid::Type::Server && bridge->find_irc_client(iid.get_server())) + || iid.type == Iid::Type::None) + { +#ifdef USE_DATABASE + if (Database::has_roster_item(to_str, from.bare())) +#endif + this->send_presence_to_contact(to_str, from.bare(), ""); +#ifdef USE_DATABASE + else // rfc 6121 4.3.2.1 + this->send_presence_to_contact(to_str, from.bare(), "unsubscribed"); +#endif + } + } + else if (type.empty()) + { // We just receive a presence from someone (as the result of a probe, + // or a directed presence, or a normal presence change) + if (iid.type == Iid::Type::None) + this->send_presence_to_contact(to_str, from.bare(), ""); } - } - else - { - // A user wants to join an invalid IRC channel, return a presence error to him/her - if (type.empty()) - this->send_invalid_room_error(to.local, to.resource, from_str); + else if (iid.type == Iid::Type::User) + { // Do nothing yet } } catch (const IRCNotConnected& ex) @@ -177,7 +219,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) if (type != "unavailable") this->send_stanza_error("presence", from_str, to_str, id, "cancel", "remote-server-not-found", - "Not connected to IRC server "s + ex.hostname, + "Not connected to IRC server " + ex.hostname, true); } stanza_error.disable(); @@ -268,7 +310,11 @@ void BiboumiComponent::handle_message(const Stanza& stanza) const auto invite_to = invite->get_tag("to"); if (!invite_to.empty()) { - bridge->send_irc_invitation(iid, invite_to); + Jid invited_jid{invite_to}; + if (invited_jid.domain == this->get_served_hostname() || invited_jid.local.empty()) + bridge->send_irc_invitation(iid, invite_to); + else + this->send_invitation_from_fulljid(std::to_string(iid), invite_to, from_str); } } @@ -277,7 +323,7 @@ void BiboumiComponent::handle_message(const Stanza& stanza) { this->send_stanza_error("message", from_str, to_str, id, "cancel", "remote-server-not-found", - "Not connected to IRC server "s + ex.hostname, + "Not connected to IRC server " + ex.hostname, true); } stanza_error.disable(); @@ -586,7 +632,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) { this->send_stanza_error("iq", from, to_str, id, "cancel", "remote-server-not-found", - "Not connected to IRC server "s + ex.hostname, + "Not connected to IRC server " + ex.hostname, true); stanza_error.disable(); return; @@ -806,7 +852,7 @@ void BiboumiComponent::send_irc_server_disco_info(const std::string& id, const s XmlSubNode identity(query, "identity"); identity["category"] = "conference"; identity["type"] = "irc"; - identity["name"] = "IRC server "s + from.local + " over Biboumi"; + identity["name"] = "IRC server " + from.local + " over Biboumi"; for (const char *ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS, PING_NS, MAM_NS, VERSION_NS}) { XmlSubNode feature(query, "feature"); @@ -849,7 +895,7 @@ void BiboumiComponent::send_irc_channel_disco_info(const std::string& id, const XmlSubNode identity(query, "identity"); identity["category"] = "conference"; identity["type"] = "irc"; - identity["name"] = "IRC channel "s + iid.get_local() + " from server " + iid.get_server() + " over biboumi"; + identity["name"] = "IRC channel " + iid.get_local() + " from server " + iid.get_server() + " over biboumi"; for (const char *ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS, PING_NS, MAM_NS, VERSION_NS}) { XmlSubNode feature(query, "feature"); @@ -945,6 +991,16 @@ void BiboumiComponent::send_invitation(const std::string& room_target, const std::string& jid_to, const std::string& author_nick) { + if (author_nick.empty()) + this->send_invitation_from_fulljid(room_target, jid_to, room_target + "@" + this->served_hostname); + else + this->send_invitation_from_fulljid(room_target, jid_to, room_target + "@" + this->served_hostname + "/" + author_nick); +} + +void BiboumiComponent::send_invitation_from_fulljid(const std::string& room_target, + const std::string& jid_to, + const std::string& from) +{ Stanza message("message"); { message["from"] = room_target + "@" + this->served_hostname; @@ -952,10 +1008,7 @@ void BiboumiComponent::send_invitation(const std::string& room_target, XmlSubNode x(message, "x"); x["xmlns"] = MUC_USER_NS; XmlSubNode invite(x, "invite"); - if (author_nick.empty()) - invite["from"] = room_target + "@" + this->served_hostname; - else - invite["from"] = room_target + "@" + this->served_hostname + "/" + author_nick; + invite["from"] = from; } this->send_stanza(message); } @@ -979,3 +1032,55 @@ void BiboumiComponent::ask_subscription(const std::string& from, const std::stri presence["type"] = "subscribe"; this->send_stanza(presence); } + +void BiboumiComponent::send_presence_to_contact(const std::string& from, const std::string& to, + const std::string& type, const std::string& id) +{ + Stanza presence("presence"); + presence["from"] = from; + presence["to"] = to; + if (!type.empty()) + presence["type"] = type; + if (!id.empty()) + presence["id"] = id; + this->send_stanza(presence); +} + +void BiboumiComponent::on_irc_client_connected(const std::string& irc_hostname, const std::string& jid) +{ +#ifdef USE_DATABASE + const auto local_jid = irc_hostname + "@" + this->served_hostname; + if (Database::has_roster_item(local_jid, jid)) + this->send_presence_to_contact(local_jid, jid, ""); +#endif +} + +void BiboumiComponent::on_irc_client_disconnected(const std::string& irc_hostname, const std::string& jid) +{ +#ifdef USE_DATABASE + const auto local_jid = irc_hostname + "@" + this->served_hostname; + if (Database::has_roster_item(local_jid, jid)) + this->send_presence_to_contact(irc_hostname + "@" + this->served_hostname, jid, "unavailable"); +#endif +} + +void BiboumiComponent::after_handshake() +{ + XmppComponent::after_handshake(); + +#ifdef USE_DATABASE + const auto contacts = Database::get_contact_list(this->get_served_hostname()); + + for (const Database::RosterItem& roster_item: contacts) + { + const auto remote_jid = roster_item.col<Database::RemoteJid>(); + // In response, we will receive a presence indicating the + // contact is online, to which we will respond with our own + // presence. + // If the contact removed us from their roster while we were + // offline, we will receive an unsubscribed presence, letting us + // stay in sync. + this->send_presence_to_contact(this->get_served_hostname(), remote_jid, "probe"); + } +#endif +} |