Do not disconnect from room when user uses two clients and shutdown one.

This commit is contained in:
HanzZ 2012-09-22 20:19:19 +02:00
parent 2f542b5077
commit 88607aff3c
6 changed files with 104 additions and 11 deletions

View file

@ -82,6 +82,18 @@ class Conversation {
m_jid = jid;
}
void addJID(const Swift::JID &jid) {
m_jids.push_back(jid);
}
void removeJID(const Swift::JID &jid) {
m_jids.remove(jid);
}
const std::list<Swift::JID> &getJIDs() {
return m_jids;
}
/// Sends message to Legacy network.
/// \param message Message.
@ -123,6 +135,7 @@ class Conversation {
std::string m_room;
bool m_muc;
Swift::JID m_jid;
std::list<Swift::JID> m_jids;
};
}

View file

@ -115,9 +115,11 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
if (n.empty()) {
n = " ";
}
message->setTo(m_jid);
message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
BOOST_FOREACH(const Swift::JID &jid, m_jids) {
message->setTo(jid);
message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
}
}
}
@ -131,7 +133,6 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
}
}
presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
presence->setTo(m_jid);
presence->setType(Swift::Presence::Available);
if (!statusMessage.empty())
@ -174,7 +175,10 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
p->addItem(item);
presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
BOOST_FOREACH(const Swift::JID &jid, m_jids) {
presence->setTo(jid);
m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
}
if (!newname.empty()) {
handleParticipantChanged(newname, flag, status, statusMessage);
}

View file

@ -1192,7 +1192,7 @@ void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, co
user->getConversationManager()->addConversation(conv);
conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
conv->setNickname(nickname);
conv->setJID(who);
conv->addJID(who);
}
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {

View file

@ -158,7 +158,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
user->getConversationManager()->addConversation(conv);
conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
conv->setNickname("nickname");
conv->setJID("user@localhost/resource");
conv->addJID("user@localhost/resource");
// reset resources should not touch this resource
user->getConversationManager()->resetResources();
@ -197,7 +197,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
conv->setNickname("nickname");
conv->setJID("user@localhost/resource");
conv->addJID("user@localhost/resource");
// normal presence
conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message");

View file

@ -25,7 +25,9 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_TEST(sendCurrentPresence);
CPPUNIT_TEST(handlePresence);
CPPUNIT_TEST(handlePresenceJoinRoom);
CPPUNIT_TEST(handlePresenceJoinRoomTwoResources);
CPPUNIT_TEST(handlePresenceLeaveRoom);
CPPUNIT_TEST(handlePresenceLeaveRoomTwoResources);
CPPUNIT_TEST(leaveJoinedRoom);
CPPUNIT_TEST(handleDisconnected);
CPPUNIT_TEST(handleDisconnectedReconnect);
@ -139,6 +141,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
// simulate that backend joined the room
TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
conv->addJID("user@localhost/resource");
user->getConversationManager()->addConversation(conv);
received.clear();
@ -154,6 +157,24 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
void handlePresenceJoinRoomTwoResources() {
handlePresenceJoinRoom();
connectSecondResource();
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
response->setFrom("user@localhost/resource2");
Swift::MUCPayload *payload = new Swift::MUCPayload();
payload->setPassword("password");
response->addPayload(boost::shared_ptr<Swift::Payload>(payload));
injectPresence(response);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(std::string(""), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
void handlePresenceLeaveRoom() {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo("#room@localhost/hanzz");
@ -173,6 +194,48 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
void handlePresenceLeaveRoomTwoResources() {
handlePresenceJoinRoomTwoResources();
received.clear();
// 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->setFrom("user@localhost/resource");
response->setType(Swift::Presence::Unavailable);
Swift::MUCPayload *payload = new Swift::MUCPayload();
payload->setPassword("password");
response->addPayload(boost::shared_ptr<Swift::Payload>(payload));
injectPresence(response);
loop->processEvents();
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);
// 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->setFrom("user@localhost/resource2");
response->setType(Swift::Presence::Unavailable);
payload = new Swift::MUCPayload();
payload->setPassword("password");
response->addPayload(boost::shared_ptr<Swift::Payload>(payload));
injectPresence(response);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
CPPUNIT_ASSERT_EQUAL(std::string("#room"), room);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
}
void leaveJoinedRoom() {
User *user = userManager->getUser("user@localhost");
handlePresenceJoinRoom();

View file

@ -218,10 +218,17 @@ void User::handlePresence(Swift::Presence::ref presence) {
if (isMUC) {
if (presence->getType() == Swift::Presence::Unavailable) {
std::string room = Buddy::JIDToLegacyName(presence->getTo());
Conversation *conv = m_conversationManager->getConversation(room);
if (conv) {
conv->removeJID(presence->getFrom());
if (!conv->getJIDs().empty()) {
return;
}
}
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room);
onRoomLeft(room);
Conversation *conv = m_conversationManager->getConversation(room);
if (conv) {
m_conversationManager->removeConversation(conv);
delete conv;
@ -235,8 +242,14 @@ void User::handlePresence(Swift::Presence::ref presence) {
onReadyToConnect();
}
std::string room = Buddy::JIDToLegacyName(presence->getTo());
if (m_conversationManager->getConversation(room) != NULL) {
LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource());
Conversation *conv = m_conversationManager->getConversation(room);
if (conv != NULL) {
if (std::find(conv->getJIDs().begin(), conv->getJIDs().end(), presence->getFrom()) != conv->getJIDs().end()) {
LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource());
}
else {
conv->addJID(presence->getFrom());
}
return;
}