Fixed leaving the room even when its name doesn't start with '#'

This commit is contained in:
HanzZ 2013-01-25 08:05:46 +01:00
parent 34ebe699b3
commit 1b49b0cf36
7 changed files with 97 additions and 87 deletions

View file

@ -137,6 +137,7 @@ class UserManager : public Swift::EntityCapsProvider {
void handleProbePresence(Swift::Presence::ref presence);
void handleErrorPresence(Swift::Presence::ref presence);
void handleSubscription(Swift::Presence::ref presence);
void handleMUCPresence(Swift::Presence::ref presence);
void handleRemoveTimeout(const std::string jid, User *user, bool reconnect);
void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
void addUser(User *user);

View file

@ -52,9 +52,8 @@ void PresenceOracle::clearPresences(const Swift::JID& bareJID) {
void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
// ignore presences for some contact, we're checking only presences for the transport itself here.
bool isMUC = presence->getPayload<MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
// filter out login/logout presence spam
if (!presence->getTo().getNode().empty() && isMUC == false)
if (!presence->getTo().getNode().empty())
return;
JID bareJID(presence->getFrom().toBare());
@ -62,29 +61,27 @@ void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
}
else {
Presence::ref passedPresence = presence;
if (!isMUC) {
if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) {
/* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */
passedPresence = Presence::ref(new Presence());
passedPresence->setType(Presence::Unavailable);
passedPresence->setFrom(bareJID);
passedPresence->setStatus(presence->getStatus());
}
std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID];
if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) {
/* Have a bare-JID only presence of offline */
jidMap.clear();
} else if (passedPresence->getType() == Presence::Available) {
/* Don't have a bare-JID only offline presence once there are available presences */
jidMap.erase(bareJID);
}
if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) {
jidMap.erase(passedPresence->getFrom());
} else {
jidMap[passedPresence->getFrom()] = passedPresence;
}
entries_[bareJID] = jidMap;
if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) {
/* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */
passedPresence = Presence::ref(new Presence());
passedPresence->setType(Presence::Unavailable);
passedPresence->setFrom(bareJID);
passedPresence->setStatus(presence->getStatus());
}
std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID];
if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) {
/* Have a bare-JID only presence of offline */
jidMap.clear();
} else if (passedPresence->getType() == Presence::Available) {
/* Don't have a bare-JID only offline presence once there are available presences */
jidMap.erase(bareJID);
}
if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) {
jidMap.erase(passedPresence->getFrom());
} else {
jidMap[passedPresence->getFrom()] = passedPresence;
}
entries_[bareJID] = jidMap;
onPresenceChange(passedPresence);
}
}

View file

