diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bridge/bridge.cpp | 3 | ||||
-rw-r--r-- | src/bridge/bridge.hpp | 3 | ||||
-rw-r--r-- | src/xmpp/xmpp_component.cpp | 32 |
3 files changed, 34 insertions, 4 deletions
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index f9dc9a6..b2563f0 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -41,11 +41,10 @@ static std::tuple<std::string, std::string> get_role_affiliation_from_irc_mode(c return std::make_tuple("participant", "none"); } -void Bridge::shutdown() +void Bridge::shutdown(const std::string& exit_message) { for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) { - const std::string exit_message("Gateway shutdown"); it->second->send_quit_command(exit_message); it->second->leave_dummy_channel(exit_message); } diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp index d0fd5bd..f78bade 100644 --- a/src/bridge/bridge.hpp +++ b/src/bridge/bridge.hpp @@ -27,11 +27,12 @@ public: /** * QUIT all connected IRC servers. */ - void shutdown(); + void shutdown(const std::string& exit_message); /** * Remove all inactive IrcClients */ void clean(); + static Xmpp::body make_xmpp_body(const std::string& str); /*** ** diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp index 967614c..aa466f5 100644 --- a/src/xmpp/xmpp_component.cpp +++ b/src/xmpp/xmpp_component.cpp @@ -34,6 +34,19 @@ using namespace std::string_literals; unsigned long XmppComponent::current_id = 0; +static std::set<std::string> kickable_errors{ + "gone", + "internal-server-error", + "item-not-found", + "jid-malformed", + "recipient-unavailable", + "redirect", + "remote-server-not-found", + "remote-server-timeout", + "service-unavailable", + "malformed-error" + }; + XmppComponent::XmppComponent(const std::string& hostname, const std::string& secret): ever_auth(false), last_auth(false), @@ -128,7 +141,7 @@ void XmppComponent::shutdown() { for (auto it = this->bridges.begin(); it != this->bridges.end(); ++it) { - it->second->shutdown(); + it->second->shutdown("Gateway shutdown"); } } @@ -359,6 +372,23 @@ void XmppComponent::handle_message(const Stanza& stanza) if (subject) bridge->set_channel_topic(iid, subject->get_inner()); } + else if (type == "error") + { + const XmlNode* error = stanza.get_child(COMPONENT_NS":error"); + // Only a set of errors are considered “fatal”. If we encounter one of + // them, we purge (we disconnect the user from all the IRC servers). + // We consider this to be true, unless the error condition is + // specified and is not in the kickable_errors set + bool kickable_error = true; + if (error) + { + const XmlNode* condition = error->get_last_child(); + if (kickable_errors.find(condition->get_name()) == kickable_errors.end()) + kickable_error = false; + } + if (kickable_error) + bridge->shutdown("Error from remote client"); + } else { if (body && !body->get_inner().empty()) |