Changeset - 36b444536cb0
[Not reviewed]
0 7 0
Jan Kaluza - 10 years ago 2015-12-14 13:59:05
jkaluza@redhat.com
Fix regression when 'from' attribute has not been sent in some situations in server mode.
7 files changed with 19 insertions and 1 deletions:
0 comments (0 inline, 0 general)
include/Swiften/Server/Server.cpp
Show inline comments
 
@@ -27,49 +27,49 @@
 
#include "Swiften/Network/ConnectionFactory.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include <iostream>
 

	
 

	
 
namespace Swift {
 

	
 
Server::Server(
 
		EventLoop* eventLoop,
 
		NetworkFactories* networkFactories,
 
		UserRegistry *userRegistry,
 
		const JID& jid,
 
		const std::string &address,
 
		int port) :
 
			userRegistry_(userRegistry),
 
			port_(port),
 
			eventLoop(eventLoop),
 
			networkFactories_(networkFactories),
 
			stopping(false),
 
			selfJID(jid),
 
			stanzaChannel_(),
 
			address_(address){
 
	stanzaChannel_ = new ServerStanzaChannel();
 
	stanzaChannel_ = new ServerStanzaChannel(selfJID);
 
	iqRouter_ = new IQRouter(stanzaChannel_);
 
	tlsFactory = NULL;
 
	parserFactory_ = new PlatformXMLParserFactory();
 
}
 

	
 
Server::~Server() {
 
	stop();
 
	delete iqRouter_;
 
	delete stanzaChannel_;
 
	delete parserFactory_;
 
}
 

	
 
void Server::start() {
 
	if (serverFromClientConnectionServer) {
 
		return;
 
	}
 
	if (address_ == "0.0.0.0") {
 
		serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(port_);
 
	}
 
	else {
 
		serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(address_), port_);
 
	}
 
	serverFromClientConnectionServerSignalConnections.push_back(
 
		serverFromClientConnectionServer->onNewConnection.connect(
include/Swiften/Server/ServerStanzaChannel.cpp
Show inline comments
 
@@ -81,48 +81,52 @@ void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element
 

	
 
		if (last && (*i)->getRemoteJID().isValid()) {
 
			Swift::Presence::ref presence = Swift::Presence::create();
 
			presence->setFrom((*i)->getRemoteJID());
 
			presence->setType(Swift::Presence::Unavailable);
 
			onPresenceReceived(presence);
 
		}
 

	
 
		(*i)->finishSession();
 
// 		std::cout << "FINISH SESSION " << sessions[to.toBare().toString()].size() << "\n";
 
		if (last) {
 
			break;
 
		}
 
	}
 
}
 

	
 
std::string ServerStanzaChannel::getNewIQID() {
 
	return idGenerator.generateID();
 
}
 

	
 
void ServerStanzaChannel::send(boost::shared_ptr<Stanza> stanza) {
 
	JID to = stanza->getTo();
 
	assert(to.isValid());
 

	
 
	if (!stanza->getFrom().isValid()) {
 
		stanza->setFrom(m_jid);
 
	}
 

	
 
	// For a full JID, first try to route to a session with the full JID
 
	if (!to.isBare()) {
 
		std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = std::find_if(sessions[stanza->getTo().toBare().toString()].begin(), sessions[stanza->getTo().toBare().toString()].end(), HasJID(to));
 
		if (i != sessions[stanza->getTo().toBare().toString()].end()) {
 
			(*i)->sendElement(stanza);
 
			return;
 
		}
 
	}
 

	
 
	// Look for candidate sessions
 
	to = to.toBare();
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[stanza->getTo().toBare().toString()].begin(); i != sessions[stanza->getTo().toBare().toString()].end(); ++i) {
 
		if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
 
			candidateSessions.push_back(*i);
 
			(*i)->sendElement(stanza);
 
		}
 
	}
 
	if (candidateSessions.empty()) {
 
		return;
 
	}
 

	
 
	// Find the session with the highest priority
 