@ -345,17 +345,17 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
injectPresence(response);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(4, (int) received.size());
CPPUNIT_ASSERT_EQUAL(3, (int) received.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[1])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getFrom().toString());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[2])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getFrom().toString());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[3])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getFrom().toString());
}
void handleGroupchatMessagesBouncerLeave() {
@ -410,17 +410,17 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
injectPresence(response);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(4, (int) received.size());
CPPUNIT_ASSERT_EQUAL(3, (int) received.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[1])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[1]))->getFrom().toString());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[2])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[2]))->getFrom().toString());
CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received[3])));
CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getBody());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received[3]))->getFrom().toString());
}
void handleGroupchatMessagesTwoResources() {

View file

@ -125,7 +125,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
User *user = userManager->getUser("user@localhost");
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
Swift::MUCPayload *payload = new Swift::MUCPayload();
@ -134,11 +134,8 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
injectPresence(response);
loop->processEvents();
// no presence received in server mode, just disco#info
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
@ -147,7 +144,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
roomPassword = "";
// simulate that backend joined the room
TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
TestingConversation *conv = new TestingConversation(user->getConversationManager(), "room", true);
conv->addJID("user@localhost/resource");
user->getConversationManager()->addConversation(conv);
@ -156,8 +153,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
loop->processEvents();
// no presence received in server mode, just disco#info
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string(""), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
@ -169,14 +165,14 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
User *user = userManager->getUser("user@localhost");
// Add 1 participant
Conversation *conv = user->getConversationManager()->getConversation("#room");
Conversation *conv = user->getConversationManager()->getConversation("room");
conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_NONE, Swift::StatusShow::Away, "my status message");
// Connect 2nd resource
connectSecondResource();
received2.clear();
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource2");
Swift::MUCPayload *payload = new Swift::MUCPayload();
@ -189,19 +185,19 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
CPPUNIT_ASSERT_EQUAL(2, (int) received2.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received2[1])));
CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received2[1]))->getShow());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast<Swift::Presence *>(getStanza(received2[1]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Presence *>(getStanza(received2[1]))->getFrom().toString());
CPPUNIT_ASSERT(getStanza(received2[1])->getPayload<Swift::MUCUserPayload>());
CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[1])->getPayload<Swift::MUCUserPayload>()->getItems()[0].affiliation);
CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[1])->getPayload<Swift::MUCUserPayload>()->getItems()[0].role);
CPPUNIT_ASSERT_EQUAL(1, (int) received2.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received2[0])));
CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received2[0]))->getShow());
CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast<Swift::Presence *>(getStanza(received2[0]))->getTo().toString());
CPPUNIT_ASSERT_EQUAL(std::string("room@localhost/anotheruser"), dynamic_cast<Swift::Presence *>(getStanza(received2[0]))->getFrom().toString());
CPPUNIT_ASSERT(getStanza(received2[0])->getPayload<Swift::MUCUserPayload>());
CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[0])->getPayload<Swift::MUCUserPayload>()->getItems()[0].affiliation);
CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[0])->getPayload<Swift::MUCUserPayload>()->getItems()[0].role);
}
void handlePresenceLeaveRoom() {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
response->setType(Swift::Presence::Unavailable);
@ -213,7 +209,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
@ -224,7 +220,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
// User is still connected from resource2, so he should not leave the room
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
response->setType(Swift::Presence::Unavailable);
@ -243,7 +239,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
// disconnect also from resource
// User is still connected from resource2, so he should not leave the room
response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource2");
response->setType(Swift::Presence::Unavailable);
@ -255,7 +251,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
@ -278,7 +274,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
Conversation *conv = user->getConversationManager()->getConversation("#room");
Conversation *conv = user->getConversationManager()->getConversation("room");
CPPUNIT_ASSERT_EQUAL(1, (int) conv->getJIDs().size());
CPPUNIT_ASSERT_EQUAL(Swift::JID("user@localhost/resource2"), conv->getJIDs().front());
}
@ -287,7 +283,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
User *user = userManager->getUser("user@localhost");
user->addUserSetting("stay_connected", "1");
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
response->setType(Swift::Presence::Unavailable);
@ -312,7 +308,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
// User is still connected from resource2, so he should not leave the room
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
response->setType(Swift::Presence::Unavailable);
@ -332,7 +328,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
// disconnect also from resource
// User is still connected from resource2, so he should not leave the room
response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource2");
response->setType(Swift::Presence::Unavailable);
@ -368,7 +364,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
Conversation *conv = user->getConversationManager()->getConversation("#room");
Conversation *conv = user->getConversationManager()->getConversation("room");
CPPUNIT_ASSERT_EQUAL(1, (int) conv->getJIDs().size());
CPPUNIT_ASSERT_EQUAL(Swift::JID("user@localhost/resource2"), conv->getJIDs().front());
}
@ -377,12 +373,12 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
User *user = userManager->getUser("user@localhost");
handlePresenceJoinRoom();
CPPUNIT_ASSERT(user->getConversationManager()->getConversation("#room"));
CPPUNIT_ASSERT(user->getConversationManager()->getConversation("room"));
received.clear();
handlePresenceLeaveRoom();
CPPUNIT_ASSERT(!user->getConversationManager()->getConversation("#room"));
CPPUNIT_ASSERT(!user->getConversationManager()->getConversation("room"));
}
void handleDisconnected() {
@ -427,7 +423,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
user->setConnected(false);
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setTo("room@localhost/hanzz");
response->setFrom("user@localhost/resource");
Swift::MUCPayload *payload = new Swift::MUCPayload();
@ -436,16 +432,13 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
injectPresence(response);
loop->processEvents();
// no presence received in server mode, just disco#info
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string(""), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
user->setConnected(true);
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
}
@ -460,7 +453,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
received.clear();
user->setConnected(true);
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());

View file

@ -275,9 +275,8 @@ void Component::handleDataWritten(const Swift::SafeByteArray &data) {
}
void Component::handlePresence(Swift::Presence::ref presence) {
bool isMUC = presence->getPayload<MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
// filter out login/logout presence spam
if (!presence->getTo().getNode().empty() && isMUC == false)
if (!presence->getTo().getNode().empty())
return;
// filter out bad presences

View file

@ -194,11 +194,6 @@ void User::setCacheMessages(bool cacheMessages) {
}
void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
m_conversationManager->resetResources();
LOG4CXX_INFO(logger, "PRESENCE " << presence->getFrom().toString() << " " << presence->getTo().toString());
if (!m_connected) {
// we are not connected to legacy network, so we should do it when disco#info arrive :)
@ -230,8 +225,9 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
}
}
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
if (isMUC) {
if (!presence->getTo().getNode().empty()) {
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
if (presence->getType() == Swift::Presence::Unavailable) {
std::string room = Buddy::JIDToLegacyName(presence->getTo());
Conversation *conv = m_conversationManager->getConversation(room);
@ -259,7 +255,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
}
}
}
else {
else if (isMUC) {
// force connection to legacy network to let backend to handle auto-join on connect.
if (!m_readyForConnect) {
LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
@ -316,7 +312,12 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
}
return;
}
int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
m_conversationManager->resetResources();
if (presence->getType() == Swift::Presence::Unavailable) {
m_conversationManager->removeJID(presence->getFrom());

View file

@ -400,6 +400,7 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
break;
case Swift::Presence::Available:
case Swift::Presence::Unavailable:
handleMUCPresence(presence);
break;
case Swift::Presence::Probe:
handleProbePresence(presence);
@ -412,6 +413,24 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
};
}
void UserManager::handleMUCPresence(Swift::Presence::ref presence) {
// Don't let RosterManager to handle presences for us
if (presence->getTo().getNode().empty()) {
return;
}
if (presence->getType() == Swift::Presence::Available) {
handlePresence(presence);
}
else if (presence->getType() == Swift::Presence::Unavailable) {
std::string userkey = presence->getFrom().toBare().toString();
User *user = getUser(userkey);
if (user) {
user->handlePresence(presence);
}
}
}
void UserManager::handleProbePresence(Swift::Presence::ref presence) {
// Don't let RosterManager to handle presences for us
if (presence->getTo().getNode().empty()) {