diff options
author | Mateusz Piekos <mateuszpiekos@gmail.com> | 2012-06-12 10:52:03 (GMT) |
---|---|---|
committer | Mateusz Piekos <mateuszpiekos@gmail.com> | 2012-06-12 10:52:03 (GMT) |
commit | edd726abb1d0f7532218efbb8067a75a313e9e98 (patch) | |
tree | 7eec4f7912a59bb9a383a61c2c96616d5b5847b6 | |
parent | 6e9fb4e4a3aeee8c40617a4dda6e5e0892ceebad (diff) | |
download | swift-contrib-edd726abb1d0f7532218efbb8067a75a313e9e98.zip swift-contrib-edd726abb1d0f7532218efbb8067a75a313e9e98.tar.bz2 |
Improved whiteboard session handling
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; |