diff options
36 files changed, 950 insertions, 21 deletions
diff --git a/Swiften/Elements/JingleContent.h b/Swiften/Elements/JingleContent.h new file mode 100644 index 0000000..bf419aa --- /dev/null +++ b/Swiften/Elements/JingleContent.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <vector> +#include <boost/optional.hpp> + +#include <Swiften/Base/String.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/JingleDescription.h> +#include <Swiften/Elements/JingleTransport.h> +#include <Swiften/Base/foreach.h> + +namespace Swift { + class JingleContent : public Payload { + public: + typedef boost::shared_ptr<JingleContent> ref; + + enum Creator { + InitiatorCreator, + ResponderCreator, + }; + + /*enum Senders { + NoSenders, + InitiatorSender, + ResponderSender, + BothSenders, + };*/ + + void setCreator(Creator creator) { + this->creator = creator; + } + + void setName(const String& name) { + this->name = name; + } + + const std::vector<JingleDescription::ref>& getDescriptions() const { + return descriptions; + } + + void addDescription(JingleDescription::ref description) { + descriptions.push_back(description); + } + + const std::vector<JingleTransport::ref>& getTransports() const { + return transports; + } + + void addTransport(JingleTransport::ref transport) { + transports.push_back(transport); + } + + template<typename T> + boost::shared_ptr<T> getDescription() const { + foreach (JingleDescription::ref i, descriptions) { + boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i)); + if (result) { + return result; + } + } + return boost::shared_ptr<T>(); + } + + template<typename T> + boost::shared_ptr<T> getTransport() const { + foreach (JingleTransport::ref i, transports) { + boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i)); + if (result) { + return result; + } + } + return boost::shared_ptr<T>(); + } + + private: + Creator creator; + String name; + //Senders senders; + std::vector<JingleDescription::ref> descriptions; + std::vector<JingleTransport::ref> transports; + }; +} diff --git a/Swiften/Elements/JingleDescription.h b/Swiften/Elements/JingleDescription.h new file mode 100644 index 0000000..775c0f7 --- /dev/null +++ b/Swiften/Elements/JingleDescription.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 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/Elements/Payload.h> + +namespace Swift { + class JingleDescription : public Payload { + public: + typedef boost::shared_ptr<JingleDescription> ref; + }; +} diff --git a/Swiften/Elements/JingleFileTransferDescription.h b/Swiften/Elements/JingleFileTransferDescription.h new file mode 100644 index 0000000..19644bd --- /dev/null +++ b/Swiften/Elements/JingleFileTransferDescription.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 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 <boost/optional.hpp> + +#include <Swiften/Elements/JingleDescription.h> +#include <Swiften/Elements/StreamInitiationFileInfo.h> + +namespace Swift { + class JingleFileTransferDescription : public JingleDescription { + public: + typedef boost::shared_ptr<JingleFileTransferDescription> ref; + + void setOffer(const StreamInitiationFileInfo& offer) { + this->offer = offer; + } + + const boost::optional<StreamInitiationFileInfo>& getOffer() const { + return offer; + } + + private: + boost::optional<StreamInitiationFileInfo> offer; + }; +} diff --git a/Swiften/Elements/JingleIBBTransport.h b/Swiften/Elements/JingleIBBTransport.h new file mode 100644 index 0000000..ca3ecc8 --- /dev/null +++ b/Swiften/Elements/JingleIBBTransport.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/String.h> +#include <Swiften/Elements/JingleTransport.h> + +namespace Swift { + class JingleIBBTransport : public JingleTransport { + public: + enum StanzaType { + IQStanza, + MessageStanza, + }; + + void setStanzaType(StanzaType stanzaType) { + this->stanzaType = stanzaType; + } + + StanzaType getStanzaType() const { + return stanzaType; + } + + void setSessionID(const String& id) { + sessionID = id; + } + + const String& getSessionID() const { + return sessionID; + } + + int getBlockSize() const { + return blockSize; + } + + void setBlockSize(int blockSize) { + this->blockSize = blockSize; + } + + private: + String sessionID; + int blockSize; + StanzaType stanzaType; + }; +} diff --git a/Swiften/Elements/JinglePayload.h b/Swiften/Elements/JinglePayload.h new file mode 100644 index 0000000..66b6d43 --- /dev/null +++ b/Swiften/Elements/JinglePayload.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <vector> +#include <boost/optional.hpp> + +#include <Swiften/Base/String.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/JingleContent.h> + + +namespace Swift { + class JinglePayload : public Payload { + public: + typedef boost::shared_ptr<JinglePayload> ref; + struct Reason { + enum Type { + AlternativeSession, + Busy, + Cancel, + ConnectivityError, + Decline, + Expired, + FailedApplication, + FailedTransport, + GeneralError, + Gone, + IncompatibleParameters, + MediaError, + SecurityError, + Success, + Timeout, + UnsupportedApplications, + UnsupportedTransports + }; + + Reason(Type type, const String& text = "") : type(type), text(text) {} + Type type; + String text; + }; + + enum Action { + ContentAccept, + ContentAdd, + ContentModify, + ContentReject, + ContentRemove, + DescriptionInfo, + SecurityInfo, + SessionAccept, + SessionInfo, + SessionInitiate, + SessionTerminate, + TransportAccept, + TransportInfo, + TransportReject, + TransportReplace + }; + + JinglePayload(Action action, const String& sessionID) : action(action), sessionID(sessionID) { + } + + void setAction(Action action) { + this->action = action; + } + + Action getAction() const { + return action; + } + + void setInitiator(const JID& initiator) { + this->initiator = initiator; + } + + const JID& getInitiator() const { + return initiator; + } + + void setResponder(const JID& responder) { + this->responder = responder; + } + + const JID& getResponder() const { + return responder; + } + + void setSessionID(const String& id) { + sessionID = id; + } + + const String& getSessionID() const { + return sessionID; + } + + void addContent(JingleContent::ref content) { + this->contents.push_back(content); + } + + const std::vector<JingleContent::ref> getContents() const { + return contents; + } + + void setReason(const Reason& reason) { + this->reason = reason; + } + + const boost::optional<Reason>& getReason() const { + return reason; + } + + private: + Action action; + JID initiator; + JID responder; + String sessionID; + std::vector<JingleContent::ref> contents; + boost::optional<Reason> reason; + }; +} diff --git a/Swiften/Elements/JingleS5BTransport.h b/Swiften/Elements/JingleS5BTransport.h new file mode 100644 index 0000000..4522417 --- /dev/null +++ b/Swiften/Elements/JingleS5BTransport.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/JingleTransport.h> +#include <Swiften/Elements/Bytestreams.h> + +namespace Swift { + class JingleS5BTransport : public JingleTransport { + public: + const Bytestreams& getInfo() const { + return info; + } + + void setInfo(const Bytestreams& info) { + this->info = info; + } + + private: + Bytestreams info; + }; +} diff --git a/Swiften/Elements/JingleTransport.h b/Swiften/Elements/JingleTransport.h new file mode 100644 index 0000000..ecd2a34 --- /dev/null +++ b/Swiften/Elements/JingleTransport.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class JingleTransport : public Payload { + }; +} diff --git a/Swiften/Elements/StreamInitiation.h b/Swiften/Elements/StreamInitiation.h index 55b6b87..16dfd4d 100644 --- a/Swiften/Elements/StreamInitiation.h +++ b/Swiften/Elements/StreamInitiation.h @@ -12,20 +12,13 @@ #include "Swiften/Base/String.h" #include "Swiften/Elements/Payload.h" +#include <Swiften/Elements/StreamInitiationFileInfo.h> namespace Swift { class StreamInitiation : public Payload { public: typedef boost::shared_ptr<StreamInitiation> ref; - struct FileInfo { - FileInfo(const String& name = "", const String& description = "", int size = -1) : name(name), description(description), size(size) {} - - String name; - String description; - int size; - }; - StreamInitiation() : isFileTransfer(true) {} const String& getID() const { @@ -36,11 +29,11 @@ namespace Swift { this->id = id; } - const boost::optional<FileInfo>& getFileInfo() const { + const boost::optional<StreamInitiationFileInfo>& getFileInfo() const { return fileInfo; } - void setFileInfo(const FileInfo& info) { + void setFileInfo(const StreamInitiationFileInfo& info) { fileInfo = info; } @@ -71,7 +64,7 @@ namespace Swift { private: bool isFileTransfer; String id; - boost::optional<FileInfo> fileInfo; + boost::optional<StreamInitiationFileInfo> fileInfo; std::vector<String> providedMethods; String requestedMethod; }; diff --git a/Swiften/Elements/StreamInitiationFileInfo.h b/Swiften/Elements/StreamInitiationFileInfo.h new file mode 100644 index 0000000..15b5a66 --- /dev/null +++ b/Swiften/Elements/StreamInitiationFileInfo.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/String.h> + +namespace Swift { + struct StreamInitiationFileInfo { + StreamInitiationFileInfo(const String& name = "", const String& description = "", int size = -1) : name(name), description(description), size(size) {} + + String name; + String description; + int size; + }; +} diff --git a/Swiften/Examples/SendFile/.gitignore b/Swiften/Examples/SendFile/.gitignore index f8b7625..b40e042 100644 --- a/Swiften/Examples/SendFile/.gitignore +++ b/Swiften/Examples/SendFile/.gitignore @@ -1 +1,2 @@ SendFile +ReceiveFile diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp new file mode 100644 index 0000000..a6386cd --- /dev/null +++ b/Swiften/Examples/SendFile/ReceiveFile.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/bind.hpp> +#include <boost/filesystem.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Client/Client.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/FileTransfer/IncomingFileTransferManager.h> +#include <Swiften/FileTransfer/FileWriteBytestream.h> +#include <Swiften/Jingle/JingleSessionManager.h> + +using namespace Swift; + +SimpleEventLoop eventLoop; +BoostNetworkFactories networkFactories(&eventLoop); + +int exitCode = 2; + +class FileReceiver { + public: + FileReceiver(const JID& jid, const String& password) : jid(jid), password(password), jingleSessionManager(NULL), incomingFileTransferManager(NULL) { + client = new Swift::Client(&eventLoop, &networkFactories, jid, password); + client->onConnected.connect(boost::bind(&FileReceiver::handleConnected, this)); + client->onDisconnected.connect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); + //tracer = new ClientXMLTracer(client); + } + + ~FileReceiver() { + delete incomingFileTransferManager; + delete jingleSessionManager; + //delete tracer; + client->onDisconnected.disconnect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); + client->onConnected.disconnect(boost::bind(&FileReceiver::handleConnected, this)); + delete client; + } + + void start() { + client->connect(); + } + + void stop() { + foreach(const IncomingFileTransfer::ref transfer, incomingFileTransfers) { + //transfer->stop(); + } + client->disconnect(); + } + + private: + void handleConnected() { + client->sendPresence(Presence::create()); + jingleSessionManager = new JingleSessionManager(client->getIQRouter()); + incomingFileTransferManager = new IncomingFileTransferManager(jingleSessionManager, client->getIQRouter()); + incomingFileTransferManager->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1)); + } + + void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) { + incomingFileTransfers.push_back(transfer); + transfer->accept(boost::make_shared<FileWriteBytestream>("out")); + //transfer->onFinished.connect(boost::bind(&FileReceiver::handleFileTransferFinished, this, _1)); + //transfer->start(); + } + + void handleDisconnected(const boost::optional<ClientError>&) { + std::cerr << "Error!" << std::endl; + exit(-1); + } + + /* + void handleFileTransferFinished(const boost::optional<FileTransferError>& error) { + std::cout << "File transfer finished" << std::endl; + if (error) { + exit(-1); + } + else { + exit(0); + } + }*/ + + void exit(int code) { + exitCode = code; + stop(); + eventLoop.stop(); + } + + private: + JID jid; + String password; + Client* client; + ClientXMLTracer* tracer; + JingleSessionManager* jingleSessionManager; + IncomingFileTransferManager* incomingFileTransferManager; + std::vector<IncomingFileTransfer::ref> incomingFileTransfers; +}; + + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " <jid> <password>" << std::endl; + return -1; + } + + JID jid(argv[1]); + FileReceiver fileReceiver(jid, String(argv[2])); + fileReceiver.start(); + + eventLoop.run(); + + return exitCode; +} diff --git a/Swiften/Examples/SendFile/SConscript b/Swiften/Examples/SendFile/SConscript index 50cbe40..6986f22 100644 --- a/Swiften/Examples/SendFile/SConscript +++ b/Swiften/Examples/SendFile/SConscript @@ -10,4 +10,6 @@ myenv.MergeFlags(myenv.get("SQLITE_FLAGS", {})) myenv.MergeFlags(myenv.get("LIBXML_FLAGS", "")) myenv.MergeFlags(myenv.get("EXPAT_FLAGS", "")) myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) -tester = myenv.Program("SendFile", ["SendFile.cpp"]) + +myenv.Program("SendFile", ["SendFile.cpp"]) +myenv.Program("ReceiveFile", ["ReceiveFile.cpp"]) diff --git a/Swiften/FileTransfer/IncomingFileTransfer.cpp b/Swiften/FileTransfer/IncomingFileTransfer.cpp index 1962724..238ccce 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingFileTransfer.cpp @@ -8,8 +8,16 @@ namespace Swift { -void IncomingFileTransfer::accept(WriteBytestream::ref) { +IncomingFileTransfer::~IncomingFileTransfer() { } +/*void IncomingFileTransfer::accept(WriteBytestream::ref) { + +} + +void IncomingFileTransfer::stop() { + +}*/ + } diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h index d5e7a2f..4286ef0 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.h +++ b/Swiften/FileTransfer/IncomingFileTransfer.h @@ -16,6 +16,8 @@ namespace Swift { public: typedef boost::shared_ptr<IncomingFileTransfer> ref; - void accept(WriteBytestream::ref); + virtual ~IncomingFileTransfer(); + + virtual void accept(WriteBytestream::ref) = 0; }; } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp new file mode 100644 index 0000000..5535840 --- /dev/null +++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/FileTransfer/IncomingFileTransferManager.h> + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Elements/JingleDescription.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Elements/JingleIBBTransport.h> +#include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> + +namespace Swift { + +IncomingFileTransferManager::IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router) : jingleSessionManager(jingleSessionManager), router(router) { + jingleSessionManager->addIncomingSessionHandler(this); +} + +IncomingFileTransferManager::~IncomingFileTransferManager() { + jingleSessionManager->removeIncomingSessionHandler(this); +} + +bool IncomingFileTransferManager::handleIncomingJingleSession(IncomingJingleSession::ref session) { + JingleContent::ref content = session->getContentWithDescription<JingleFileTransferDescription>(); + if (content) { + // Check for supported transports + if (content->getTransport<JingleIBBTransport>()) { + IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(session); + onIncomingFileTransfer(transfer); + } + else { + session->terminate(JinglePayload::Reason::UnsupportedTransports); + } + return true; + } + else { + return false; + } +} + + +} diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h index 41499e5..a54b5cd 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.h +++ b/Swiften/FileTransfer/IncomingFileTransferManager.h @@ -8,11 +8,26 @@ #include <boost/shared_ptr.hpp> -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/Jingle/IncomingJingleSessionHandler.h> namespace Swift { - class IncomingFileTransferManager { + class IQRouter; + class JingleSessionManager; + + class IncomingFileTransferManager : public IncomingJingleSessionHandler { public: + IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router); + ~IncomingFileTransferManager(); + boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; + + private: + bool handleIncomingJingleSession(IncomingJingleSession::ref session); + + private: + JingleSessionManager* jingleSessionManager; + IQRouter* router; }; } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp new file mode 100644 index 0000000..cb2f65c --- /dev/null +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> + +namespace Swift { + +IncomingJingleFileTransfer::IncomingJingleFileTransfer(IncomingJingleSession::ref session) : session(session) { + +} + +void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) { + this->stream = stream; +} + +} diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h new file mode 100644 index 0000000..d69449e --- /dev/null +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -0,0 +1,27 @@ +/* + * 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/Jingle/IncomingJingleSession.h> +#include <Swiften/FileTransfer/IncomingFileTransfer.h> + +namespace Swift { + class IncomingJingleFileTransfer : public IncomingFileTransfer { + public: + typedef boost::shared_ptr<IncomingJingleFileTransfer> ref; + + IncomingJingleFileTransfer(IncomingJingleSession::ref session); + + virtual void accept(WriteBytestream::ref); + + private: + IncomingJingleSession::ref session; + WriteBytestream::ref stream; + }; +} diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.cpp b/Swiften/FileTransfer/OutgoingFileTransfer.cpp index 4fa8d94..8e6f839 100644 --- a/Swiften/FileTransfer/OutgoingFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransfer.cpp @@ -21,7 +21,7 @@ OutgoingFileTransfer::OutgoingFileTransfer(const String& id, const JID& from, co void OutgoingFileTransfer::start() { StreamInitiation::ref streamInitiation(new StreamInitiation()); streamInitiation->setID(id); - streamInitiation->setFileInfo(StreamInitiation::FileInfo(name, description, size)); + streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size)); //streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb"); StreamInitiationRequest::ref request = StreamInitiationRequest::create(to, streamInitiation, iqRouter); diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript index d36e029..9f3234f 100644 --- a/Swiften/FileTransfer/SConscript +++ b/Swiften/FileTransfer/SConscript @@ -3,6 +3,8 @@ Import("swiften_env") sources = [ "OutgoingFileTransfer.cpp", "IncomingFileTransfer.cpp", + "IncomingJingleFileTransfer.cpp", + "IncomingFileTransferManager.cpp", "ReadBytestream.cpp", "WriteBytestream.cpp", "FileReadBytestream.cpp", diff --git a/Swiften/Jingle/IncomingJingleSession.cpp b/Swiften/Jingle/IncomingJingleSession.cpp new file mode 100644 index 0000000..29155b8 --- /dev/null +++ b/Swiften/Jingle/IncomingJingleSession.cpp @@ -0,0 +1,15 @@ +/* + * 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/IncomingJingleSession.h> + +namespace Swift { + +IncomingJingleSession::IncomingJingleSession(const String& id, const std::vector<JingleContent::ref>& contents) : JingleSession(id, contents) { + +} + +} diff --git a/Swiften/Jingle/IncomingJingleSession.h b/Swiften/Jingle/IncomingJingleSession.h new file mode 100644 index 0000000..222100f --- /dev/null +++ b/Swiften/Jingle/IncomingJingleSession.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 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/Jingle/JingleSession.h> + +namespace Swift { + class IncomingJingleSession : public JingleSession { + public: + IncomingJingleSession(const String& id, const std::vector<JingleContent::ref>& contents); + + typedef boost::shared_ptr<IncomingJingleSession> ref; + }; +} diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.cpp b/Swiften/Jingle/IncomingJingleSessionHandler.cpp new file mode 100644 index 0000000..d38118c --- /dev/null +++ b/Swiften/Jingle/IncomingJingleSessionHandler.cpp @@ -0,0 +1,14 @@ +/* + * 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/IncomingJingleSessionHandler.h> + +namespace Swift { + +IncomingJingleSessionHandler::~IncomingJingleSessionHandler() { +} + +} diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.h b/Swiften/Jingle/IncomingJingleSessionHandler.h new file mode 100644 index 0000000..5bf9237 --- /dev/null +++ b/Swiften/Jingle/IncomingJingleSessionHandler.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Jingle/IncomingJingleSession.h> + +namespace Swift { + class IncomingJingleSessionHandler { + public: + virtual ~IncomingJingleSessionHandler(); + + virtual bool handleIncomingJingleSession(IncomingJingleSession::ref) = 0; + }; +} diff --git a/Swiften/Jingle/JingleResponder.cpp b/Swiften/Jingle/JingleResponder.cpp new file mode 100644 index 0000000..3dfc327 --- /dev/null +++ b/Swiften/Jingle/JingleResponder.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Jingle/JingleResponder.h> + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/Jingle/IncomingJingleSession.h> + +namespace Swift { + +JingleResponder::JingleResponder(JingleSessionManager* sessionManager, IQRouter* router) : SetResponder<JinglePayload>(router), sessionManager(sessionManager) { +} + +bool JingleResponder::handleSetRequest(const JID& from, const JID&, const String& id, boost::shared_ptr<JinglePayload> payload) { + if (payload->getAction() == JinglePayload::SessionInitiate) { + if (sessionManager->getSession(from, payload->getSessionID())) { + // TODO: Add tie-break error + sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); + } + else { + sendResponse(from, id, boost::shared_ptr<JinglePayload>()); + IncomingJingleSession::ref session = boost::make_shared<IncomingJingleSession>(id, payload->getContents()); + sessionManager->handleIncomingSession(from, session); + } + } + else { + JingleSession::ref session = sessionManager->getSession(from, payload->getSessionID()); + if (session) { + session->handleIncomingAction(payload); + sendResponse(from, id, boost::shared_ptr<JinglePayload>()); + } + else { + // TODO: Add jingle-specific error + sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + return true; +} + +} diff --git a/Swiften/Jingle/JingleResponder.h b/Swiften/Jingle/JingleResponder.h new file mode 100644 index 0000000..47dc90a --- /dev/null +++ b/Swiften/Jingle/JingleResponder.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Queries/SetResponder.h> +#include <Swiften/Elements/JinglePayload.h> + +namespace Swift { + class IQRouter; + class JingleSessionManager; + + class JingleResponder : public SetResponder<JinglePayload> { + public: + JingleResponder(JingleSessionManager* sessionManager, IQRouter* router); + + private: + virtual bool handleSetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr<JinglePayload> payload); + + private: + JingleSessionManager* sessionManager; + }; +} diff --git a/Swiften/Jingle/JingleSession.cpp b/Swiften/Jingle/JingleSession.cpp new file mode 100644 index 0000000..3dbb12a --- /dev/null +++ b/Swiften/Jingle/JingleSession.cpp @@ -0,0 +1,30 @@ +/* + * 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/JingleSession.h> + +#include <boost/smart_ptr/make_shared.hpp> + +namespace Swift { + +JingleSession::JingleSession(const String& id, const std::vector<JingleContent::ref>& contents) : id(id), contents(contents) { + +} + +JingleSession::~JingleSession() { +} + +void JingleSession::handleIncomingAction(JinglePayload::ref) { +} + +void JingleSession::terminate(JinglePayload::Reason::Type reason) { + JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, id); + payload->setReason(JinglePayload::Reason(reason)); + //onAction(payload) +} + + +} diff --git a/Swiften/Jingle/JingleSession.h b/Swiften/Jingle/JingleSession.h new file mode 100644 index 0000000..7ed86c2 --- /dev/null +++ b/Swiften/Jingle/JingleSession.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 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/boost_bsignals.h> +#include <Swiften/Base/String.h> +#include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Elements/JingleContent.h> +#include <Swiften/Base/foreach.h> + +namespace Swift { + class JingleSession { + friend class JingleResponder; + public: + typedef boost::shared_ptr<JingleSession> ref; + + JingleSession(const String& id, const std::vector<JingleContent::ref>& contents); + virtual ~JingleSession(); + + String getID() const { + return id; + } + + template<typename T> + JingleContent::ref getContentWithDescription() const { + foreach (JingleContent::ref content, contents) { + if (content->getDescription<T>()) { + return content; + } + } + return JingleContent::ref(); + } + + const std::vector<JingleContent::ref> getContents() const { + return contents; + } + + void terminate(JinglePayload::Reason::Type reason); + + private: + void handleIncomingAction(JinglePayload::ref); + + private: + String id; + std::vector<JingleContent::ref> contents; + }; +} diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp new file mode 100644 index 0000000..d8630cc --- /dev/null +++ b/Swiften/Jingle/JingleSessionManager.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/Jingle/JingleResponder.h> +#include <Swiften/Jingle/IncomingJingleSessionHandler.h> + +namespace Swift { + +JingleSessionManager::JingleSessionManager(IQRouter* router) : router(router) { + responder = new JingleResponder(this, router); +} + +JingleSessionManager::~JingleSessionManager() { + delete responder; +} + +JingleSession::ref JingleSessionManager::getSession(const JID& jid, const String& id) const { + SessionMap::const_iterator i = incomingSessions.find(JIDSession(jid, id)); + return i != incomingSessions.end() ? i->second : JingleSession::ref(); +} + +void JingleSessionManager::addIncomingSessionHandler(IncomingJingleSessionHandler* handler) { + incomingSessionHandlers.push_back(handler); +} + +void JingleSessionManager::removeIncomingSessionHandler(IncomingJingleSessionHandler* handler) { + incomingSessionHandlers.erase(std::remove(incomingSessionHandlers.begin(), incomingSessionHandlers.end(), handler), incomingSessionHandlers.end()); +} + +void JingleSessionManager::handleIncomingSession(const JID& from, IncomingJingleSession::ref session) { + incomingSessions.insert(std::make_pair(JIDSession(from, session->getID()), session)); + foreach (IncomingJingleSessionHandler* handler, incomingSessionHandlers) { + if (handler->handleIncomingJingleSession(session)) { + return; + } + } + // TODO: Finish session +} + + +} diff --git a/Swiften/Jingle/JingleSessionManager.h b/Swiften/Jingle/JingleSessionManager.h new file mode 100644 index 0000000..ea4199d --- /dev/null +++ b/Swiften/Jingle/JingleSessionManager.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 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 <map> + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Jingle/IncomingJingleSession.h> + +namespace Swift { + class IQRouter; + class JingleResponder; + class IncomingJingleSessionHandler; + + class JingleSessionManager { + friend class JingleResponder; + public: + JingleSessionManager(IQRouter* router); + ~JingleSessionManager(); + + JingleSession::ref getSession(const JID& jid, const String& id) const; + + void addIncomingSessionHandler(IncomingJingleSessionHandler* handler); + void removeIncomingSessionHandler(IncomingJingleSessionHandler* handler); + + protected: + void handleIncomingSession(const JID& from, IncomingJingleSession::ref); + + private: + IQRouter* router; + JingleResponder* responder; + std::vector<IncomingJingleSessionHandler*> incomingSessionHandlers; + struct JIDSession { + JIDSession(const JID& jid, const String& session) : jid(jid), session(session) {} + bool operator<(const JIDSession& o) const { + return jid == o.jid ? session < o.session : jid < o.jid; + } + JID jid; + String session; + }; + typedef std::map<JIDSession, JingleSession::ref> SessionMap; + SessionMap incomingSessions; + }; +} diff --git a/Swiften/Jingle/SConscript b/Swiften/Jingle/SConscript new file mode 100644 index 0000000..c1aadea --- /dev/null +++ b/Swiften/Jingle/SConscript @@ -0,0 +1,11 @@ +Import("swiften_env") + +sources = [ + "IncomingJingleSession.cpp", + "IncomingJingleSessionHandler.cpp", + "JingleSessionManager.cpp", + "JingleResponder.cpp", + "JingleSession.cpp", + ] + +swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.StaticObject(sources)) diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp index 6e1082c..bf36321 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp @@ -36,7 +36,7 @@ void StreamInitiationParser::handleStartElement(const String& element, const Str else if (level == PayloadLevel) { if (element == "file") { inFile = true; - currentFile = StreamInitiation::FileInfo(); + currentFile = StreamInitiationFileInfo(); currentFile.name = attributes.getAttribute("name"); try { currentFile.size = boost::lexical_cast<int>(attributes.getAttribute("size")); diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h index f01567e..7a44651 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h @@ -36,7 +36,7 @@ namespace Swift { FormParser* formParser; bool inFile; bool inFeature; - StreamInitiation::FileInfo currentFile; + StreamInitiationFileInfo currentFile; String currentText; }; } diff --git a/Swiften/SConscript b/Swiften/SConscript index c325d03..36ebd0c 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -151,6 +151,7 @@ if env["SCONS_STAGE"] == "build" : "EventLoop", "Parser", "JID", + "Jingle", "Disco", "VCards", "Network", diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp index 71702d0..0c7f593 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp @@ -35,7 +35,7 @@ String StreamInitiationSerializer::serializePayload(boost::shared_ptr<StreamInit siElement.setAttribute("profile", FILE_TRANSFER_NS); if (streamInitiation->getFileInfo()) { - StreamInitiation::FileInfo file = *streamInitiation->getFileInfo(); + StreamInitiationFileInfo file = *streamInitiation->getFileInfo(); boost::shared_ptr<XMLElement> fileElement(new XMLElement("file", "http://jabber.org/protocol/si/profile/file-transfer")); fileElement->setAttribute("name", file.name); if (file.size != -1) { diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp index 12c8485..e1a13b8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp @@ -21,7 +21,7 @@ class StreamInitiationSerializerTest : public CppUnit::TestFixture{ void testSerialize_Request() { StreamInitiationSerializer testling; boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); - StreamInitiation::FileInfo fileInfo("test.txt", "This is info about the file.", 1022); + StreamInitiationFileInfo fileInfo("test.txt", "This is info about the file.", 1022); streamInitiation->setID("a0"); streamInitiation->setFileInfo(fileInfo); streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); |