// 	std::vector<ServerSession*>::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan());
include/Swiften/Server/ServerStanzaChannel.h
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include "Swiften/Base/IDGenerator.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Client/StanzaChannel.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/TLS/Certificate.h"
 
#include <Swiften/Version.h>
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
namespace Swift {
 
	class Error;
 
	class ServerStanzaChannel : public StanzaChannel {
 
		public:
 
			ServerStanzaChannel(const JID &selfJID) : StanzaChannel() {
 
				m_jid = selfJID;
 
			}
 
			void addSession(boost::shared_ptr<ServerFromClientSession> session);
 
			void removeSession(boost::shared_ptr<ServerFromClientSession> session);
 

	
 
			void sendIQ(boost::shared_ptr<IQ> iq);
 
			void sendMessage(boost::shared_ptr<Message> message);
 
			void sendPresence(boost::shared_ptr<Presence> presence);
 
#if HAVE_SWIFTEN_3
 
			void finishSession(const JID& to, boost::shared_ptr<ToplevelElement> element, bool last = false);
 
#else
 
			void finishSession(const JID& to, boost::shared_ptr<Element> element, bool last = false);
 
#endif
 
			bool getStreamManagementEnabled() const {
 
				return false;
 
			}
 
	
 
			bool isAvailable() const {
 
				return true;
 
			}
 
			
 
			std::vector<Certificate::ref> getPeerCertificateChain() const {
 
				return std::vector<Certificate::ref>();
 
			}
 

	
 
		private:
 
			std::string getNewIQID();
 
			void send(boost::shared_ptr<Stanza> stanza);
 
			void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleSessionInitialized();
 

	
 
		private:
 
			JID m_jid;
 
			IDGenerator idGenerator;
 
			// [JID][resources][ServerFromClientSession]
 
			std::map<std::string, std::list<boost::shared_ptr<ServerFromClientSession> > > sessions;
 
	};
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserManager.cpp
Show inline comments
 
@@ -10,109 +10,114 @@
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "XMPPUserManager.h"
 
#include "XMPPUserRegistration.h"
 
#include "transport/User.h"
 
#include "transport/Transport.h"
 
#include "transport/StorageBackend.h"
 
#include "transport/Logging.h"
 
#include "transport/Frontend.h"
 
#include "storageresponder.h"
 
#include "vcardresponder.h"
 
#include "XMPPFrontend.h"
 
#include "gatewayresponder.h"
 
#include "adhocmanager.h"
 
#include "settingsadhoccommand.h"
 
#include "RosterResponder.h"
 

	
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/ChatState.h"
 
#ifndef __FreeBSD__ 
 
#ifndef __MACH__
 
#include "malloc.h"
 
#endif
 
#endif
 
// #include "valgrind/memcheck.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "XMPPUserManager");
 

	
 
XMPPUserManager::XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) : UserManager(component, userRegistry, storageBackend) {
 
	m_component = component;
 

	
 
	XMPPFrontend *frontend = static_cast<XMPPFrontend *>(component->getFrontend());
 
	if (storageBackend) {
 
		m_storageResponder = new StorageResponder(frontend->getIQRouter(), storageBackend, this);
 
		m_storageResponder->start();
 
	}
 

	
 
	m_vcardResponder = new VCardResponder(frontend->getIQRouter(), component->getNetworkFactories(), this);
 
	m_vcardResponder->onVCardRequired.connect(boost::bind(&XMPPUserManager::handleVCardRequired, this, _1, _2, _3));
 
	m_vcardResponder->onVCardUpdated.connect(boost::bind(&XMPPUserManager::handleVCardUpdated, this, _1, _2));
 
	m_vcardResponder->start();
 

	
 
	if (storageBackend) {
 
		m_userRegistration = new XMPPUserRegistration(component, this, storageBackend);
 
		m_userRegistration->start();
 
	}
 
	else {
 
		m_userRegistration = NULL;
 
	}
 

	
 
// 	StatsResponder statsResponder(component, this, &plugin, storageBackend);
 
// 	statsResponder.start();
 

	
 
	m_gatewayResponder = new GatewayResponder(frontend->getIQRouter(), this);
 
	m_gatewayResponder->start();
 

	
 
	m_rosterResponder = new RosterResponder(frontend->getIQRouter(), this);
 
	m_rosterResponder->start();
 

	
 
	m_adHocManager = new AdHocManager(component, frontend->getDiscoItemsResponder(), this, storageBackend);
 
	m_adHocManager->start();
 

	
 
	SettingsAdHocCommandFactory *m_settings = new SettingsAdHocCommandFactory();
 
	m_adHocManager->addAdHocCommand(m_settings);
 
}
 

	
 
