From 0ce75ab52111ba27ca99961057b36b68f0a135a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 3 Jul 2016 15:43:11 +0200 Subject: Properly remove the resource from the server when we leave the last channel --- src/bridge/bridge.cpp | 15 ++++++++++++++- src/bridge/bridge.hpp | 1 + tests/end_to_end/__main__.py | 46 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6de2516..613e0e2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -349,9 +349,11 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message, const st this->send_muc_leave(std::move(iid), std::move(nick), "Biboumi note: "s + std::to_string(resources - 1) + " resources are still in this channel.", true, resource); + if (this->number_of_channels_the_resource_is_in(iid.get_server(), resource) == 0) + this->remove_resource_from_server(iid.get_server(), resource); } } - } +} void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) { @@ -868,6 +870,17 @@ std::size_t Bridge::number_of_resources_in_chan(const Bridge::ChannelKey& channe return it->second.size(); } +std::size_t Bridge::number_of_channels_the_resource_is_in(const std::string& irc_hostname, const std::string& resource) const +{ + std::size_t res = 0; + for (auto pair: this->resources_in_chan) + { + if (std::get<0>(pair.first) == irc_hostname && pair.second.count(resource) != 0) + res++; + } + return res; +} + void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::string& resource) { IrcClient* irc = this->get_irc_client(iid.get_server()); diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp index 6feb282..3430b06 100644 --- a/src/bridge/bridge.hpp +++ b/src/bridge/bridge.hpp @@ -278,6 +278,7 @@ private: void add_resource_to_server(const IrcHostname& irc_hostname, const std::string& resource); void remove_resource_from_server(const IrcHostname& irc_hostname, const std::string& resource); bool is_resource_in_server(const IrcHostname& irc_hostname, const std::string& resource) const; + size_t number_of_channels_the_resource_is_in(const std::string& irc_hostname, const std::string& resource) const; /** * Generate all the stanzas to be sent to this resource, simulating a join on this channel. diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index 0223e47..d1d653d 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -229,7 +229,7 @@ class BiboumiTest: def __init__(self, scenario, expected_code=0): self.scenario = scenario - self.expected_code = 0 + self.expected_code = expected_code def run(self, with_valgrind=True): print("Running scenario: %s%s" % (self.scenario.name, " (with valgrind)" if with_valgrind else '')) @@ -355,6 +355,8 @@ def connection_end_sequence(irc_host, jid): xpath_re % (r'^%s: This server was created .*$' % irc_host)), partial(expect_stanza, xpath_re % (r'^%s: There are \d+ users and \d+ invisible on \d+ servers$' % irc_host)), + partial(expect_stanza, + xpath_re % (r'^%s: \d+ unknown connection\(s\)$' % irc_host), optional=True), partial(expect_stanza, xpath_re % (r'^%s: \d+ channels formed$' % irc_host), optional=True), partial(expect_stanza, @@ -582,7 +584,7 @@ if __name__ == '__main__': partial(send_stanza, "COUCOU"), partial(expect_stanza, "/iq[@type='result']/commands:command[@node='hello'][@status='completed']/commands:note[@type='info'][text()='Hello COUCOU!']") ]), - Scenario("simple_multisessionnick", + Scenario("multisessionnick", [ handshake_sequence(), partial(send_stanza, @@ -605,6 +607,46 @@ if __name__ == '__main__': "/presence/muc_user:x/muc_user:status[@code='110']") ), partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat'][@to='{jid_one}/{resource_two}']/subject[not(text())]"), + + # A different user joins the same room + partial(send_stanza, + ""), + connection_sequence("irc.localhost", '{jid_two}/{resource_one}'), + + partial(expect_stanza, + ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']",)), + partial(expect_stanza, + ("/presence[@to='{jid_one}/{resource_two}'][@from='#foo%{irc_server_one}/{nick_two}']",)), + + partial(expect_stanza, + "/presence[@to='{jid_second}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']"), + partial(expect_stanza, + ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']", + "/presence/muc_user:x/muc_user:status[@code='110']") + ), + partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"), + + # That second user sends a private message to the first one + partial(send_stanza, "RELLO"), + # Message is received with a server-wide JID, by the two resources behind nick_one + partial(expect_stanza, "/message[@from='{lower_nick_two}!{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='RELLO']"), + partial(expect_stanza, "/message[@from='{lower_nick_two}!{irc_server_one}'][@to='{jid_one}/{resource_two}'][@type='chat']/body[text()='RELLO']"), + + # One resource leaves the server entirely. + partial(send_stanza, ""), + # The leave is forwarded only to us + partial(expect_stanza, + ("/presence[@type='unavailable']/muc_user:x/muc_user:status[@code='110']", + "/presence/status[text()='Biboumi note: 1 resources are still in this channel.']") + ), + # The second user sends two new private messages to the first user + partial(send_stanza, "first"), + partial(send_stanza, "second"), + # The first user receives the two messages, on the connected resource, once each + partial(expect_stanza, "/message[@from='{lower_nick_two}!{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='first']"), + partial(expect_stanza, "/message[@from='{lower_nick_two}!{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='second']"), + + ]), Scenario("channel_messages", [ -- cgit v1.2.3