diff options
Diffstat (limited to 'Swiften/MUC')
-rw-r--r-- | Swiften/MUC/MUC.cpp | 73 | ||||
-rw-r--r-- | Swiften/MUC/MUC.h | 11 | ||||
-rw-r--r-- | Swiften/MUC/UnitTest/MUCTest.cpp | 26 |
3 files changed, 71 insertions, 39 deletions
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index 15a9a4f..486ba27 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -8,6 +8,7 @@ #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> #include "Swiften/Presence/DirectedPresenceSender.h" #include "Swiften/Client/StanzaChannel.h" @@ -37,30 +38,34 @@ void MUC::joinAs(const String &nick) { internalJoin(nick); } +/** + * Join the MUC with context since date. + */ +void MUC::joinWithContextSince(const String &nick, const boost::posix_time::ptime& since) { + joinSince_ = since; + internalJoin(nick); +} + void MUC::internalJoin(const String &nick) { //TODO: password //TODO: history request - mucRegistry->addMUC(getJID()); joinComplete_ = false; + joinSucceeded_ = false; + + mucRegistry->addMUC(getJID()); + ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick); - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); - boost::shared_ptr<Presence> joinPresence(presenceSender->getLastSentUndirectedPresence()); + + Presence::ref joinPresence = boost::make_shared<Presence>(*presenceSender->getLastSentUndirectedPresence()); assert(joinPresence->getType() == Presence::Available); joinPresence->setTo(ownMUCJID); - boost::shared_ptr<MUCPayload> mucPayload(new MUCPayload()); + MUCPayload::ref mucPayload = boost::make_shared<MUCPayload>(); if (joinSince_ != boost::posix_time::not_a_date_time) { mucPayload->setSince(joinSince_); } joinPresence->addPayload(mucPayload); - presenceSender->sendPresence(joinPresence); -} -/** - * Join the MUC with context since date. - */ -void MUC::joinWithContextSince(const String &nick, const boost::posix_time::ptime& since) { - joinSince_ = since; - internalJoin(nick); + presenceSender->sendPresence(joinPresence); } void MUC::part() { @@ -77,27 +82,34 @@ void MUC::handleUserLeft(LeavingType type) { } occupants.clear(); joinComplete_ = false; + joinSucceeded_ = false; presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); } -void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) { +void MUC::handleIncomingPresence(Presence::ref presence) { if (!isFromMUC(presence->getFrom())) { return; } - boost::shared_ptr<MUCUserPayload> mucPayload; - foreach (boost::shared_ptr<MUCUserPayload> payload, presence->getPayloads<MUCUserPayload>()) { + + MUCUserPayload::ref mucPayload; + foreach (MUCUserPayload::ref payload, presence->getPayloads<MUCUserPayload>()) { if (payload->getItems().size() > 0 || payload->getStatusCodes().size() > 0) { mucPayload = payload; } } - if (!joinComplete_) { + // On the first incoming presence, check if our join has succeeded + // (i.e. we start getting non-error presence from the MUC) or not + if (!joinSucceeded_) { if (presence->getType() == Presence::Error) { String reason; - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); onJoinFailed(presence->getPayload<ErrorPayload>()); return; } + else { + joinSucceeded_ = true; + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + } } String nick = presence->getFrom().getResource(); @@ -121,7 +133,8 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) { if (presence->getFrom() == ownMUCJID) { handleUserLeft(Part); return; - } else { + } + else { std::map<String,MUCOccupant>::iterator i = occupants.find(nick); if (i != occupants.end()) { //TODO: part type @@ -129,7 +142,8 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) { occupants.erase(i); } } - } else if (presence->getType() == Presence::Available) { + } + else if (presence->getType() == Presence::Available) { std::map<String, MUCOccupant>::iterator it = occupants.find(nick); MUCOccupant occupant(nick, role, affiliation); bool isJoin = true; @@ -158,19 +172,24 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> 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(); - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + if (ownMUCJID != presence->getFrom()) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + ownMUCJID = presence->getFrom(); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + } 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<MUCOwnerPayload> mucPayload(new MUCOwnerPayload()); + if (ownMUCJID != presence->getFrom()) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + ownMUCJID = presence->getFrom(); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + } + MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); - mucPayload->setPayload(boost::shared_ptr<Payload>(new Form(Form::SubmitType))); + mucPayload->setPayload(boost::make_shared<Form>(Form::SubmitType)); GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); request->onResponse.connect(boost::bind(&MUC::handleCreationConfigResponse, this, _1, _2)); request->send(); @@ -180,7 +199,7 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) { } -void MUC::handleCreationConfigResponse(boost::shared_ptr<MUCOwnerPayload> /*unused*/, ErrorPayload::ref error) { +void MUC::handleCreationConfigResponse(MUCOwnerPayload::ref /*unused*/, ErrorPayload::ref error) { if (error) { presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); onJoinFailed(error); diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index 44759d5..cdef292 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -48,14 +48,14 @@ namespace Swift { /*void queryRoomItems(); */ String getCurrentNick(); void part(); - void handleIncomingMessage(boost::shared_ptr<Message> message); + void handleIncomingMessage(Message::ref message); /** Expose public so it can be called when e.g. user goes offline */ void handleUserLeft(LeavingType); public: boost::signal<void (const String& /*nick*/)> onJoinComplete; - boost::signal<void (boost::shared_ptr<ErrorPayload>)> onJoinFailed; - boost::signal<void (boost::shared_ptr<Presence>)> onOccupantPresenceChange; + boost::signal<void (ErrorPayload::ref)> onJoinFailed; + boost::signal<void (Presence::ref)> onOccupantPresenceChange; boost::signal<void (const String&, const MUCOccupant& /*now*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged; boost::signal<void (const String&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged; boost::signal<void (const MUCOccupant&)> onOccupantJoined; @@ -74,9 +74,9 @@ namespace Swift { } private: - void handleIncomingPresence(boost::shared_ptr<Presence> presence); + void handleIncomingPresence(Presence::ref presence); void internalJoin(const String& nick); - void handleCreationConfigResponse(boost::shared_ptr<MUCOwnerPayload>, ErrorPayload::ref); + void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref); private: JID ownMUCJID; @@ -85,6 +85,7 @@ namespace Swift { DirectedPresenceSender* presenceSender; MUCRegistry* mucRegistry; std::map<String, MUCOccupant> occupants; + bool joinSucceeded_; bool joinComplete_; boost::bsignals::scoped_connection scopedConnection_; boost::posix_time::ptime joinSince_; diff --git a/Swiften/MUC/UnitTest/MUCTest.cpp b/Swiften/MUC/UnitTest/MUCTest.cpp index 1e3582b..fd07711 100644 --- a/Swiften/MUC/UnitTest/MUCTest.cpp +++ b/Swiften/MUC/UnitTest/MUCTest.cpp @@ -21,7 +21,8 @@ using namespace Swift; class MUCTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MUCTest); CPPUNIT_TEST(testJoin); - CPPUNIT_TEST(testJoin_ChangePresenceDuringJoin); + CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess); + CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess); /*CPPUNIT_TEST(testJoin_Success); CPPUNIT_TEST(testJoin_Fail);*/ CPPUNIT_TEST_SUITE_END(); @@ -53,15 +54,26 @@ class MUCTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); } - void testJoin_ChangePresenceDuringJoin() { + void testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess() { MUC::ref testling = createMUC(JID("foo@bar.com")); testling->joinAs("Alice"); presenceSender->sendPresence(Presence::create("Test")); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); + } + + void testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + presenceSender->sendPresence(Presence::create("Test")); + receivePresence(JID("foo@bar.com/Rabbit"), "Here"); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(channel->sentStanzas.size())); Presence::ref p = channel->getStanzaAtIndex<Presence>(2); CPPUNIT_ASSERT(p); CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + CPPUNIT_ASSERT_EQUAL(String("Test"), p->getStatus()); } /*void testJoin_Success() { @@ -91,14 +103,14 @@ class MUCTest : public CppUnit::TestFixture { joinResults.push_back(r); } - /*void receivePresence(const JID& jid, const String& status, const MUCUserPayload::Item& item) { + void receivePresence(const JID& jid, const String& status) { Presence::ref p = Presence::create(status); p->setFrom(jid); - MUCUserPayload::ref mucUserPayload = boost::make_shared<MUCUserPayload>(); - mucUserPayload->addItem(item); - p->addPayload(mucUserPayload); + //MUCUserPayload::ref mucUserPayload = boost::make_shared<MUCUserPayload>(); + //mucUserPayload->addItem(item); + //p->addPayload(mucUserPayload); channel->onPresenceReceived(p); - }*/ + } private: DummyStanzaChannel* channel; |