diff options
25 files changed, 493 insertions, 112 deletions
| diff --git a/Swift/Controllers/UIInterfaces/WhiteboardWindow.h b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h index bedb057..ae736d7 100644 --- a/Swift/Controllers/UIInterfaces/WhiteboardWindow.h +++ b/Swift/Controllers/UIInterfaces/WhiteboardWindow.h @@ -11,6 +11,7 @@  #include <string>  namespace Swift { +	class WhiteboardSession;  	class WhiteboardWindow {  	public: @@ -18,6 +19,7 @@ namespace Swift {  		virtual void show() = 0;  		virtual void addItem(const std::string& item) = 0; +		virtual void setSession(boost::shared_ptr<WhiteboardSession> session) = 0;  		boost::signal<void (std::string)> onItemAdd;  	}; diff --git a/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h b/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h index 7e0fe81..c2d2f6c 100644 --- a/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h +++ b/Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h @@ -14,6 +14,6 @@ namespace Swift {  	public :  		virtual ~WhiteboardWindowFactory() {}; -		virtual WhiteboardWindow* createWhiteboardWindow(WhiteboardSession* whiteboardSession) = 0; +		virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession) = 0;  	};  } diff --git a/Swift/Controllers/WhiteboardManager.cpp b/Swift/Controllers/WhiteboardManager.cpp index 37c3263..f6db4ff 100644 --- a/Swift/Controllers/WhiteboardManager.cpp +++ b/Swift/Controllers/WhiteboardManager.cpp @@ -20,7 +20,6 @@ namespace Swift {  	WhiteboardManager::WhiteboardManager(WhiteboardWindowFactory* whiteboardWindowFactory, UIEventStream* uiEventStream, WhiteboardSessionManager* whiteboardSessionManager) : whiteboardWindowFactory_(whiteboardWindowFactory), uiEventStream_(uiEventStream), whiteboardSessionManager_(whiteboardSessionManager) {  		uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&WhiteboardManager::handleUIEvent, this, _1)); -		whiteboardSessionManager_->onRequestAccepted.connect(boost::bind(&WhiteboardManager::handleAcceptedRequest, this, _1, _2));  	}  	WhiteboardManager::~WhiteboardManager() { @@ -29,23 +28,30 @@ namespace Swift {  		}  	} -	WhiteboardWindow* WhiteboardManager::createNewWhiteboardWindow(const JID& contact, WhiteboardSession* session) { +	WhiteboardWindow* WhiteboardManager::createNewWhiteboardWindow(const JID& contact, WhiteboardSession::ref session) {  		WhiteboardWindow *window = whiteboardWindowFactory_->createWhiteboardWindow(session); -		whiteboardWindows_[contact] = window; +		whiteboardWindows_[contact.toBare()] = window;  		return window;  	}  	WhiteboardWindow* WhiteboardManager::findWhiteboardWindow(const JID& contact) { -		if (whiteboardWindows_.find(contact) == whiteboardWindows_.end()) { +		if (whiteboardWindows_.find(contact.toBare()) == whiteboardWindows_.end()) {  			return NULL;  		} -		return whiteboardWindows_[contact]; +		return whiteboardWindows_[contact.toBare()];  	}  	void WhiteboardManager::handleUIEvent(boost::shared_ptr<UIEvent> event) { -		boost::shared_ptr<RequestWhiteboardUIEvent> whiteboardEvent = boost::dynamic_pointer_cast<RequestWhiteboardUIEvent>(event); -		if (whiteboardEvent) { -			whiteboardSessionManager_->requestSession(whiteboardEvent->getContact()); +		boost::shared_ptr<RequestWhiteboardUIEvent> requestWhiteboardEvent = boost::dynamic_pointer_cast<RequestWhiteboardUIEvent>(event); +		if (requestWhiteboardEvent) { +			JID contact = requestWhiteboardEvent->getContact(); +			WhiteboardSession::ref session = whiteboardSessionManager_->requestSession(contact); +			WhiteboardWindow* window = findWhiteboardWindow(contact); +			if (window == NULL) { +				createNewWhiteboardWindow(contact, session); +			} else { +				window->setSession(session); +			}  		}  		boost::shared_ptr<AcceptWhiteboardSessionUIEvent> sessionAcceptEvent = boost::dynamic_pointer_cast<AcceptWhiteboardSessionUIEvent>(event);  		if (sessionAcceptEvent) { @@ -53,24 +59,28 @@ namespace Swift {  		}  		boost::shared_ptr<CancelWhiteboardSessionUIEvent> sessionCancelEvent = boost::dynamic_pointer_cast<CancelWhiteboardSessionUIEvent>(event);  		if (sessionCancelEvent) { -			whiteboardSessionManager_->cancelSession(sessionCancelEvent->getContact()); +			cancelSession(sessionCancelEvent->getContact());  		}  	}  	void WhiteboardManager::acceptSession(const JID& from) { -		WhiteboardSession* session = whiteboardSessionManager_->acceptSession(from); -		WhiteboardWindow* window = findWhiteboardWindow(from); -		if (window == NULL) { -			window = createNewWhiteboardWindow(from, session); +		IncomingWhiteboardSession::ref session = boost::dynamic_pointer_cast<IncomingWhiteboardSession>(whiteboardSessionManager_->getSession(from)); +		if (session) { +			session->accept(); +			WhiteboardWindow* window = findWhiteboardWindow(from); +			if (window == NULL) { +				window = createNewWhiteboardWindow(from, session); +			} else { +				window->setSession(session); +			} +			window->show();  		} -		window->show();  	} -	void WhiteboardManager::handleAcceptedRequest(const JID& from, WhiteboardSession* session) { -		WhiteboardWindow* window = findWhiteboardWindow(from); -		if (window == NULL) { -			window = createNewWhiteboardWindow(from, session); +	void WhiteboardManager::cancelSession(const JID& from) { +		IncomingWhiteboardSession::ref session = boost::dynamic_pointer_cast<IncomingWhiteboardSession>(whiteboardSessionManager_->getSession(from)); +		if (session) { +			session->cancel();  		} -		window->show();  	}  } diff --git a/Swift/Controllers/WhiteboardManager.h b/Swift/Controllers/WhiteboardManager.h index 2690f36..52d9bae 100644 --- a/Swift/Controllers/WhiteboardManager.h +++ b/Swift/Controllers/WhiteboardManager.h @@ -16,6 +16,7 @@  #include <Swift/Controllers/UIEvents/UIEventStream.h>  #include <Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h>  #include <Swift/Controllers/UIInterfaces/WhiteboardWindow.h> +#include <Swiften/Whiteboard/WhiteboardSession.h>  namespace Swift {  	class WhiteboardSessionManager; @@ -25,12 +26,12 @@ namespace Swift {  		WhiteboardManager(WhiteboardWindowFactory* whiteboardWindowFactory, UIEventStream* uiEventStream, WhiteboardSessionManager* whiteboardSessionManager);  		~WhiteboardManager(); -		WhiteboardWindow* createNewWhiteboardWindow(const JID& contact, WhiteboardSession* session); +		WhiteboardWindow* createNewWhiteboardWindow(const JID& contact, WhiteboardSession::ref session);  	private:  		void handleUIEvent(boost::shared_ptr<UIEvent> event);  		void acceptSession(const JID& from); -		void handleAcceptedRequest(const JID& from, WhiteboardSession* session); +		void cancelSession(const JID& from);  		WhiteboardWindow* findWhiteboardWindow(const JID& contact);  	private: diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index e0fc532..38e065c 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -136,7 +136,7 @@ ContactEditWindow* QtUIFactory::createContactEditWindow() {  	return new QtContactEditWindow();  } -WhiteboardWindow* QtUIFactory::createWhiteboardWindow(WhiteboardSession* whiteboardSession) { +WhiteboardWindow* QtUIFactory::createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession) {  	return new QtWhiteboardWindow(whiteboardSession);  } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 951b19c..d307759 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -43,7 +43,7 @@ namespace Swift {  			virtual ProfileWindow* createProfileWindow();  			virtual ContactEditWindow* createContactEditWindow();  			virtual FileTransferListWidget* createFileTransferListWidget(); -			virtual WhiteboardWindow* createWhiteboardWindow(WhiteboardSession* whiteboardSession); +			virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession);  			virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command);  		private slots: diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp index e0e68ba..3527eba 100644 --- a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp +++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp @@ -13,10 +13,11 @@  #include <Swiften/Whiteboard/WhiteboardSession.h>  #include <Swiften/Elements/WhiteboardPayload.h> +#include <QMessageBox>  using namespace std;  namespace Swift { -	QtWhiteboardWindow::QtWhiteboardWindow(WhiteboardSession* whiteboardSession) : QWidget(), whiteboardSession_(whiteboardSession) { +	QtWhiteboardWindow::QtWhiteboardWindow(WhiteboardSession::ref whiteboardSession) : QWidget() {  		layout = new QVBoxLayout(this);  		hLayout = new QHBoxLayout;  		sidebarLayout = new QVBoxLayout; @@ -121,7 +122,7 @@ namespace Swift {  		layout->addLayout(hLayout);  		this->setLayout(layout); -		whiteboardSession_->onDataReceived.connect(boost::bind(&QtWhiteboardWindow::addItem, this, _1));		 +		setSession(whiteboardSession);  	}  	void QtWhiteboardWindow::addItem(const std::string& item) { @@ -222,10 +223,19 @@ namespace Swift {  	{  		graphicsView->setMode(GView::Select);  	} +  	void QtWhiteboardWindow::show()  	{  		QWidget::show();  	} + +	void QtWhiteboardWindow::setSession(WhiteboardSession::ref session) { +		whiteboardSession_ = session; +		whiteboardSession_->onDataReceived.connect(boost::bind(&QtWhiteboardWindow::addItem, this, _1));		 +		whiteboardSession_->onRequestAccepted.connect(boost::bind(&QWidget::show, this)); +		whiteboardSession_->onSessionTerminateReceived.connect(boost::bind(&QtWhiteboardWindow::handleSessionTerminate, this)); +	} +  	void QtWhiteboardWindow::handleLastItemChanged(QGraphicsItem* item) {  		std::string serialized;  		QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); @@ -261,6 +271,25 @@ namespace Swift {  //			stanzaChannel_->sendMessage(mes);*/  			whiteboardSession_->sendData(serialized);  		} +	} +	void QtWhiteboardWindow::handleSessionTerminate() { +		QMessageBox box(this); +		box.setText(tr("Session was terminated by other user")); +		box.setIcon(QMessageBox::Information); +		box.exec(); +		hide(); +	} + +	void QtWhiteboardWindow::closeEvent(QCloseEvent* event) { +		QMessageBox box(this); +		box.setText(tr("Closing window is equivalent closing the session. Are you sure you want to do this?")); +		box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); +		box.setIcon(QMessageBox::Question); +		if (box.exec() == QMessageBox::Yes) { +			whiteboardSession_->cancel(); +		} else { +			event->ignore(); +		}  	}  } diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h index f1a9ed5..4c0a065 100644 --- a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h +++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h @@ -8,6 +8,7 @@  #include <Swift/Controllers/UIInterfaces/WhiteboardWindow.h>  #include <Swiften/Elements/Message.h> +#include <Swiften/Whiteboard/WhiteboardSession.h>  #include <QWidget>  #include <QGraphicsView> @@ -20,19 +21,19 @@  #include <QSpinBox>  #include <QColorDialog>  #include <QToolButton> +#include <QCloseEvent>  #include "GView.h"  namespace Swift { -	class WhiteboardSession; -  	class QtWhiteboardWindow : public QWidget, public WhiteboardWindow  	{  		Q_OBJECT;  	public: -		QtWhiteboardWindow(WhiteboardSession* whiteboardSession); +		QtWhiteboardWindow(WhiteboardSession::ref whiteboardSession);  		void addItem(const std::string& item);  		void show(); +		void setSession(WhiteboardSession::ref session);  	private slots:  		void changeLineWidth(int i); @@ -50,6 +51,10 @@ namespace Swift {  		void handleLastItemChanged(QGraphicsItem* item);  	private: +		void handleSessionTerminate(); +		void closeEvent(QCloseEvent* event); + +	private:  		QGraphicsScene* scene;  		GView* graphicsView;  		QVBoxLayout* layout; @@ -72,6 +77,6 @@ namespace Swift {  		QToolButton* polygonButton;  		QToolButton* selectButton; -		WhiteboardSession* whiteboardSession_; +		WhiteboardSession::ref whiteboardSession_;  	};  } diff --git a/Swiften/Elements/WhiteboardPayload.h b/Swiften/Elements/WhiteboardPayload.h index db261ca..3ad1706 100644 --- a/Swiften/Elements/WhiteboardPayload.h +++ b/Swiften/Elements/WhiteboardPayload.h @@ -15,7 +15,7 @@ namespace Swift {  	public:  		typedef boost::shared_ptr<WhiteboardPayload> ref; -		enum Type {Data, SessionRequest}; +		enum Type {Data, SessionRequest, SessionAccept, SessionTerminate};  		WhiteboardPayload(Type type = WhiteboardPayload::Data) : type_(type) {  		} diff --git a/Swiften/Jingle/#JingleSessionImpl.cpp# b/Swiften/Jingle/#JingleSessionImpl.cpp# new file mode 100644 index 0000000..98c5196 --- /dev/null +++ b/Swiften/Jingle/#JingleSessionImpl.cpp# @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Jingle/JingleSessionImpl.h> + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Parser/PayloadParsers/JingleParser.h> +#include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Elements/JingleContentPayload.h> +#include <Swiften/Queries/Request.h> +#include <Swiften/Queries/GenericRequest.h> + +#include <Swiften/Base/Log.h> + +#include "Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h" +#include "Swiften/FileTransfer/JingleTransport.h" + +namespace Swift { + +JingleSessionImpl::JingleSessionImpl(const JID& initiator, const JID& peerJID, const std::string& id, IQRouter* router) : JingleSession(initiator, id), iqRouter(router), peerJID(peerJID) { +	SWIFT_LOG(debug) << "initiator: " << initiator << ", peerJID: " << peerJID << std::endl; +} + +void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { +	if (action->getAction() == JinglePayload::SessionTerminate) { +		onSessionTerminateReceived(action->getReason()); +		return; +	} +	if (action->getAction() == JinglePayload::SessionInfo) { +		onSessionInfoReceived(action); +		return; +	} + +	JingleContentPayload::ref content = action->getPayload<JingleContentPayload>(); +	if (!content) { +		SWIFT_LOG(debug) << "no content payload!" << std::endl; +		return; +	} +	JingleContentID contentID(content->getName(), content->getCreator()); +	JingleDescription::ref description = content->getDescriptions().empty() ? JingleDescription::ref() : content->getDescriptions()[0]; +	JingleTransportPayload::ref transport = content->getTransports().empty() ? JingleTransportPayload::ref() : content->getTransports()[0]; +	switch(action->getAction()) { +		case JinglePayload::SessionAccept: +			onSessionAcceptReceived(contentID, description, transport); +			return; +		case JinglePayload::TransportAccept: +			onTransportAcceptReceived(contentID, transport); +			return; +		case JinglePayload::TransportInfo: +			onTransportInfoReceived(contentID, transport); +			return; +		case JinglePayload::TransportReject: +			onTransportRejectReceived(contentID, transport); +			return; +		case JinglePayload::TransportReplace: +			onTransportReplaceReceived(contentID, transport); +			return; +		// following unused Jingle actions +		case JinglePayload::ContentAccept: +		case JinglePayload::ContentAdd: +		case JinglePayload::ContentModify: +		case JinglePayload::ContentReject: +		case JinglePayload::ContentRemove: +		case JinglePayload::DescriptionInfo: +		case JinglePayload::SecurityInfo: + +		// handled elsewhere +		case JinglePayload::SessionInitiate: +		case JinglePayload::SessionInfo: +		case JinglePayload::SessionTerminate: + +		case JinglePayload::UnknownAction: +			return; +	} +	std::cerr << "Unhandled Jingle action!!! ACTION: " << action->getAction() << std::endl; +} + +void JingleSessionImpl::sendInitiate(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transport) { +	JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionInitiate, getID()); +	payload->setInitiator(getInitiator()); +	JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); +	content->setCreator(id.getCreator()); +	content->setName(id.getName()); +	content->addDescription(description); +	content->addTransport(transport); +	payload->addPayload(content); + +	sendSetRequest(payload); +} + +void JingleSessionImpl::sendTerminate(JinglePayload::Reason::Type reason) { +	JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, getID()); +	payload->setReason(JinglePayload::Reason(reason)); +	payload->setInitiator(getInitiator()); +	sendSetRequest(payload); +} + +void JingleSessionImpl::sendInfo(boost::shared_ptr<Payload> info) { +	JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionInfo, getID()); +	payload->addPayload(info); + +	sendSetRequest(payload); +} + +void JingleSessionImpl::sendAccept(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transPayload) { +	JinglePayload::ref payload = createPayload(); +	 +	JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); +	content->setCreator(id.getCreator()); +	content->setName(id.getName()); +	content->addTransport(transPayload); +	content->addDescription(description); +	payload->setAction(JinglePayload::SessionAccept); +	payload->addPayload(content); +	 +	// put into IQ:set and send it away +	sendSetRequest(payload); +} + + +void JingleSessionImpl::sendTransportAccept(const JingleContentID& id, JingleTransportPayload::ref transPayload) { +	JinglePayload::ref payload = createPayload(); + +	JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); +	content->setCreator(id.getCreator()); +	content->setName(id.getName()); +	content->addTransport(transPayload); +	payload->setAction(JinglePayload::TransportAccept); +	payload->addPayload(content); + +	// put into IQ:set and send it away +	sendSetRequest(payload); +} + +void JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref transPayload) { +	JinglePayload::ref payload = createPayload(); + +	JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); +	content->setCreator(id.getCreator()); +	content->setName(id.getName()); +	content->addTransport(transPayload); +	payload->setAction(JinglePayload::TransportInfo); +	payload->addPayload(content); + +	sendSetRequest(payload); +} + +void JingleSessionImpl::sendTransportReject(const JingleContentID& /* id */, JingleTransportPayload::ref /* transPayload */) { +	SWIFT_LOG(debug) << "NOT IMPLEMENTED YET!!!!" << std::endl; +} + +void JingleSessionImpl::sendTransportReplace(const JingleContentID& id, JingleTransportPayload::ref transPayload) { +	JinglePayload::ref payload = createPayload(); + +	JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); +	content->setCreator(id.getCreator()); +	content->setName(id.getName()); +	content->addTransport(transPayload); +	payload->setAction(JinglePayload::TransportReplace); +	payload->addContent(content); + +	sendSetRequest(payload); +} + + +void JingleSessionImpl::sendSetRequest(JinglePayload::ref payload) { +	boost::shared_ptr<GenericRequest<JinglePayload> > request = boost::make_shared<GenericRequest<JinglePayload> >(IQ::Set, peerJID, payload, iqRouter); +	request->send(); +} + + +JinglePayload::ref JingleSessionImpl::createPayload() const { +	JinglePayload::ref payload = boost::make_shared<JinglePayload>(); +	payload->setSessionID(getID()); +	payload->setInitiator(getInitiator()); +	return payload; +} + + + +} diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index 94b67e5..4306497 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -5,19 +5,16 @@   */  #include <Swiften/Parser/PayloadParsers/WhiteboardParser.h> +#include <boost/optional.hpp>  namespace Swift {  	WhiteboardParser::WhiteboardParser() : level_(0) {  	} +  	void WhiteboardParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {  		if (level_ == 0) { -			std::string type = attributes.getAttribute("type"); -			if (type.empty()) { -				getPayloadInternal()->setType(WhiteboardPayload::Data); -			} -			else if (type == "request") { -				getPayloadInternal()->setType(WhiteboardPayload::SessionRequest); -			} +//			std::string type = attributes.getAttribute("type"); +			getPayloadInternal()->setType(stringToType(attributes.getAttributeValue("type").get_value_or("")));  		}  		++level_;  	} @@ -32,4 +29,16 @@ namespace Swift {  	void WhiteboardParser::handleCharacterData(const std::string& data) {  		data_ += data;  	} + +	WhiteboardPayload::Type WhiteboardParser::stringToType(const std::string& type) const { +		if (type.empty()) { +			return WhiteboardPayload::Data; +		} else if (type == "session-request") { +			return WhiteboardPayload::SessionRequest; +		} else if (type == "session-accept") { +			return WhiteboardPayload::SessionAccept; +		} else if (type == "session-terminate") { +			return WhiteboardPayload::SessionTerminate; +		} +	}  } diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.h b/Swiften/Parser/PayloadParsers/WhiteboardParser.h index 265e12d..faa698b 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.h +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.h @@ -17,6 +17,10 @@ namespace Swift {  		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);  		virtual void handleEndElement(const std::string& element, const std::string&);  		virtual void handleCharacterData(const std::string& data); + +	private: +		WhiteboardPayload::Type stringToType(const std::string& type) const; +  	private:  		int level_;  		std::string data_; diff --git a/Swiften/SConscript b/Swiften/SConscript index 9b31304..1fa47ca 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -184,6 +184,7 @@ if env["SCONS_STAGE"] == "build" :  			"Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp",  			"Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp",  			"Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp", +			"Serializer/PayloadSerializers/WhiteboardSerializer.cpp",  			"Serializer/PresenceSerializer.cpp",  			"Serializer/StanzaSerializer.cpp",  			"Serializer/StreamErrorSerializer.cpp", @@ -202,6 +203,8 @@ if env["SCONS_STAGE"] == "build" :  			"StringCodecs/Hexify.cpp",  			"Whiteboard/WhiteboardResponder.cpp",  			"Whiteboard/WhiteboardSession.cpp", +			"Whiteboard/IncomingWhiteboardSession.cpp", +			"Whiteboard/OutgoingWhiteboardSession.cpp",  			"Whiteboard/WhiteboardSessionManager.cpp",  		] diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp new file mode 100644 index 0000000..578b0ab --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { +	std::string WhiteboardSerializer::serializePayload(boost::shared_ptr<WhiteboardPayload> payload) const { +		XMLElement element("wb"); +		element.addNode(XMLTextNode::ref(new XMLTextNode(payload->getData()))); +		element.setAttribute("type", typeToString(payload->getType())); +		return element.serialize(); +	} + +	std::string WhiteboardSerializer::typeToString(WhiteboardPayload::Type type) const { +		if(type == WhiteboardPayload::Data) { +			return ""; +		} else if (type == WhiteboardPayload::SessionRequest) { +			return "session-request"; +		} else if (type == WhiteboardPayload::SessionAccept) { +			return "session-accept"; +		} else if (type == WhiteboardPayload::SessionTerminate) { +			return "session-terminate"; +		} +	} +} diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h index 9b7f905..975d537 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h @@ -12,13 +12,9 @@  namespace Swift {  	class WhiteboardSerializer : public GenericPayloadSerializer<WhiteboardPayload> {  	public: -		std::string serializePayload(boost::shared_ptr<WhiteboardPayload> payload) const { -			XMLElement element("wb"); -			element.addNode(XMLTextNode::ref(new XMLTextNode(payload->getData()))); -			if (payload->getType() == WhiteboardPayload::SessionRequest) { -				element.setAttribute("type", "request"); -			} -			return element.serialize(); -		} +		std::string serializePayload(boost::shared_ptr<WhiteboardPayload> payload) const; + +	private: +		std::string typeToString(WhiteboardPayload::Type type) const;  	};  } diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.cpp b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp new file mode 100644 index 0000000..92a86a1 --- /dev/null +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Whiteboard/IncomingWhiteboardSession.h> +#include <Swiften/Elements/WhiteboardPayload.h> + +namespace Swift { +	IncomingWhiteboardSession::IncomingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { +	} + +	IncomingWhiteboardSession::~IncomingWhiteboardSession() { +	} + +	void IncomingWhiteboardSession::accept() { +		boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionAccept); +		boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); +		request->send(); +	} +} diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.h b/Swiften/Whiteboard/IncomingWhiteboardSession.h new file mode 100644 index 0000000..3b15a49 --- /dev/null +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Whiteboard/WhiteboardSession.h> + +#include <boost/shared_ptr.hpp> + +#pragma once + +namespace Swift { +	class IncomingWhiteboardSession : public WhiteboardSession { +	public: +		typedef boost::shared_ptr<IncomingWhiteboardSession> ref; + +	public: +		IncomingWhiteboardSession(const JID& jid, IQRouter* router); +		~IncomingWhiteboardSession(); + +		void accept(); +	}; +} diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp new file mode 100644 index 0000000..2693fcd --- /dev/null +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Whiteboard/OutgoingWhiteboardSession.h> + +#include <boost/bind.hpp> +#include <Swiften/Elements/WhiteboardPayload.h> + +namespace Swift { +	OutgoingWhiteboardSession::OutgoingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { +	} + +	OutgoingWhiteboardSession::~OutgoingWhiteboardSession() { +	} + +	void OutgoingWhiteboardSession::startSession() { +		boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionRequest); +		boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); +		request->send(); +	} +} diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.h b/Swiften/Whiteboard/OutgoingWhiteboardSession.h new file mode 100644 index 0000000..dfbd200 --- /dev/null +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Whiteboard/WhiteboardSession.h> + +#include <boost/shared_ptr.hpp> +#include <Swiften/Queries/GenericRequest.h> + +namespace Swift { +	class OutgoingWhiteboardSession : public WhiteboardSession { +	public: +		typedef boost::shared_ptr<OutgoingWhiteboardSession> ref; + +	public: +		OutgoingWhiteboardSession(const JID& jid, IQRouter* router); +		virtual ~OutgoingWhiteboardSession(); +		void startSession(); +	}; +} diff --git a/Swiften/Whiteboard/WhiteboardResponder.cpp b/Swiften/Whiteboard/WhiteboardResponder.cpp index 8a1b290..c947aec 100644 --- a/Swiften/Whiteboard/WhiteboardResponder.cpp +++ b/Swiften/Whiteboard/WhiteboardResponder.cpp @@ -7,6 +7,7 @@  #include <Swiften/Whiteboard/WhiteboardResponder.h>  #include <Swiften/Whiteboard/WhiteboardSessionManager.h> +#include <Swiften/Whiteboard/IncomingWhiteboardSession.h>  #include <Swiften/Whiteboard/WhiteboardSession.h>  #include <Swiften/Queries/IQRouter.h> @@ -16,27 +17,20 @@ namespace Swift {  	bool WhiteboardResponder::handleSetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<WhiteboardPayload> payload) {  		if (payload->getType() == WhiteboardPayload::SessionRequest) { -			sessionManager_->onRequestReceived(from); -			sessionRequests_[from] = id; +			if (sessionManager_->getSession(from.toBare())) { +				sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); +			} else { +				sendResponse(from, id, boost::shared_ptr<WhiteboardPayload>()); +				IncomingWhiteboardSession::ref session = boost::make_shared<IncomingWhiteboardSession>(from, router_); +				sessionManager_->handleIncomingSession(session); +			}  		} else {  			sendResponse(from, id, boost::shared_ptr<WhiteboardPayload>()); -			WhiteboardSession* session = sessionManager_->getSession(from.toBare()); +			WhiteboardSession::ref session = sessionManager_->getSession(from.toBare());  			if (session != NULL) {  				session->handleIncomingAction(payload);  			}  		}  		return true;  	} - -	void WhiteboardResponder::sendRequestResponse(const JID& contact, bool accepted) { -		if (sessionRequests_.find(contact) == sessionRequests_.end()) { -			return; -		} -		if (accepted ) { -			sendResponse(contact, sessionRequests_[contact], boost::shared_ptr<WhiteboardPayload>()); -		} else { -			sendError(contact, sessionRequests_[contact], ErrorPayload::Conflict, ErrorPayload::Cancel); -		} -		sessionRequests_.erase(contact); -	}  } diff --git a/Swiften/Whiteboard/WhiteboardResponder.h b/Swiften/Whiteboard/WhiteboardResponder.h index d1b712d..b171ef3 100644 --- a/Swiften/Whiteboard/WhiteboardResponder.h +++ b/Swiften/Whiteboard/WhiteboardResponder.h @@ -17,10 +17,8 @@ namespace Swift {  	public:  		WhiteboardResponder(WhiteboardSessionManager* sessionManager, IQRouter* router);  		bool handleSetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<WhiteboardPayload> payload); -		void sendRequestResponse(const JID& contact, bool accepted);  	private: -		std::map<JID, std::string> sessionRequests_;  		WhiteboardSessionManager* sessionManager_;  		IQRouter* router_;  	}; diff --git a/Swiften/Whiteboard/WhiteboardSession.cpp b/Swiften/Whiteboard/WhiteboardSession.cpp index 859f2cd..bfef7c3 100644 --- a/Swiften/Whiteboard/WhiteboardSession.cpp +++ b/Swiften/Whiteboard/WhiteboardSession.cpp @@ -6,7 +6,6 @@  #include <Swiften/Whiteboard/WhiteboardSession.h> -#include <boost/bind.hpp>  #include <boost/smart_ptr/make_shared.hpp>  #include <Swiften/Elements/WhiteboardPayload.h>  #include <Swiften/Elements/ErrorPayload.h> @@ -17,8 +16,23 @@ namespace Swift {  	WhiteboardSession::WhiteboardSession(const JID& jid, IQRouter* router) : toJID_(jid), router_(router) {  	} +	WhiteboardSession::~WhiteboardSession() { +	} +  	void WhiteboardSession::handleIncomingAction(boost::shared_ptr<WhiteboardPayload> payload) { -		onDataReceived(payload->getData()); +		if (payload->getType() == WhiteboardPayload::SessionTerminate) { +			onSessionTerminateReceived(toJID_); +			return; +		} + +		switch (payload->getType()) { +		case WhiteboardPayload::Data: +			onDataReceived(payload->getData()); +			break; +		case WhiteboardPayload::SessionAccept: +			onRequestAccepted(toJID_); +			break; +		}  	}  	void WhiteboardSession::sendData(const std::string& data) { @@ -28,17 +42,14 @@ namespace Swift {  		request->send();  	} -	void WhiteboardSession::sendSessionRequest() { -		boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionRequest); -		sessionRequest = new GenericRequest<WhiteboardPayload>(IQ::Set, toJID_, payload, router_); -		sessionRequest->onResponse.connect(boost::bind(&WhiteboardSession::handleSessionRequestResponse, this, _1, _2)); -		sessionRequest->send(); +	void WhiteboardSession::cancel() { +		boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionTerminate); +		boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); +		request->send(); +		onSessionCancelled(toJID_);  	} -	void WhiteboardSession::handleSessionRequestResponse(boost::shared_ptr<WhiteboardPayload> whiteboardPayload, boost::shared_ptr<ErrorPayload> errorPayload) { -		if (errorPayload.get() == 0) { -			onRequestAccepted(toJID_, this); -		} -		delete sessionRequest; +	const JID& WhiteboardSession::getTo() const { +		return toJID_;  	}  } diff --git a/Swiften/Whiteboard/WhiteboardSession.h b/Swiften/Whiteboard/WhiteboardSession.h index 14d6778..7aa67ca 100644 --- a/Swiften/Whiteboard/WhiteboardSession.h +++ b/Swiften/Whiteboard/WhiteboardSession.h @@ -19,19 +19,24 @@ namespace Swift {  	class WhiteboardSession {  	public: +		typedef boost::shared_ptr<WhiteboardSession> ref; + +	public:  		WhiteboardSession(const JID& jid, IQRouter* router); +		virtual ~WhiteboardSession();  		void handleIncomingAction(boost::shared_ptr<WhiteboardPayload> payload);  		void sendData(const std::string& data); -		void sendSessionRequest(); -		void handleSessionRequestResponse(boost::shared_ptr<WhiteboardPayload> whiteboardPayload, boost::shared_ptr<ErrorPayload> errorPayload); +		void cancel(); +		const JID& getTo() const;  	public:  		boost::signal< void(const std::string& data)> onDataReceived; -		boost::signal< void(const JID& contact, WhiteboardSession* session)> onRequestAccepted; +		boost::signal< void(const JID& contact)> onSessionTerminateReceived; +		boost::signal< void(const JID& contact)> onRequestAccepted; +		boost::signal< void(const JID& contact)> onSessionCancelled; -	private: +	protected:  		JID toJID_;  		IQRouter* router_; -		GenericRequest<WhiteboardPayload>* sessionRequest;  	};  } diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.cpp b/Swiften/Whiteboard/WhiteboardSessionManager.cpp index ccbc4d7..eae9e5b 100644 --- a/Swiften/Whiteboard/WhiteboardSessionManager.cpp +++ b/Swiften/Whiteboard/WhiteboardSessionManager.cpp @@ -9,7 +9,6 @@  #include <boost/bind.hpp>  #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Whiteboard/WhiteboardSession.h>  #include <Swiften/Whiteboard/WhiteboardResponder.h>  #include <Swiften/Presence/PresenceOracle.h> @@ -24,48 +23,53 @@ namespace Swift {  		delete responder;  	} -	WhiteboardSession* WhiteboardSessionManager::getSession(const JID& to) { +	WhiteboardSession::ref WhiteboardSessionManager::getSession(const JID& to) {  		if (sessions_.find(to.toBare()) == sessions_.end()) { -			return NULL; +			return boost::shared_ptr<WhiteboardSession>();  		}  		return sessions_[to.toBare()];  	} -	WhiteboardSession* WhiteboardSessionManager::createSession(const JID& to) { +	OutgoingWhiteboardSession::ref WhiteboardSessionManager::createOutgoingSession(const JID& to) {  		JID fullJID = to;  		if (fullJID.isBare()) {  			fullJID = getFullJID(fullJID);  		} -		WhiteboardSession* session = new WhiteboardSession(fullJID, router_); +		OutgoingWhiteboardSession::ref session = boost::make_shared<OutgoingWhiteboardSession>(fullJID, router_);  		sessions_[to.toBare()] = session; +		session->onSessionTerminateReceived.connect(boost::bind(&WhiteboardSessionManager::handleSessionTerminate, this, _1)); +		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancelled, this, _1));  		return session;  	} -	WhiteboardSession* WhiteboardSessionManager::acceptSession(const JID& to) { -		responder->sendRequestResponse(to, true); -		WhiteboardSession* session = getSession(to); -		if (session == NULL) { -			return createSession(to); +	WhiteboardSession::ref WhiteboardSessionManager::requestSession(const JID& to) { +		WhiteboardSession::ref session = getSession(to); +		if (!session) { +			OutgoingWhiteboardSession::ref outgoingSession = createOutgoingSession(to); +			outgoingSession->startSession(); +			return outgoingSession; +		} else { +			return session;  		} -		return session;  	} -	void WhiteboardSessionManager::requestSession(const JID& to) { -		WhiteboardSession* session = createSession(to); -		session->onRequestAccepted.connect(boost::bind(&WhiteboardSessionManager::handleRequestAccepted, this, _1, _2)); -		session->sendSessionRequest(); +	void WhiteboardSessionManager::handleIncomingSession(IncomingWhiteboardSession::ref session) { +		sessions_[session->getTo().toBare()] = session; +		session->onSessionTerminateReceived.connect(boost::bind(&WhiteboardSessionManager::handleSessionTerminate, this, _1)); +		session->onSessionCancelled.connect(boost::bind(&WhiteboardSessionManager::handleSessionCancelled, this, _1)); +		onRequestReceived(session->getTo());  	} -	void WhiteboardSessionManager::cancelSession(const JID& to) { -		responder->sendRequestResponse(to, false); +	JID WhiteboardSessionManager::getFullJID(const JID& bareJID) { +		std::vector<Presence::ref> presences = presenceOracle_->getAllPresence(bareJID); +		return presences[0]->getFrom();  	} -	void WhiteboardSessionManager::handleRequestAccepted(const JID& contact, WhiteboardSession* session) { -		onRequestAccepted(contact, session); +	void WhiteboardSessionManager::handleSessionTerminate(const JID& contact) { +		sessions_.erase(contact.toBare());  	} -	JID WhiteboardSessionManager::getFullJID(const JID& bareJID) { -		std::vector<Presence::ref> presences = presenceOracle_->getAllPresence(bareJID); -		return presences[0]->getFrom(); +	void WhiteboardSessionManager::handleSessionCancelled(const JID& contact) { +		sessions_.erase(contact.toBare());  	}  } diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.h b/Swiften/Whiteboard/WhiteboardSessionManager.h index 3cd3aab..d2a59e0 100644 --- a/Swiften/Whiteboard/WhiteboardSessionManager.h +++ b/Swiften/Whiteboard/WhiteboardSessionManager.h @@ -11,34 +11,35 @@  #include <Swiften/Queries/IQRouter.h>  #include <Swiften/JID/JID.h>  #include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> +#include <Swiften/Whiteboard/IncomingWhiteboardSession.h> +#include <Swiften/Whiteboard/OutgoingWhiteboardSession.h>  namespace Swift {  	class IQRouter; -	class WhiteboardSession;  	class WhiteboardResponder;  	class PresenceOracle;  	class WhiteboardSessionManager { +		friend class WhiteboardResponder;  	public:  		WhiteboardSessionManager(IQRouter* router, PresenceOracle* presenceOracle);  		~WhiteboardSessionManager(); - -		WhiteboardSession* getSession(const JID& to); -		WhiteboardSession* acceptSession(const JID& to); -		void requestSession(const JID& to); -		void cancelSession(const JID& to); -		void handleRequestAccepted(const JID& contact, WhiteboardSession* session); +		WhiteboardSession::ref getSession(const JID& to); +		WhiteboardSession::ref requestSession(const JID& to);  	public:  		boost::signal< void (const JID&)> onRequestReceived; -		boost::signal< void (const JID&, WhiteboardSession*)> onRequestAccepted;  	private:  		JID getFullJID(const JID& bareJID); -		WhiteboardSession* createSession(const JID& to); +		OutgoingWhiteboardSession::ref createOutgoingSession(const JID& to); +		void handleIncomingSession(IncomingWhiteboardSession::ref session); +		void handleSessionTerminate(const JID& contact); +		void handleSessionCancelled(const JID& contact);  	private: -		std::map<JID, WhiteboardSession*> sessions_; +		std::map<JID, boost::shared_ptr<WhiteboardSession> > sessions_;  		IQRouter* router_;  		PresenceOracle* presenceOracle_;  		WhiteboardResponder* responder; | 
 Swift
 Swift