Changeset - 1055c577d2d3
[Not reviewed]
0 5 0
HanzZ - 13 years ago 2012-09-23 09:48:03
hanzz.k@gmail.com
Send participants to second resource when it joins the room
5 files changed with 127 insertions and 2 deletions:
0 comments (0 inline, 0 general)
include/transport/conversation.h
Show inline comments
 
@@ -31,12 +31,18 @@ namespace Transport {
 

	
 
class ConversationManager;
 

	
 
/// Represents one XMPP-Legacy network conversation.
 
class Conversation {
 
	public:
 
		typedef struct _Participant {
 
			int flag;
 
			int status;
 
			std::string statusMessage;
 
		} Participant;
 

	
 
		/// Type of participants in MUC rooms.
 
		enum ParticipantFlag {None, Moderator};
 

	
 
		/// Creates new conversation.
 

	
 
		/// \param conversationManager ConversationManager associated with this Conversation.
 
@@ -125,17 +131,23 @@ class Conversation {
 
		const std::string &getRoom() {
 
			return m_room;
 
		}
 

	
 
		void destroyRoom();
 

	
 
		void sendParticipants(const Swift::JID &to);
 

	
 
	private:
 
		Swift::Presence::ref generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname = "");
 

	
 
	private:
 
		ConversationManager *m_conversationManager;
 
		std::string m_legacyName;
 
		std::string m_nickname;
 
		std::string m_room;
 
		bool m_muc;
 
		Swift::JID m_jid;
 
		std::list<Swift::JID> m_jids;
 
		std::map<std::string, Participant> m_participants;
 
};
 

	
 
}
src/conversation.cpp
Show inline comments
 
@@ -120,13 +120,21 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
 
			message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
			m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
		}
 
	}
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) {
 
void Conversation::sendParticipants(const Swift::JID &to) {
 
	for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		Swift::Presence::ref presence = generatePresence(it->first, it->second.flag, it->second.status, it->second.statusMessage, "");
 
		presence->setTo(to);
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
	}
 
}
 

	
 
Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) {
 
	std::string nickname = nick;
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	std::string legacyName = m_legacyName;
 
	if (m_muc) {
 
		if (legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
@@ -170,14 +178,31 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
 
		c.code = 303;
 
		p->addStatusCode(c);
 
		presence->setType(Swift::Presence::Unavailable);
 
	}
 

	
 
	p->addItem(item);
 

	
 
	presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
	return presence;
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) {
 
	Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname);
 

	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
 
		m_participants.erase(nick);
 
	}
 
	else {
 
		Participant p;
 
		p.flag = flag;
 
		p.status = status;
 
		p.statusMessage = statusMessage;
 
		m_participants[nick] = p;
 
	}
 

	
 

	
 
	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);
src/tests/conversationmanager.cpp
Show inline comments
 
@@ -22,14 +22,16 @@
 
using namespace Transport;
 

	
 
class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(ConversationManagerTest);
 
	CPPUNIT_TEST(handleNormalMessages);
 
	CPPUNIT_TEST(handleGroupchatMessages);
 
	CPPUNIT_TEST(handleGroupchatMessagesTwoResources);
 
	CPPUNIT_TEST(handleChatstateMessages);
 
	CPPUNIT_TEST(handleParticipantChanged);
 
	CPPUNIT_TEST(handleParticipantChangedTwoResources);
 
	CPPUNIT_TEST(handlePMFromXMPP);
 
	CPPUNIT_TEST(handleGroupchatRemoved);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		TestingConversation *m_conv;
 
@@ -188,12 +190,54 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 
		
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
		CPPUNIT_ASSERT(m_msg);
 
		CPPUNIT_ASSERT_EQUAL(std::string("response!"), m_msg->getBody());
 
	}
 

	
 
	void handleGroupchatMessagesTwoResources() {
 
		connectSecondResource();
 
		received2.clear();
 
		User *user = userManager->getUser("user@localhost");
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 
		conv->setNickname("nickname");
 
		conv->addJID("user@localhost/resource");
 
		conv->addJID("user@localhost/resource2");
 

	
 
		// reset resources should not touch this resource
 
		user->getConversationManager()->resetResources();
 

	
 
		boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
		msg->setBody("hi there!");
 

	
 
		// Forward it
 
		conv->handleMessage(msg, "anotheruser");
 

	
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received2.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Message *>(getStanza(received2[0])));
 
		CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast<Swift::Message *>(getStanza(received2[0]))->getBody());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast<Swift::Message *>(getStanza(received2[0]))->getTo().toString());
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast<Swift::Message *>(getStanza(received2[0]))->getFrom().toString());
 

	
 
		received.clear();
 

	
 
		// send response
 
		msg->setFrom("user@localhost/resource2");
 
		msg->setTo("#room@localhost");
 
		msg->setBody("response!");
 
		msg->setType(Swift::Message::Groupchat);
 
		injectMessage(msg);
 
		loop->processEvents();
 
		
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
		CPPUNIT_ASSERT(m_msg);
 
		CPPUNIT_ASSERT_EQUAL(std::string("response!"), m_msg->getBody());
 
	}
 

	
 
	void handleParticipantChanged() {
 
		User *user = userManager->getUser("user@localhost");
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
 
		
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 
		conv->setNickname("nickname");
 
@@ -243,12 +287,37 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 
		CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Admin, *getStanza(received[0])->getPayload<Swift::MUCUserPayload>()->getItems()[0].affiliation);
 
		CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Moderator, *getStanza(received[0])->getPayload<Swift::MUCUserPayload>()->getItems()[0].role);
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), *getStanza(received[0])->getPayload<Swift::MUCUserPayload>()->getItems()[0].nick);
 
		CPPUNIT_ASSERT_EQUAL(303, getStanza(received[0])->getPayload<Swift::MUCUserPayload>()->getStatusCodes()[0].code);
 
	}
 

	
 
	void handleParticipantChangedTwoResources() {
 
		connectSecondResource();
 
		received2.clear();
 
		User *user = userManager->getUser("user@localhost");
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
 
		
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 
		conv->setNickname("nickname");
 
		conv->addJID("user@localhost/resource");
 
		conv->addJID("user@localhost/resource2");
 

	
 
		// normal presence
 
		conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message");
 
		loop->processEvents();
 

	
 
		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 handlePMFromXMPP() {
 
		User *user = userManager->getUser("user@localhost");
 
		TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true);
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2));
 
		conv->setNickname("nickname");
src/tests/user.cpp
Show inline comments
 
@@ -156,13 +156,21 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
 
	}
 

	
 
	void handlePresenceJoinRoomTwoResources() {
 
		handlePresenceJoinRoom();
 
		User *user = userManager->getUser("user@localhost");
 

	
 
		// Add 1 participant
 
		Conversation *conv = user->getConversationManager()->getConversation("#room");
 
		conv->handleParticipantChanged("anotheruser", 0, 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->setFrom("user@localhost/resource2");
 

	
 
		Swift::MUCPayload *payload = new Swift::MUCPayload();
 
		payload->setPassword("password");
 
@@ -170,12 +178,22 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		injectPresence(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), room);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword);
 

	
 
		dumpReceived();
 
		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);
 
	}
 

	
 
	void handlePresenceLeaveRoom() {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("#room@localhost/hanzz");
 
		response->setFrom("user@localhost/resource");
src/user.cpp
Show inline comments
 
@@ -246,12 +246,13 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
			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());
 
					conv->sendParticipants(presence->getFrom());
 
				}
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource());
 
			std::string password = "";
0 comments (0 inline, 0 general)