XMPPUserManager::~XMPPUserManager() {
 
	if (m_storageResponder) {
 
		m_storageResponder->stop();
 
		delete m_storageResponder;
 
	}
 

	
 
	if (m_userRegistration) {
 
		m_userRegistration->stop();
 
		delete m_userRegistration;
 
	}
 

	
 
	delete m_gatewayResponder;
 
	delete m_adHocManager;
 
	delete m_settings;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
}
 

	
 
void XMPPUserManager::sendVCard(unsigned int id, Swift::VCard::ref vcard) {
 
	m_vcardResponder->sendVCard(id, vcard);
 
}
 

	
 
void XMPPUserManager::handleVCardRequired(User *user, const std::string &name, unsigned int id) {
 
	m_component->getFrontend()->onVCardRequired(user, name, id);
 
}
 

	
 
void XMPPUserManager::handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> vcard) {
 
	m_component->getFrontend()->onVCardUpdated(user, vcard);
 
}
 

	
 
UserRegistration *XMPPUserManager::getUserRegistration() {
 
	return m_userRegistration;
 
}
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserManager.h
Show inline comments
 
@@ -18,49 +18,51 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 
#include "transport/UserManager.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class StorageBackend;
 
class StorageResponder;
 
class VCardResponder;
 
class XMPPUserRegistration;
 
class GatewayResponder;
 
class AdHocManager;
 
class SettingsAdHocCommandFactory;
 
class RosterResponder;
 

	
 
class XMPPUserManager : public UserManager {
 
	public:
 
		XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL);
 

	
 
		virtual ~XMPPUserManager();
 

	
 
		virtual void sendVCard(unsigned int id, Swift::VCard::ref vcard);
 

	
 
		UserRegistration *getUserRegistration();
 

	
 
	private:
 
		void handleVCardRequired(User *, const std::string &name, unsigned int id);
 
		void handleVCardUpdated(User *, boost::shared_ptr<Swift::VCard> vcard);
 

	
 
		StorageResponder *m_storageResponder;
 
		VCardResponder *m_vcardResponder;
 
		Component *m_component;
 
		XMPPUserRegistration *m_userRegistration;
 
		GatewayResponder *m_gatewayResponder;
 
		AdHocManager *m_adHocManager;
 
		SettingsAdHocCommandFactory *m_settings;
 
		RosterResponder *m_rosterResponder;
 
};
 

	
 
}
spectrum/src/tests/irc_test.py
Show inline comments
 
@@ -22,48 +22,50 @@ class Responder(sleekxmpp.ClientXMPP):
 
							mtype='groupchat')
 

	
 
	def start(self, event):
 
		self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True)
 
		#time.sleep(1)
 
		#self.send_message(mto=self.room, mbody=self.message, mtype='groupchat')
 
		#time.sleep(10)
 
		#self.disconnect()
 

	
 
