summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/MUC')
-rw-r--r--Swiften/MUC/MUC.cpp73
-rw-r--r--Swiften/MUC/MUC.h11
-rw-r--r--Swiften/MUC/UnitTest/MUCTest.cpp26
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;