From 694ff33145467a9d8a0f87317124bc5c4251d18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Wed, 12 Jan 2011 21:15:56 +0100 Subject: Refactored MUC code a bit. diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 20bf403..5ce799f 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -18,7 +18,7 @@ #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/JID/JID.h" #include "Swiften/MUC/MUC.h" -#include "Swiften/MUC/MUCOccupant.h" +#include "Swiften/Elements/MUCOccupant.h" namespace Swift { class StanzaChannel; diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index d9fb138..5784788 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -57,6 +57,9 @@ namespace Swift { } template boost::shared_ptr getStanzaAtIndex(size_t index) { + if (sentStanzas.size() <= index) { + return boost::shared_ptr(); + } return boost::dynamic_pointer_cast(sentStanzas[index]); } diff --git a/Swiften/Elements/MUCOccupant.cpp b/Swiften/Elements/MUCOccupant.cpp new file mode 100644 index 0000000..0d3773e --- /dev/null +++ b/Swiften/Elements/MUCOccupant.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Elements/MUCOccupant.h" + +namespace Swift { + +MUCOccupant::MUCOccupant(const String &nick, Role role, Affiliation affiliation) : nick_(nick), role_(role), affiliation_(affiliation) { +} + +MUCOccupant::~MUCOccupant() { +} + +MUCOccupant::MUCOccupant(const MUCOccupant& other) : nick_(other.getNick()), role_(other.getRole()), affiliation_(other.getAffiliation()), realJID_(other.getRealJID()) { + +} + +String MUCOccupant::getNick() const { + return nick_; +} + +MUCOccupant::Role MUCOccupant::getRole() const { + return role_; +} + +MUCOccupant::Affiliation MUCOccupant::getAffiliation() const { + return affiliation_; +} + +void MUCOccupant::setRealJID(const JID& realJID) { + realJID_ = realJID; +} + +void MUCOccupant::setNick(const String& nick) { + nick_ = nick; +} + + +boost::optional MUCOccupant::getRealJID() const { + return realJID_; +} + +} diff --git a/Swiften/Elements/MUCOccupant.h b/Swiften/Elements/MUCOccupant.h new file mode 100644 index 0000000..96ac5ad --- /dev/null +++ b/Swiften/Elements/MUCOccupant.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include "Swiften/Base/String.h" +#include "Swiften/JID/JID.h" + +namespace Swift { + class Client; + + class MUCOccupant { + public: + enum Role {Moderator, Participant, Visitor, NoRole}; + enum Affiliation {Owner, Admin, Member, Outcast, NoAffiliation}; + + MUCOccupant(const String &nick, Role role, Affiliation affiliation); + MUCOccupant(const MUCOccupant& other); + ~MUCOccupant(); + + String getNick() const; + Role getRole() const; + Affiliation getAffiliation() const; + boost::optional getRealJID() const; + void setRealJID(const JID& jid); + void setNick(const String& nick); + + private: + String nick_; + Role role_; + Affiliation affiliation_; + boost::optional realJID_; + /* If you add a field, remember to update the const copy constructor */ + }; +} + diff --git a/Swiften/Elements/MUCUserPayload.h b/Swiften/Elements/MUCUserPayload.h index f55c779..2014bc4 100644 --- a/Swiften/Elements/MUCUserPayload.h +++ b/Swiften/Elements/MUCUserPayload.h @@ -12,7 +12,7 @@ #include "Swiften/JID/JID.h" #include "Swiften/Base/String.h" #include "Swiften/Elements/Payload.h" -#include "Swiften/MUC/MUCOccupant.h" +#include "Swiften/Elements/MUCOccupant.h" namespace Swift { class MUCUserPayload : public Payload { @@ -20,7 +20,7 @@ namespace Swift { typedef boost::shared_ptr ref; struct Item { - Item() : affiliation(MUCOccupant::NoAffiliation), role(MUCOccupant::NoRole) {} + Item(MUCOccupant::Affiliation affiliation = MUCOccupant::NoAffiliation, MUCOccupant::Role role = MUCOccupant::NoRole) : affiliation(affiliation), role(role) {} boost::optional realJID; boost::optional nick; MUCOccupant::Affiliation affiliation; diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index 309107c..15a9a4f 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -43,6 +43,7 @@ void MUC::internalJoin(const String &nick) { mucRegistry->addMUC(getJID()); joinComplete_ = false; ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); boost::shared_ptr joinPresence(presenceSender->getLastSentUndirectedPresence()); assert(joinPresence->getType() == Presence::Available); joinPresence->setTo(ownMUCJID); @@ -93,6 +94,7 @@ void MUC::handleIncomingPresence(boost::shared_ptr presence) { if (!joinComplete_) { if (presence->getType() == Presence::Error) { String reason; + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); onJoinFailed(presence->getPayload()); return; } @@ -156,15 +158,18 @@ void MUC::handleIncomingPresence(boost::shared_ptr presence) { if (status.code == 110) { /* Simply knowing this is your presence is enough, 210 doesn't seem to be necessary. */ joinComplete_ = true; + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); ownMUCJID = presence->getFrom(); - onJoinComplete(getOwnNick()); presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + onJoinComplete(getOwnNick()); } if (status.code == 201) { /* Room is created and locked */ /* Currently deal with this by making an instant room */ + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); ownMUCJID = presence->getFrom(); boost::shared_ptr mucPayload(new MUCOwnerPayload()); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); mucPayload->setPayload(boost::shared_ptr(new Form(Form::SubmitType))); GenericRequest* request = new GenericRequest(IQ::Set, getJID(), mucPayload, iqRouter_); request->onResponse.connect(boost::bind(&MUC::handleCreationConfigResponse, this, _1, _2)); @@ -177,10 +182,10 @@ void MUC::handleIncomingPresence(boost::shared_ptr presence) { void MUC::handleCreationConfigResponse(boost::shared_ptr /*unused*/, ErrorPayload::ref error) { if (error) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); onJoinFailed(error); } else { onJoinComplete(getOwnNick()); /* Previously, this wasn't needed here, as the presence duplication bug caused an emit elsewhere. */ - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); } } diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index 56cd392..44759d5 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -10,7 +10,7 @@ #include "Swiften/Base/String.h" #include "Swiften/Elements/Message.h" #include "Swiften/Elements/Presence.h" -#include "Swiften/MUC/MUCOccupant.h" +#include "Swiften/Elements/MUCOccupant.h" #include "Swiften/MUC/MUCRegistry.h" #include "Swiften/Elements/MUCOwnerPayload.h" diff --git a/Swiften/MUC/MUCOccupant.cpp b/Swiften/MUC/MUCOccupant.cpp deleted file mode 100644 index 33a5fcc..0000000 --- a/Swiften/MUC/MUCOccupant.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/MUC/MUCOccupant.h" - -namespace Swift { - -MUCOccupant::MUCOccupant(const String &nick, Role role, Affiliation affiliation) : nick_(nick), role_(role), affiliation_(affiliation) { -} - -MUCOccupant::~MUCOccupant() { -} - -MUCOccupant::MUCOccupant(const MUCOccupant& other) : nick_(other.getNick()), role_(other.getRole()), affiliation_(other.getAffiliation()), realJID_(other.getRealJID()) { - -} - -String MUCOccupant::getNick() const { - return nick_; -} - -MUCOccupant::Role MUCOccupant::getRole() const { - return role_; -} - -MUCOccupant::Affiliation MUCOccupant::getAffiliation() const { - return affiliation_; -} - -void MUCOccupant::setRealJID(const JID& realJID) { - realJID_ = realJID; -} - -void MUCOccupant::setNick(const String& nick) { - nick_ = nick; -} - - -boost::optional MUCOccupant::getRealJID() const { - return realJID_; -} - -} diff --git a/Swiften/MUC/MUCOccupant.h b/Swiften/MUC/MUCOccupant.h deleted file mode 100644 index 96ac5ad..0000000 --- a/Swiften/MUC/MUCOccupant.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include - -#include "Swiften/Base/String.h" -#include "Swiften/JID/JID.h" - -namespace Swift { - class Client; - - class MUCOccupant { - public: - enum Role {Moderator, Participant, Visitor, NoRole}; - enum Affiliation {Owner, Admin, Member, Outcast, NoAffiliation}; - - MUCOccupant(const String &nick, Role role, Affiliation affiliation); - MUCOccupant(const MUCOccupant& other); - ~MUCOccupant(); - - String getNick() const; - Role getRole() const; - Affiliation getAffiliation() const; - boost::optional getRealJID() const; - void setRealJID(const JID& jid); - void setNick(const String& nick); - - private: - String nick_; - Role role_; - Affiliation affiliation_; - boost::optional realJID_; - /* If you add a field, remember to update the const copy constructor */ - }; -} - diff --git a/Swiften/MUC/UnitTest/MUCTest.cpp b/Swiften/MUC/UnitTest/MUCTest.cpp new file mode 100644 index 0000000..1e3582b --- /dev/null +++ b/Swiften/MUC/UnitTest/MUCTest.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace Swift; + +class MUCTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(MUCTest); + CPPUNIT_TEST(testJoin); + CPPUNIT_TEST(testJoin_ChangePresenceDuringJoin); + /*CPPUNIT_TEST(testJoin_Success); + CPPUNIT_TEST(testJoin_Fail);*/ + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel = new DummyStanzaChannel(); + router = new IQRouter(channel); + mucRegistry = new MUCRegistry(); + stanzaChannelPresenceSender = new StanzaChannelPresenceSender(channel); + presenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); + } + + void tearDown() { + delete presenceSender; + delete stanzaChannelPresenceSender; + delete mucRegistry; + delete router; + delete channel; + } + + void testJoin() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + CPPUNIT_ASSERT(mucRegistry->isMUC(JID("foo@bar.com"))); + Presence::ref p = channel->getStanzaAtIndex(0); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + } + + void testJoin_ChangePresenceDuringJoin() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + presenceSender->sendPresence(Presence::create("Test")); + CPPUNIT_ASSERT_EQUAL(3, static_cast(channel->sentStanzas.size())); + Presence::ref p = channel->getStanzaAtIndex(2); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + } + + /*void testJoin_Success() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->onJoinFinished.connect(boost::bind(&MUCTest::handleJoinFinished, this, _1, _2)); + testling->joinAs("Alice"); + receivePresence(JID("foo@bar.com/Rabbit"), "Here"); + + CPPUNIT_ASSERT_EQUAL(1, static_cast(joinResults.size())); + CPPUNIT_ASSERT_EQUAL(String("Alice"), joinResults[0].nick); + CPPUNIT_ASSERT(joinResults[0].error); + } + + void testJoin_Fail() { + //CPPUNIT_ASSERT(!mucRegistry->isMUC(JID("foo@bar.com"))); + }*/ + + private: + MUC::ref createMUC(const JID& jid) { + return boost::make_shared(channel, router, presenceSender, jid, mucRegistry); + } + + void handleJoinFinished(const String& nick, ErrorPayload::ref error) { + JoinResult r; + r.nick = nick; + r.error = error; + joinResults.push_back(r); + } + + /*void receivePresence(const JID& jid, const String& status, const MUCUserPayload::Item& item) { + Presence::ref p = Presence::create(status); + p->setFrom(jid); + MUCUserPayload::ref mucUserPayload = boost::make_shared(); + mucUserPayload->addItem(item); + p->addPayload(mucUserPayload); + channel->onPresenceReceived(p); + }*/ + + private: + DummyStanzaChannel* channel; + IQRouter* router; + MUCRegistry* mucRegistry; + StanzaChannelPresenceSender* stanzaChannelPresenceSender; + DirectedPresenceSender* presenceSender; + struct JoinResult { + String nick; + ErrorPayload::ref error; + }; + std::vector joinResults; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MUCTest); diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp index 5bb0e68..65417a7 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp @@ -8,7 +8,7 @@ #include -#include "Swiften/MUC/MUCOccupant.h" +#include "Swiften/Elements/MUCOccupant.h" #include #include diff --git a/Swiften/SConscript b/Swiften/SConscript index a9b6f41..8474610 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -62,10 +62,10 @@ if env["SCONS_STAGE"] == "build" : "Elements/RosterPayload.cpp", "Elements/Stanza.cpp", "Elements/VCard.cpp", + "Elements/MUCOccupant.cpp", "Entity/Entity.cpp", "MUC/MUC.cpp", "MUC/MUCManager.cpp", - "MUC/MUCOccupant.cpp", "MUC/MUCRegistry.cpp", "MUC/MUCBookmarkManager.cpp", "Queries/IQChannel.cpp", @@ -207,6 +207,7 @@ if env["SCONS_STAGE"] == "build" : File("LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp"), File("LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp"), File("LinkLocal/UnitTest/LinkLocalServiceTest.cpp"), + File("MUC/UnitTest/MUCTest.cpp"), File("Network/UnitTest/HostAddressTest.cpp"), File("Network/UnitTest/ConnectorTest.cpp"), File("Parser/PayloadParsers/UnitTest/BodyParserTest.cpp"), -- cgit v0.10.2-6-g49f6