class Client(sleekxmpp.ClientXMPP):
 
	def __init__(self, jid, password, room, nick):
 
		sleekxmpp.ClientXMPP.__init__(self, jid, password)
 
		self.room = room
 
		self.nick = nick
 
		self.echo_received = False
 
		self.add_event_handler("session_start", self.start)
 
		self.add_event_handler("groupchat_message", self.muc_message)
 

	
 
	def muc_message(self, msg):
 
		if msg['mucnick'] != self.nick:
 
			if msg['body'] == "echo abc":
 
				self.echo_received = True
 

	
 
	def start(self, event):
 
		self.getRoster()
 
		self.sendPresence()
 
		self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True)
 
		self.send_message(mto=self.room, mbody="abc", mtype='groupchat')
 
		#time.sleep(10)
 
		#self.disconnect()
 

	
 
if __name__ == '__main__':
 
	os.system("../spectrum2 -n ./irc_test.cfg &")
 
	os.system("ngircd -f ngircd.conf &")
 
	time.sleep(1)
 
	responder = Responder("responder@localhost", "password", "#channel@localhost", "responder")
 
	responder.register_plugin('xep_0030')  # Service Discovery
 
	responder.register_plugin('xep_0045')  # Multi-User Chat
 
	responder.register_plugin('xep_0199')  # XMPP Ping
 
	responder['feature_mechanisms'].unencrypted_plain = True
 

	
 
	if responder.connect():
 
		responder.process(block=False)
 
	else:
 
		print "connect() failed"
 
		sys.exit(1)
 

	
 
	client = Client("client@localhost", "password", "#channel@localhost", "client")
 
	client.register_plugin('xep_0030')  # Service Discovery
 
	client.register_plugin('xep_0045')  # Multi-User Chat
src/tests/rostermanager.cpp
Show inline comments
 
@@ -74,48 +74,49 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		grp.push_back("group1");
 
		LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "", grp, BUDDY_JID_ESCAPING);
 
		user->getRosterManager()->setBuddy(buddy);
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 

	
 
		Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>();
 
		CPPUNIT_ASSERT(payload1);
 
		CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size());
 
		Swift::RosterItemPayload item = payload1->getItems()[0];
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), Buddy::JIDToLegacyName(item.getJID()));
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), item.getName());
 
	}
 

	
 
	void setBuddy() {
 
		add2Buddies();
 
		CPPUNIT_ASSERT_EQUAL(4, (int) received.size());
 

	
 
		Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>();
 
		CPPUNIT_ASSERT(payload1);
 
		CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size());
 
		Swift::RosterItemPayload item = payload1->getItems()[0];
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), Buddy::JIDToLegacyName(item.getJID()));
 
		CPPUNIT_ASSERT_EQUAL(std::string("Buddy 1"), item.getName());
 
		CPPUNIT_ASSERT_EQUAL(std::string("localhost"), getStanza(received[0])->getFrom().toString());
 

	
 
		Swift::RosterPayload::ref payload2 = getStanza(received[2])->getPayload<Swift::RosterPayload>();
 
		CPPUNIT_ASSERT(payload2);
 
		CPPUNIT_ASSERT_EQUAL(1, (int) payload2->getItems().size());
 
		item = payload2->getItems()[0];
 
		CPPUNIT_ASSERT_EQUAL(std::string("buddy2"), Buddy::JIDToLegacyName(item.getJID()));
 
		CPPUNIT_ASSERT_EQUAL(std::string("Buddy 2"), item.getName());
 

	
 
		// send responses back
 
		injectIQ(Swift::IQ::createResult(getStanza(received[0])->getFrom(), getStanza(received[0])->getTo(), getStanza(received[0])->getID()));
 
		injectIQ(Swift::IQ::createResult(getStanza(received[2])->getFrom(), getStanza(received[2])->getTo(), getStanza(received[2])->getID()));
 

	
 
		// we should get presences
 
		CPPUNIT_ASSERT_EQUAL(6, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[4])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[4]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast<Swift::Presence *>(getStanza(received[4]))->getStatus());
 

	
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[5])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[5]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast<Swift::Presence *>(getStanza(received[5]))->getStatus());
 
	}
 

	
 
	void sendCurrentPresences() {
0 comments (0 inline, 0 general)